summaryrefslogtreecommitdiff
path: root/src/mesa/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/drivers')
-rw-r--r--src/mesa/drivers/dri/mga/Doxyfile234
-rw-r--r--src/mesa/drivers/dri/mga/Makefile.X1127
-rw-r--r--src/mesa/drivers/dri/mga/mga_texstate.c747
-rw-r--r--src/mesa/drivers/dri/mga/mga_xmesa.c356
-rw-r--r--src/mesa/drivers/dri/mga/mga_xmesa.h9
-rw-r--r--src/mesa/drivers/dri/mga/mgacontext.h193
-rw-r--r--src/mesa/drivers/dri/mga/mgadd.c92
-rw-r--r--src/mesa/drivers/dri/mga/mgadd.h1
-rw-r--r--src/mesa/drivers/dri/mga/mgaioctl.c127
-rw-r--r--src/mesa/drivers/dri/mga/mgaioctl.h7
-rw-r--r--src/mesa/drivers/dri/mga/mgapixel.c42
-rw-r--r--src/mesa/drivers/dri/mga/mgaregs.h14
-rw-r--r--src/mesa/drivers/dri/mga/mgarender.c5
-rw-r--r--src/mesa/drivers/dri/mga/mgaspan.c31
-rw-r--r--src/mesa/drivers/dri/mga/mgastate.c1297
-rw-r--r--src/mesa/drivers/dri/mga/mgastate.h5
-rw-r--r--src/mesa/drivers/dri/mga/mgatex.c904
-rw-r--r--src/mesa/drivers/dri/mga/mgatex.h13
-rw-r--r--src/mesa/drivers/dri/mga/mgatexmem.c616
-rw-r--r--src/mesa/drivers/dri/mga/mgatris.c85
-rw-r--r--src/mesa/drivers/dri/mga/mgatris.h9
-rw-r--r--src/mesa/drivers/dri/mga/mgavb.c23
-rw-r--r--src/mesa/drivers/dri/mga/server/mga_common.h2
-rw-r--r--src/mesa/drivers/dri/r128/Makefile.X11116
-rw-r--r--src/mesa/drivers/dri/r128/r128_context.c335
-rw-r--r--src/mesa/drivers/dri/r128/r128_context.h270
-rw-r--r--src/mesa/drivers/dri/r128/r128_dd.c148
-rw-r--r--src/mesa/drivers/dri/r128/r128_dd.h44
-rw-r--r--src/mesa/drivers/dri/r128/r128_ioctl.c812
-rw-r--r--src/mesa/drivers/dri/r128/r128_ioctl.h146
-rw-r--r--src/mesa/drivers/dri/r128/r128_lock.c123
-rw-r--r--src/mesa/drivers/dri/r128/r128_lock.h111
-rw-r--r--src/mesa/drivers/dri/r128/r128_screen.c357
-rw-r--r--src/mesa/drivers/dri/r128/r128_screen.h84
-rw-r--r--src/mesa/drivers/dri/r128/r128_span.c475
-rw-r--r--src/mesa/drivers/dri/r128/r128_span.h44
-rw-r--r--src/mesa/drivers/dri/r128/r128_state.c1239
-rw-r--r--src/mesa/drivers/dri/r128/r128_state.h54
-rw-r--r--src/mesa/drivers/dri/r128/r128_tex.c598
-rw-r--r--src/mesa/drivers/dri/r128/r128_tex.h88
-rw-r--r--src/mesa/drivers/dri/r128/r128_texmem.c302
-rw-r--r--src/mesa/drivers/dri/r128/r128_texobj.h69
-rw-r--r--src/mesa/drivers/dri/r128/r128_texstate.c652
-rw-r--r--src/mesa/drivers/dri/r128/r128_tris.c721
-rw-r--r--src/mesa/drivers/dri/r128/r128_tris.h48
-rw-r--r--src/mesa/drivers/dri/r128/r128_vb.c522
-rw-r--r--src/mesa/drivers/dri/r128/r128_vb.h74
-rw-r--r--src/mesa/drivers/dri/r128/server/r128.h566
-rw-r--r--src/mesa/drivers/dri/r128/server/r128_common.h169
-rw-r--r--src/mesa/drivers/dri/r128/server/r128_dri.c1165
-rw-r--r--src/mesa/drivers/dri/r128/server/r128_dri.h103
-rw-r--r--src/mesa/drivers/dri/r128/server/r128_macros.h135
-rw-r--r--src/mesa/drivers/dri/r128/server/r128_reg.h1431
-rw-r--r--src/mesa/drivers/dri/r128/server/r128_sarea.h195
-rw-r--r--src/mesa/drivers/dri/r128/server/r128_version.h60
-rw-r--r--src/mesa/drivers/dri/r200/Makefile.X1116
-rw-r--r--src/mesa/drivers/dri/r200/r200_context.c5
-rw-r--r--src/mesa/drivers/dri/r200/r200_context.h2
-rw-r--r--src/mesa/drivers/dri/r200/r200_ioctl.c6
-rw-r--r--src/mesa/drivers/dri/r200/r200_swtcl.c4
-rw-r--r--src/mesa/drivers/dri/r200/r200_tcl.c68
-rw-r--r--src/mesa/drivers/dri/radeon/Makefile.X11154
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_compat.c304
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_context.c598
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_context.h839
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_ioctl.c1191
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_ioctl.h188
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_lighting.c682
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_lock.c128
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_lock.h113
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_maos.c12
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_maos.h47
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_maos_arrays.c591
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_maos_vbtmp.h368
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_maos_verts.c335
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_sanity.c1043
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_sanity.h8
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_screen.c421
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_screen.h101
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_span.c415
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_span.h45
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_state.c2211
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_state.h77
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_state_init.c531
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_subset.h75
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_subset_bitmap.c197
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_subset_readpix.c246
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_subset_select.c998
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_subset_tex.c1018
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_subset_vtx.c989
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_swtcl.c1332
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_swtcl.h77
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_tcl.c527
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_tcl.h70
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_tex.c733
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_tex.h53
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_texmem.c378
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_texstate.c1628
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_vtxfmt.c1089
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_vtxfmt.h124
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_vtxfmt_c.c905
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_vtxfmt_sse.c232
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_vtxfmt_x86.c437
-rw-r--r--src/mesa/drivers/dri/radeon/server/radeon_common.h397
-rw-r--r--src/mesa/drivers/dri/radeon/server/radeon_dri.c6
-rw-r--r--src/mesa/drivers/dri/radeon/server/radeon_reg.h132
-rw-r--r--src/mesa/drivers/dri/radeon/server/radeon_sarea.h4
107 files changed, 35757 insertions, 2488 deletions
diff --git a/src/mesa/drivers/dri/mga/Doxyfile b/src/mesa/drivers/dri/mga/Doxyfile
new file mode 100644
index 0000000000..0d0c134a72
--- /dev/null
+++ b/src/mesa/drivers/dri/mga/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/mesa/drivers/dri/mga/Makefile.X11 b/src/mesa/drivers/dri/mga/Makefile.X11
index c69d6e5989..0dce6e7b1a 100644
--- a/src/mesa/drivers/dri/mga/Makefile.X11
+++ b/src/mesa/drivers/dri/mga/Makefile.X11
@@ -1,4 +1,4 @@
-# $Id: Makefile.X11,v 1.1 2003/08/06 18:01:13 keithw Exp $
+# $Id: Makefile.X11,v 1.2 2003/08/22 20:11:44 brianp Exp $
# Mesa 3-D graphics library
# Version: 5.0
@@ -6,8 +6,10 @@
TOP = ../../../../..
+default: linux-solo
+
SHARED_INCLUDES = $(INCLUDE_DIRS) -I. -I../common -Iserver
-MINIGLX_INCLUDES = -I$(TOP)/src/miniglx
+MINIGLX_INCLUDES = -I$(TOP)/src/glx/mini
DEFINES += \
-D_HAVE_SWRAST=1 \
@@ -16,24 +18,27 @@ DEFINES += \
-D_HAVE_CODEGEN=1 \
-D_HAVE_LIGHTING=1 \
-D_HAVE_TEXGEN=1 \
- -D_HAVE_USERCLIP=1
+ -D_HAVE_USERCLIP=1 \
+ -DGLX_DIRECT_RENDERING
MINIGLX_SOURCES = server/mga_dri.c
-DRIVER_SOURCES = mgabuffers.c \
- mgadd.c \
+DRIVER_SOURCES = mgadd.c \
mgaioctl.c \
mgarender.c \
mgastate.c \
mgatris.c \
- ../common/mm.c
+ ../common/mm.c \
+ ../common/utils.c \
+ ../common/texmem.c \
+ ../common/vblank.c
FULL_DRIVER_SOURCES = \
mgapixel.c \
mgaspan.c \
mgatex.c \
- mgatexcnv.c \
mgatexmem.c \
+ mga_texstate.c \
mgavb.c \
mga_xmesa.c
@@ -54,7 +59,7 @@ WINOBJ=$(MESABUILDDIR)/dri/dri.a
WINLIB=
else
WINOBJ=
-WINLIB=-L$(MESA)/src/miniglx
+WINLIB=-L$(MESA)/src/glx/mini
endif
ASM_SOURCES =
@@ -87,7 +92,7 @@ INCLUDE_DIRS = \
##### TARGETS #####
-targets: mga_dri.so
+targets: depend mga_dri.so
mga_dri.so: $(OBJECTS) $(MESA_MODULES) $(WINOBJ) Makefile.X11
rm -f $@ && gcc -o $@ -shared $(OBJECTS) $(MESA_MODULES) $(WINOBJ) $(WINLIB) -lc -lm
@@ -96,7 +101,7 @@ mga_dri.so: $(OBJECTS) $(MESA_MODULES) $(WINOBJ) Makefile.X11
# Run 'make -f Makefile.X11 dep' to update the dependencies if you change
# what's included by any source file.
-dep: $(C_SOURCES) $(ASM_SOURCES)
+depend: $(C_SOURCES) $(ASM_SOURCES)
makedepend -fdepend -Y $(SHARED_INCLUDES) \
$(C_SOURCES) $(ASM_SOURCES)
@@ -108,7 +113,7 @@ tags:
# Remove .o and backup files
clean:
- -rm -f *.o *~ *.o *~ *.so
+ -rm -f *.o *~ *.o *~ *.so server/*.o
include $(TOP)/Make-config
diff --git a/src/mesa/drivers/dri/mga/mga_texstate.c b/src/mesa/drivers/dri/mga/mga_texstate.c
new file mode 100644
index 0000000000..fc1406cab9
--- /dev/null
+++ b/src/mesa/drivers/dri/mga/mga_texstate.c
@@ -0,0 +1,747 @@
+/*
+ * 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 "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 | TMC_takey_1 | TMC_tamask_0,
+ [MESA_FORMAT_RGB565] = TMC_tformat_tw16 | TMC_takey_1 | TMC_tamask_0,
+ [MESA_FORMAT_ARGB4444] = TMC_tformat_tw12 | TMC_takey_1 | TMC_tamask_0,
+ [MESA_FORMAT_ARGB1555] = TMC_tformat_tw15 | TMC_takey_1 | TMC_tamask_0,
+ [MESA_FORMAT_CI8] = TMC_tformat_tw8 | TMC_takey_1 | TMC_tamask_0,
+ [MESA_FORMAT_YCBCR] = TMC_tformat_tw422uyvy | TMC_takey_1 | TMC_tamask_0,
+ [MESA_FORMAT_YCBCR_REV] = TMC_tformat_tw422 | TMC_takey_1 | TMC_tamask_0,
+};
+#endif
+
+static void
+mgaSetTexImages( mgaContextPtr mmesa,
+ const struct gl_texture_object * tObj )
+{
+ mgaTextureObjectPtr t = (mgaTextureObjectPtr) tObj->DriverData;
+ struct gl_texture_image *baseImage = tObj->Image[ tObj->BaseLevel ];
+ GLint totalSize;
+ GLint width, height;
+ GLint i;
+ GLint firstLevel, lastLevel, 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_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 */
+
+ if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) {
+ /* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL.
+ */
+
+ firstLevel = lastLevel = tObj->BaseLevel;
+ } else {
+ /* Compute which mipmap levels we really want to send to the hardware.
+ * This depends on the base image size, GL_TEXTURE_MIN_LOD,
+ * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
+ * Yes, this looks overly complicated, but it's all needed.
+ */
+
+ firstLevel = tObj->BaseLevel + (GLint)(tObj->MinLod + 0.5);
+ firstLevel = MAX2(firstLevel, tObj->BaseLevel);
+ lastLevel = tObj->BaseLevel + (GLint)(tObj->MaxLod + 0.5);
+ lastLevel = MAX2(lastLevel, tObj->BaseLevel);
+ lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2);
+ lastLevel = MIN2(lastLevel, tObj->MaxLevel);
+ lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */
+ }
+
+ log2Width = tObj->Image[firstLevel]->WidthLog2;
+ log2Height = tObj->Image[firstLevel]->HeightLog2;
+ width = tObj->Image[firstLevel]->Width;
+ height = tObj->Image[firstLevel]->Height;
+
+ numLevels = MIN2( lastLevel - 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[i+firstLevel];
+
+ if ( (texImage == NULL)
+ || ((i != 0)
+ && ((texImage->Width < 8) || (texImage->Height < 8))) ) {
+ break;
+ }
+
+ t->offsets[i] = totalSize;
+ t->base.dirty_images[0] |= (1<<i);
+
+ totalSize += ((MAX2( texImage->Width, 8 ) *
+ MAX2( texImage->Height, 8 ) *
+ baseImage->TexFormat->TexelBytes) + 31) & ~31;
+ }
+
+ numLevels = i;
+ lastLevel = firstLevel + numLevels - 1;
+
+ /* save these values */
+ t->base.firstLevel = firstLevel;
+ t->base.lastLevel = lastLevel;
+
+ 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 |= (width & (2048 - 1)) << TMC_tpitchext_SHIFT;
+
+
+ /* G400 specifies the number of mip levels in a strange way. Since there
+ * are up to 12 levels, it requires 4 bits. Three of the bits are at the
+ * high end of TEXFILTER. The other bit is in the middle. Weird.
+ */
+
+ t->setup.texfilter &= TF_mapnb_MASK & TF_mapnbhigh_MASK & TF_reserved_MASK;
+ t->setup.texfilter |= (((numLevels-1) & 0x07) << (TF_mapnb_SHIFT));
+ t->setup.texfilter |= (((numLevels-1) & 0x08) << (TF_mapnbhigh_SHIFT - 3));
+
+ /* 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 )
+{
+ struct gl_texture_object *tObj = ctx->Texture.Unit[0]._Current;
+ mgaTextureObjectPtr t;
+
+ if (!tObj || !tObj->DriverData)
+ return;
+
+ t = (mgaTextureObjectPtr)tObj->DriverData;
+
+ t->setup.texctl2 &= ~TMC_decalblend_enable;
+
+ switch (ctx->Texture.Unit[0].EnvMode) {
+ case GL_REPLACE:
+ t->setup.texctl &= ~TMC_tmodulate_enable;
+ break;
+ case GL_MODULATE:
+ t->setup.texctl |= TMC_tmodulate_enable;
+ break;
+ case GL_DECAL:
+ t->setup.texctl &= ~TMC_tmodulate_enable;
+ t->setup.texctl2 |= TMC_decalblend_enable;
+ break;
+ case GL_BLEND:
+ FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE );
+ break;
+ default:
+ break;
+ }
+}
+
+
+#define MGA_DISABLE 0
+#define MGA_REPLACE 1
+#define MGA_MODULATE 2
+#define MGA_DECAL 3
+#define MGA_BLEND 4
+#define MGA_ADD 5
+#define MGA_MAX_COMBFUNC 6
+
+static const GLuint g400_color_combine[][MGA_MAX_COMBFUNC] =
+{
+ /* Unit 0:
+ */
+ {
+ /* Disable combiner stage
+ */
+ (0),
+
+ /* GL_REPLACE
+ */
+ (TD0_color_sel_arg1 |
+ TD0_alpha_arg2_diffuse |
+ TD0_alpha_sel_arg2 ),
+
+ /* GL_MODULATE
+ */
+ (TD0_color_arg2_diffuse |
+ TD0_color_sel_mul |
+ TD0_alpha_arg2_diffuse |
+ TD0_alpha_sel_mul),
+
+ /* GL_DECAL
+ */
+ (TD0_color_sel_arg1 |
+ TD0_alpha_arg2_diffuse |
+ TD0_alpha_sel_arg2),
+
+ /* GL_BLEND
+ */
+ (0),
+
+ /* GL_ADD
+ */
+ (TD0_color_arg2_diffuse |
+ TD0_color_add_add |
+ TD0_color_sel_add |
+ TD0_alpha_arg2_diffuse |
+ TD0_alpha_sel_mul),
+ },
+
+ /* Unit 1:
+ */
+ {
+ /* Disable combiner stage
+ */
+ (0),
+
+ /* GL_REPLACE
+ */
+ (TD0_color_sel_arg1 |
+ TD0_alpha_arg2_diffuse |
+ TD0_alpha_sel_arg2 ),
+
+ /* GL_MODULATE
+ */
+ (TD0_color_arg2_prevstage |
+ TD0_color_alpha_prevstage |
+ TD0_color_sel_mul |
+ TD0_alpha_arg2_prevstage |
+ TD0_alpha_sel_mul),
+
+ /* GL_DECAL
+ */
+ (TD0_color_sel_arg1 |
+ TD0_alpha_arg2_prevstage |
+ TD0_alpha_sel_arg2 ),
+
+ /* GL_BLEND
+ */
+ (0),
+
+ /* GL_ADD
+ */
+ (TD0_color_arg2_prevstage |
+ TD0_color_alpha_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:
+ */
+ {
+ /* Disable combiner stage
+ */
+ (0),
+
+ /* GL_REPLACE
+ */
+ (TD0_color_sel_arg2 |
+ TD0_color_arg2_diffuse |
+ TD0_alpha_sel_arg1 ),
+
+ /* GL_MODULATE
+ * FIXME: Is this correct?
+ */
+ (TD0_color_arg2_diffuse |
+ TD0_color_sel_mul |
+ TD0_alpha_arg2_diffuse |
+ TD0_alpha_sel_mul),
+
+ /* GL_DECAL
+ */
+ (TD0_color_arg2_diffuse |
+ TD0_color_sel_arg2 |
+ TD0_alpha_arg2_diffuse |
+ TD0_alpha_sel_arg2),
+
+ /* GL_BLEND
+ */
+ (TD0_color_arg2_diffuse |
+ TD0_color_sel_mul |
+ TD0_alpha_arg2_diffuse |
+ TD0_alpha_sel_mul),
+
+ /* GL_ADD
+ */
+ (TD0_color_arg2_diffuse |
+ TD0_color_sel_mul |
+ TD0_alpha_arg2_diffuse |
+ TD0_alpha_sel_mul),
+ },
+
+ /* Unit 1:
+ */
+ {
+ /* Disable combiner stage
+ */
+ (0),
+
+ /* GL_REPLACE
+ */
+ (TD0_color_sel_arg2 |
+ TD0_color_arg2_diffuse |
+ TD0_alpha_sel_arg1 ),
+
+ /* GL_MODULATE
+ * FIXME: Is this correct?
+ */
+ (TD0_color_arg2_prevstage |
+ TD0_color_alpha_prevstage |
+ TD0_color_sel_mul |
+ TD0_alpha_arg2_prevstage |
+ TD0_alpha_sel_mul),
+
+ /* GL_DECAL
+ */
+ (TD0_color_arg2_prevstage |
+ TD0_color_sel_arg2 |
+ TD0_alpha_arg2_prevstage |
+ TD0_alpha_sel_arg2),
+
+ /* GL_BLEND
+ */
+ (TD0_color_arg2_diffuse |
+ TD0_color_sel_mul |
+ TD0_alpha_arg2_diffuse |
+ TD0_alpha_sel_mul),
+
+ /* GL_ADD
+ */
+ (TD0_color_arg2_prevstage |
+ TD0_color_sel_mul |
+ TD0_alpha_arg2_prevstage |
+ TD0_alpha_sel_mul),
+ },
+};
+
+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);
+ GLenum format;
+
+ if ( tObj != ctx->Texture.Unit[source].Current2D || !tObj )
+ return;
+
+ format = tObj->Image[tObj->BaseLevel]->Format;
+
+ switch (ctx->Texture.Unit[source].EnvMode) {
+ case GL_REPLACE:
+ if (format == GL_RGB || format == GL_LUMINANCE) {
+ *reg = g400_color_combine[unit][MGA_REPLACE];
+ }
+ else if (format == GL_ALPHA) {
+ *reg = g400_alpha_combine[unit][MGA_REPLACE];
+ }
+ else {
+ *reg = (TD0_color_sel_arg1 |
+ TD0_alpha_sel_arg1 );
+ }
+ break;
+
+ case GL_MODULATE:
+ *reg = g400_color_combine[unit][MGA_MODULATE];
+ break;
+ case GL_DECAL:
+ if (format == GL_RGB) {
+ *reg = g400_color_combine[unit][MGA_DECAL];
+ }
+ else if ( format == GL_RGBA ) {
+#if 0
+ if (unit == 0) {
+ /* this doesn't work */
+ *reg = (TD0_color_arg2_diffuse |
+ TD0_color_alpha_currtex |
+ TD0_color_alpha2inv_enable |
+ TD0_color_arg2mul_alpha2 |
+ TD0_color_arg1mul_alpha1 |
+ TD0_color_blend_enable |
+ TD0_color_arg1add_mulout |
+ TD0_color_arg2add_mulout |
+ TD0_color_add_add |
+ TD0_color_sel_mul |
+ TD0_alpha_arg2_diffuse |
+ TD0_alpha_sel_arg2 );
+ }
+ else {
+ *reg = (TD0_color_arg2_prevstage |
+ TD0_color_alpha_currtex |
+ TD0_color_alpha2inv_enable |
+ TD0_color_arg2mul_alpha2 |
+ TD0_color_arg1mul_alpha1 |
+ TD0_color_add_add |
+ TD0_color_sel_add |
+ TD0_alpha_arg2_prevstage |
+ TD0_alpha_sel_arg2 );
+ }
+#else
+ /* s/w fallback, pretty sure we can't do in h/w */
+ FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE );
+ if ( MGA_DEBUG & DEBUG_VERBOSE_FALLBACK )
+ fprintf( stderr, "FALLBACK: GL_DECAL RGBA texture, unit=%d\n",
+ unit );
+#endif
+ }
+ else {
+ *reg = g400_alpha_combine[unit][MGA_DECAL];
+ }
+ break;
+
+ case GL_ADD:
+ if (format == GL_INTENSITY) {
+ 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);
+ }
+ }
+ else if (format == GL_ALPHA) {
+ *reg = g400_alpha_combine[unit][MGA_ADD];
+ }
+ else {
+ *reg = g400_color_combine[unit][MGA_ADD];
+ }
+ break;
+
+ case GL_BLEND:
+ if (format == GL_ALPHA) {
+ *reg = g400_alpha_combine[unit][MGA_BLEND];
+ }
+ else {
+ FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE );
+ if ( MGA_DEBUG & DEBUG_VERBOSE_FALLBACK )
+ fprintf( stderr, "FALLBACK: GL_BLEND envcolor=0x%08x\n",
+ mmesa->envcolor );
+
+ /* Do singletexture GL_BLEND with 'all ones' env-color
+ * by using both texture units. Multitexture gl_blend
+ * is a fallback.
+ */
+ if (unit == 0) {
+ /* Part 1: R1 = Rf ( 1 - Rt )
+ * A1 = Af At
+ */
+ *reg = ( TD0_color_arg2_diffuse |
+ TD0_color_arg1_inv_enable |
+ TD0_color_sel_mul |
+ TD0_alpha_arg2_diffuse |
+ TD0_alpha_sel_arg1);
+ } else {
+ /* Part 2: R2 = R1 + Rt
+ * A2 = A1
+ */
+ *reg = ( TD0_color_arg2_prevstage |
+ TD0_color_add_add |
+ TD0_color_sel_add |
+ TD0_alpha_arg2_prevstage |
+ TD0_alpha_sel_arg2);
+ }
+ }
+ 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->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_2d( 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[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->setup.texctl2 &= TMC_dualtex_MASK;
+ if (ctx->Texture._EnabledUnits == 0x03) {
+ t->setup.texctl2 |= TMC_dualtex_enable;
+ }
+
+ /* 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 {
+ mmesa->hw.alpha_sel = 0;
+ switch (ctx->Texture.Unit[0].EnvMode) {
+ case GL_DECAL:
+ mmesa->hw.alpha_sel |= AC_alphasel_diffused;
+ case GL_REPLACE:
+ mmesa->hw.alpha_sel |= AC_alphasel_fromtex;
+ break;
+ case GL_BLEND:
+ case GL_MODULATE:
+ mmesa->hw.alpha_sel |= AC_alphasel_modulated;
+ break;
+ default:
+ break;
+ }
+
+ mgaUpdateTextureEnvG200( ctx, unit );
+ }
+
+ mmesa->setup.dwgctl &= DC_opcod_MASK;
+ mmesa->setup.dwgctl |= DC_opcod_texture_trap;
+ mmesa->dirty |= MGA_UPLOAD_CONTEXT | (MGA_UPLOAD_TEX0 << unit);
+
+ FALLBACK( ctx, MGA_FALLBACK_BORDER_MODE, t->border_fallback );
+ return !t->border_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) {
+ return(enable_tex_2d( 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;
+
+
+ /* 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 );
+
+ /* FIXME: I believe that ChooseVertexState should be called here instead of
+ * FIXME: in mgaDDValidateState.
+ */
+}
diff --git a/src/mesa/drivers/dri/mga/mga_xmesa.c b/src/mesa/drivers/dri/mga/mga_xmesa.c
index de1bcc2a0f..16dc349cac 100644
--- a/src/mesa/drivers/dri/mga/mga_xmesa.c
+++ b/src/mesa/drivers/dri/mga/mga_xmesa.c
@@ -1,4 +1,4 @@
-/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mga_xmesa.c,v 1.19 2003/03/26 20:43:49 tsi Exp $ */
+/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mga_xmesa.c,v 1.18 2002/12/16 16:18:52 dawes Exp $ */
/*
* Copyright 2000-2001 VA Linux Systems, Inc.
* All Rights Reserved.
@@ -26,15 +26,14 @@
* Keith Whitwell <keith@tungstengraphics.com>
*/
-#include <stdio.h>
+#ifdef GLX_DIRECT_RENDERING
#include "mga_common.h"
#include "mga_xmesa.h"
#include "context.h"
#include "matrix.h"
-/*#include "mmath.h"*/
#include "simple_list.h"
-/*#include "mem.h"*/
+#include "imports.h"
#include "swrast/swrast.h"
#include "swrast_setup/swrast_setup.h"
@@ -50,26 +49,23 @@
#include "mgaioctl.h"
#include "mgatris.h"
#include "mgavb.h"
-#include "mgabuffers.h"
#include "mgapixel.h"
-
#include "mga_xmesa.h"
-
#include "mga_dri.h"
+#include "utils.h"
+#include "vblank.h"
+#include "dri_util.h"
+#ifndef _SOLO
+#include "glxextensions.h"
+#endif
+
#ifndef MGA_DEBUG
-int MGA_DEBUG = (0
-/* | DEBUG_ALWAYS_SYNC */
-/* | DEBUG_VERBOSE_MSG */
-/* | DEBUG_VERBOSE_LRU */
-/* | DEBUG_VERBOSE_DRI */
-/* | DEBUG_VERBOSE_IOCTL */
-/* | DEBUG_VERBOSE_2D */
-/* | DEBUG_VERBOSE_FALLBACK */
- );
+int MGA_DEBUG = 0;
#endif
+static int getSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo );
static GLboolean
mgaInitDriver(__DRIscreenPrivate *sPriv)
@@ -77,16 +73,8 @@ mgaInitDriver(__DRIscreenPrivate *sPriv)
mgaScreenPrivate *mgaScreen;
MGADRIPtr serverInfo = (MGADRIPtr)sPriv->pDevPriv;
- if (MGA_DEBUG&DEBUG_VERBOSE_DRI)
- fprintf(stderr, "mgaInitDriver\n");
-
- /* Check that the DRM driver version is compatible */
- if (sPriv->drmMajor != 3 ||
- sPriv->drmMinor < 0) {
- __driUtilMessage("MGA DRI driver expected DRM driver version 3.0.x but got version %d.%d.%d", sPriv->drmMajor, sPriv->drmMinor, sPriv->drmPatch);
+ if ( ! driCheckDriDdxDrmVersions( sPriv, "MGA", 4, 0, 1, 0, 3, 0 ) )
return GL_FALSE;
- }
-
/* Allocate the private area */
mgaScreen = (mgaScreenPrivate *)MALLOC(sizeof(mgaScreenPrivate));
@@ -103,21 +91,37 @@ mgaInitDriver(__DRIscreenPrivate *sPriv)
drmMGAGetParam gp;
gp.param = MGA_PARAM_IRQ_NR;
- gp.value = (int *) &mgaScreen->irq;
+ gp.value = &mgaScreen->irq;
ret = drmCommandWriteRead( sPriv->fd, DRM_MGA_GETPARAM,
&gp, sizeof(gp));
if (ret) {
fprintf(stderr, "drmMgaGetParam (MGA_PARAM_IRQ_NR): %d\n", ret);
- FREE(mgaScreen);
+ free(mgaScreen);
sPriv->private = NULL;
return GL_FALSE;
}
}
+ mgaScreen->linecomp_sane = (sPriv->ddxMajor > 1) || (sPriv->ddxMinor > 1)
+ || ((sPriv->ddxMinor == 1) && (sPriv->ddxPatch > 0));
+#ifndef _SOLO
+ if ( ! mgaScreen->linecomp_sane ) {
+ PFNGLXDISABLEEXTENSIONPROC glx_disable_extension;
+
+ glx_disable_extension = (PFNGLXDISABLEEXTENSIONPROC)
+ glXGetProcAddress( "__glXDisableExtension" );
+
+ if ( glx_disable_extension != NULL ) {
+ (*glx_disable_extension)( "GLX_SGI_swap_control" );
+ (*glx_disable_extension)( "GLX_SGI_video_sync" );
+ (*glx_disable_extension)( "GLX_MESA_swap_control" );
+ }
+ }
+#endif
if (serverInfo->chipset != MGA_CARD_TYPE_G200 &&
serverInfo->chipset != MGA_CARD_TYPE_G400) {
- FREE(mgaScreen);
+ free(mgaScreen);
sPriv->private = NULL;
__driUtilMessage("Unrecognized chipset");
return GL_FALSE;
@@ -164,7 +168,7 @@ mgaInitDriver(__DRIscreenPrivate *sPriv)
mgaScreen->agp.size,
(drmAddress *)&mgaScreen->agp.map) != 0)
{
- Xfree(mgaScreen);
+ free(mgaScreen);
sPriv->private = NULL;
__driUtilMessage("Couldn't map agp region");
return GL_FALSE;
@@ -210,7 +214,7 @@ mgaInitDriver(__DRIscreenPrivate *sPriv)
mgaScreen->bufs = drmMapBufs(sPriv->fd);
if (!mgaScreen->bufs) {
/*drmUnmap(mgaScreen->agp_tex.map, mgaScreen->agp_tex.size);*/
- FREE(mgaScreen);
+ free(mgaScreen);
sPriv->private = NULL;
__driUtilMessage("Couldn't map dma buffers");
return GL_FALSE;
@@ -254,12 +258,63 @@ static const struct gl_pipeline_stage *mga_pipeline[] = {
};
+static const char * const g400_extensions[] =
+{
+ "GL_ARB_multitexture",
+ "GL_ARB_texture_env_add",
+ "GL_EXT_texture_env_add",
+ "GL_EXT_texture_edge_clamp",
+ "GL_SGIS_texture_edge_clamp",
+#if defined (MESA_packed_depth_stencil)
+ "GL_MESA_packed_depth_stencil",
+#endif
+ NULL
+};
+
+static const char * const card_extensions[] =
+{
+ "GL_ARB_multisample",
+ "GL_ARB_texture_compression",
+ "GL_EXT_fog_coord",
+ /* paletted_textures currently doesn't work, but we could fix them later */
+#if 0
+ "GL_EXT_shared_texture_palette",
+ "GL_EXT_paletted_texture",
+#endif
+ "GL_EXT_secondary_color",
+ "GL_EXT_stencil_wrap",
+ "GL_MESA_ycbcr_texture",
+ "GL_SGIS_generate_mipmap",
+ "GL_SGIS_texture_lod",
+ 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 int
+get_ust_nop( uint64_t * ust )
+{
+ *ust = 1;
+ return 0;
+}
+
+
static GLboolean
mgaCreateContext( const __GLcontextModes *mesaVis,
__DRIcontextPrivate *driContextPriv,
void *sharedContextPrivate )
{
int i;
+ unsigned maxlevels;
GLcontext *ctx, *shareCtx;
mgaContextPtr mmesa;
__DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
@@ -281,7 +336,7 @@ mgaCreateContext( const __GLcontextModes *mesaVis,
shareCtx = ((mgaContextPtr) sharedContextPrivate)->glCtx;
else
shareCtx = NULL;
- mmesa->glCtx = _mesa_create_context(mesaVis, shareCtx, mmesa, GL_TRUE);
+ mmesa->glCtx = _mesa_create_context(mesaVis, shareCtx, (void *) mmesa, GL_TRUE);
if (!mmesa->glCtx) {
FREE(mmesa);
return GL_FALSE;
@@ -298,13 +353,20 @@ mgaCreateContext( const __GLcontextModes *mesaVis,
mmesa->sarea = (void *)saPriv;
mmesa->glBuffer = NULL;
- make_empty_list(&mmesa->SwappedOut);
-
- mmesa->lastTexHeap = mgaScreen->texVirtual[MGA_AGP_HEAP] ? 2 : 1;
-
- for (i = 0 ; i < mmesa->lastTexHeap ; i++) {
- mmesa->texHeap[i] = mmInit( 0, mgaScreen->textureSize[i]);
- make_empty_list(&mmesa->TexObjList[i]);
+ (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,
+ 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
@@ -312,22 +374,26 @@ mgaCreateContext( const __GLcontextModes *mesaVis,
* on the card at once.
*/
ctx = mmesa->glCtx;
- {
- int nr = 2;
-
- if (mgaScreen->chipset == MGA_CARD_TYPE_G200)
- nr = 1;
-
- if (mgaScreen->textureSize[0] < nr*1024*1024) {
- ctx->Const.MaxTextureLevels = 9;
- } else if (mgaScreen->textureSize[0] < nr*4*1024*1024) {
- ctx->Const.MaxTextureLevels = 10;
- } else {
- ctx->Const.MaxTextureLevels = 11;
- }
+ if ( mgaScreen->chipset == MGA_CARD_TYPE_G200 ) {
+ ctx->Const.MaxTextureUnits = 1;
+ maxlevels = G200_TEX_MAXLEVELS;
- ctx->Const.MaxTextureUnits = nr;
}
+ else {
+ ctx->Const.MaxTextureUnits = 2;
+ maxlevels = G400_TEX_MAXLEVELS;
+ }
+
+ driCalculateMaxTextureLevels( mmesa->texture_heaps,
+ mmesa->nr_heaps,
+ & ctx->Const,
+ 4,
+ 11, /* max 2D texture size is 1024x1024 */
+ 0, /* 3D textures unsupported. */
+ 0, /* cube textures unsupported. */
+ 0, /* texture rectangles unsupported. */
+ maxlevels,
+ GL_FALSE );
ctx->Const.MinLineWidth = 1.0;
ctx->Const.MinLineWidthAA = 1.0;
@@ -335,6 +401,7 @@ mgaCreateContext( const __GLcontextModes *mesaVis,
ctx->Const.MaxLineWidthAA = 10.0;
ctx->Const.LineWidthGranularity = 1.0;
+ mmesa->default32BitTextures = (mesaVis->rgbBits >= 24);
mmesa->hw_stencil = mesaVis->stencilBits && mesaVis->depthBits == 24;
switch (mesaVis->depthBits) {
@@ -361,7 +428,6 @@ mgaCreateContext( const __GLcontextModes *mesaVis,
mmesa->haveHwStipple = GL_FALSE;
mmesa->RenderIndex = -1; /* impossible value */
- mmesa->new_state = ~0;
mmesa->dirty = ~0;
mmesa->vertex_format = 0;
mmesa->CurrentTexObj[0] = 0;
@@ -395,7 +461,11 @@ mgaCreateContext( const __GLcontextModes *mesaVis,
ctx->DriverCtx = (void *) mmesa;
mmesa->glCtx = ctx;
- mgaDDExtensionsInit( ctx );
+ driInitExtensions( ctx, card_extensions, GL_FALSE );
+
+ if (MGA_IS_G400(MGA_CONTEXT(ctx))) {
+ driInitExtensions( ctx, g400_extensions, GL_FALSE );
+ }
mgaDDInitStateFuncs( ctx );
mgaDDInitTextureFuncs( ctx );
@@ -410,6 +480,24 @@ mgaCreateContext( const __GLcontextModes *mesaVis,
driContextPriv->driverPrivate = (void *) mmesa;
+#if DO_DEBUG
+ MGA_DEBUG = driParseDebugString( getenv( "MGA_DEBUG" ),
+ debug_control );
+#endif
+
+ mmesa->vblank_flags = ((mmesa->mgaScreen->irq == 0)
+ || !mmesa->mgaScreen->linecomp_sane)
+ ? VBLANK_FLAG_NO_IRQ : driGetDefaultVBlankFlags();
+#ifndef _SOLO
+ mmesa->get_ust = (PFNGLXGETUSTPROC) glXGetProcAddress( "__glXGetUST" );
+ if ( mmesa->get_ust == NULL )
+#endif
+ {
+ mmesa->get_ust = get_ust_nop;
+ }
+
+ (*mmesa->get_ust)( & mmesa->swap_ust );
+
return GL_TRUE;
}
@@ -419,10 +507,15 @@ mgaDestroyContext(__DRIcontextPrivate *driContextPriv)
mgaContextPtr mmesa = (mgaContextPtr) driContextPriv->driverPrivate;
if (MGA_DEBUG&DEBUG_VERBOSE_DRI)
- fprintf(stderr, "mgaDestroyContext\n");
+ 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 );
_ac_DestroyContext( mmesa->glCtx );
@@ -433,9 +526,27 @@ mgaDestroyContext(__DRIcontextPrivate *driContextPriv)
/* free the Mesa context */
mmesa->glCtx->DriverCtx = NULL;
_mesa_destroy_context(mmesa->glCtx);
- /* free the mga context */
+
+ if ( release_texture_heaps ) {
+ /* This share group is about to go away, free our private
+ * texture object data.
+ */
+ int i;
+
+ assert( is_empty_list( & mmesa->swapped ) );
+
+ for ( i = 0 ; i < mmesa->nr_heaps ; i++ ) {
+ driDestroyTextureHeap( mmesa->texture_heaps[ i ] );
+ mmesa->texture_heaps[ i ] = NULL;
+ }
+ }
+
FREE(mmesa);
}
+
+ if (MGA_DEBUG&DEBUG_VERBOSE_DRI)
+ fprintf( stderr, "[%s:%d] mgaDestroyContext done\n",
+ __FILE__, __LINE__ );
}
@@ -482,13 +593,7 @@ mgaUnbindContext(__DRIcontextPrivate *driContextPriv)
}
static GLboolean
-mgaOpenFullScreen(__DRIcontextPrivate *driContextPriv)
-{
- return GL_TRUE;
-}
-
-static GLboolean
-mgaCloseFullScreen(__DRIcontextPrivate *driContextPriv)
+mgaOpenCloseFullScreen(__DRIcontextPrivate *driContextPriv)
{
return GL_TRUE;
}
@@ -505,8 +610,6 @@ mgaMakeCurrent(__DRIcontextPrivate *driContextPriv,
__DRIdrawablePrivate *driDrawPriv,
__DRIdrawablePrivate *driReadPriv)
{
- fprintf(stderr, "%s\n", __FUNCTION__);
-
if (driContextPriv) {
mgaContextPtr mmesa = (mgaContextPtr) driContextPriv->driverPrivate;
@@ -532,6 +635,7 @@ mgaMakeCurrent(__DRIcontextPrivate *driContextPriv,
return GL_TRUE;
}
+
void mgaGetLock( mgaContextPtr mmesa, GLuint flags )
{
__DRIdrawablePrivate *dPriv = mmesa->driDrawable;
@@ -539,29 +643,10 @@ void mgaGetLock( mgaContextPtr mmesa, GLuint flags )
int me = mmesa->hHWContext;
int i;
- fprintf(stderr, "%s\n", __FUNCTION__);
-
drmGetLock(mmesa->driFd, mmesa->hHWContext, flags);
-
- fprintf(stderr,
- "mmesa->lastStamp %d dpriv->lastStamp %d *(dpriv->pStamp) %d\n",
- mmesa->lastStamp,
- dPriv->lastStamp,
- *(dPriv->pStamp));
-
- /* The window might have moved, so we might need to get new clip
- * rects.
- *
- * NOTE: This releases and regrabs the hw lock to allow the X server
- * to respond to the DRI protocol request for new drawable info.
- * Since the hardware state depends on having the latest drawable
- * clip rects, all state checking must be done _after_ this call.
- */
- DRI_VALIDATE_DRAWABLE_INFO( sPriv, dPriv );
- if ( mmesa->lastStamp == 0 ||
- mmesa->lastStamp != dPriv->lastStamp ) {
- mmesa->lastStamp = dPriv->lastStamp;
+ if (*(dPriv->pStamp) != mmesa->lastStamp) {
+ mmesa->lastStamp = *(dPriv->pStamp);
mmesa->SetupNewInputs |= VERT_BIT_CLIP;
mmesa->dirty_cliprects = (MGA_FRONT|MGA_BACK);
mgaUpdateRects( mmesa, (MGA_FRONT|MGA_BACK) );
@@ -569,7 +654,7 @@ void mgaGetLock( mgaContextPtr mmesa, GLuint flags )
mmesa->dirty |= MGA_UPLOAD_CONTEXT | MGA_UPLOAD_CLIPRECTS;
- mmesa->sarea->dirty |= MGA_UPLOAD_CONTEXT;
+ mmesa->sarea->dirty |= MGA_UPLOAD_CONTEXT;
if (sarea->ctxOwner != me) {
mmesa->dirty |= (MGA_UPLOAD_CONTEXT | MGA_UPLOAD_TEX0 |
@@ -577,36 +662,48 @@ void mgaGetLock( mgaContextPtr mmesa, GLuint flags )
sarea->ctxOwner=me;
}
- for (i = 0 ; i < mmesa->lastTexHeap ; i++)
- if (sarea->texAge[i] != mmesa->texAge[i])
- mgaAgeTextures( mmesa, i );
+ for ( i = 0 ; i < mmesa->nr_heaps ; i++ ) {
+ DRI_AGE_TEXTURES( mmesa->texture_heaps[ i ] );
+ }
sarea->last_quiescent = -1; /* just kill it for now */
}
-
static const struct __DriverAPIRec mgaAPI = {
- mgaInitDriver,
- mgaDestroyScreen,
- mgaCreateContext,
- mgaDestroyContext,
- mgaCreateBuffer,
- mgaDestroyBuffer,
- mgaSwapBuffers,
- mgaMakeCurrent,
- mgaUnbindContext,
- mgaOpenFullScreen,
- mgaCloseFullScreen
+ .InitDriver = mgaInitDriver,
+ .DestroyScreen = mgaDestroyScreen,
+ .CreateContext = mgaCreateContext,
+ .DestroyContext = mgaDestroyContext,
+ .CreateBuffer = mgaCreateBuffer,
+ .DestroyBuffer = mgaDestroyBuffer,
+ .SwapBuffers = mgaSwapBuffers,
+ .MakeCurrent = mgaMakeCurrent,
+ .UnbindContext = mgaUnbindContext,
+ .OpenFullScreen = mgaOpenCloseFullScreen,
+ .CloseFullScreen = mgaOpenCloseFullScreen,
+ .GetSwapInfo = getSwapInfo,
+ .GetMSC = driGetMSC32,
+ .WaitForMSC = driWaitForMSC32,
+ .WaitForSBC = NULL,
+ .SwapBuffersMSC = NULL
};
-
/*
* This is the bootstrap function for the driver.
* The __driCreateScreen name is the symbol that libGL.so fetches.
* Return: pointer to a __DRIscreenPrivate.
*/
+#ifndef _SOLO
+void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
+ int numConfigs, __GLXvisualConfig *config)
+{
+ __DRIscreenPrivate *psp;
+ psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &mgaAPI);
+ return (void *) psp;
+}
+#else
void *__driCreateScreen(struct DRIDriverRec *driver,
struct DRIDriverContextRec *driverContext)
{
@@ -614,3 +711,56 @@ void *__driCreateScreen(struct DRIDriverRec *driver,
psp = __driUtilCreateScreen(driver, driverContext, &mgaAPI);
return (void *) psp;
}
+#endif
+
+
+#ifndef _SOLO
+/* This function is called by libGL.so as soon as libGL.so is loaded.
+ * This is where we'd register new extension functions with the dispatcher.
+ */
+void
+__driRegisterExtensions( void )
+{
+ PFNGLXENABLEEXTENSIONPROC glx_enable_extension;
+
+
+ if ( driCompareGLXAPIVersion( 20030317 ) >= 0 ) {
+ glx_enable_extension = (PFNGLXENABLEEXTENSIONPROC)
+ glXGetProcAddress( "__glXEnableExtension" );
+
+ if ( glx_enable_extension != NULL ) {
+ (*glx_enable_extension)( "GLX_SGI_swap_control", GL_FALSE );
+ (*glx_enable_extension)( "GLX_SGI_video_sync", GL_FALSE );
+ (*glx_enable_extension)( "GLX_MESA_swap_control", GL_FALSE );
+ (*glx_enable_extension)( "GLX_MESA_swap_frame_usage", GL_FALSE );
+ }
+ }
+}
+#endif
+
+/**
+ * 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;
+}
+#endif
diff --git a/src/mesa/drivers/dri/mga/mga_xmesa.h b/src/mesa/drivers/dri/mga/mga_xmesa.h
index eda996f5a4..de349da089 100644
--- a/src/mesa/drivers/dri/mga/mga_xmesa.h
+++ b/src/mesa/drivers/dri/mga/mga_xmesa.h
@@ -29,8 +29,9 @@
#ifndef _MGA_INIT_H_
#define _MGA_INIT_H_
+#ifdef GLX_DIRECT_RENDERING
+
#include <sys/time.h>
-#include <linux/types.h>
#include "dri_util.h"
#include "mtypes.h"
#include "mgaregs.h"
@@ -46,6 +47,9 @@ typedef struct mga_screen_private_s {
int cpp; /* for front and back buffers */
GLint agpMode;
unsigned int irq; /* IRQ number (0 means none) */
+ GLboolean linecomp_sane; /* GL_TRUE if line comp. programmed correctly
+ * by the DDX driver.
+ */
unsigned int mAccess;
@@ -136,8 +140,9 @@ do { \
#define MGA_BASE( reg ) ((unsigned long)(mmesa->mgaScreen->mmio.map))
#define MGA_ADDR( reg ) (MGA_BASE(reg) + reg)
-#define MGA_DEREF( reg ) *(volatile __u32 *)MGA_ADDR( reg )
+#define MGA_DEREF( reg ) *(volatile CARD32 *)MGA_ADDR( reg )
#define MGA_READ( reg ) MGA_DEREF( reg )
#define MGA_WRITE( reg, val ) do { MGA_DEREF( reg ) = val; } while (0)
#endif
+#endif
diff --git a/src/mesa/drivers/dri/mga/mgacontext.h b/src/mesa/drivers/dri/mga/mgacontext.h
index 3065ea9fd1..7188f6d955 100644
--- a/src/mesa/drivers/dri/mga/mgacontext.h
+++ b/src/mesa/drivers/dri/mga/mgacontext.h
@@ -29,14 +29,15 @@
#ifndef MGALIB_INC
#define MGALIB_INC
-/*#include <X11/Xlibint.h>*/
+#include <inttypes.h>
#include "dri_util.h"
#include "mtypes.h"
+#include "colormac.h"
#include "xf86drm.h"
#include "mm.h"
-/*#include "mem.h"*/
#include "mga_sarea.h"
-
+#include "texmem.h"
+#include "macros.h"
#define MGA_SET_FIELD(reg,mask,val) reg = ((reg) & (mask)) | ((val) & ~(mask))
#define MGA_FIELD(field,val) (((val) << (field ## _SHIFT)) & ~(field ## _MASK))
@@ -59,19 +60,9 @@
#define MGA_FALLBACK_RENDERMODE 0x10
#define MGA_FALLBACK_STENCIL 0x20
#define MGA_FALLBACK_DEPTH 0x40
+#define MGA_FALLBACK_BORDER_MODE 0x80
-/* For mgaCtx->new_state.
- */
-#define MGA_NEW_DEPTH 0x1
-#define MGA_NEW_ALPHA 0x2
-#define MGA_NEW_CLIP 0x8
-#define MGA_NEW_TEXTURE 0x20
-#define MGA_NEW_CULL 0x40
-#define MGA_NEW_WARP 0x80
-#define MGA_NEW_STENCIL 0x100
-#define MGA_NEW_CONTEXT 0x200
-
/* Use the templated vertex formats:
*/
#define TAG(x) mga##x
@@ -96,43 +87,103 @@ typedef void (*mga_point_func)( mgaContextPtr, mgaVertex * );
struct mga_texture_object_s;
struct mga_screen_private_s;
-#define MGA_TEX_MAXLEVELS 5
+#define G200_TEX_MAXLEVELS 5
+#define G400_TEX_MAXLEVELS 11
typedef struct mga_texture_object_s
{
- struct mga_texture_object_s *next;
- struct mga_texture_object_s *prev;
- struct gl_texture_object *tObj;
- struct mga_context_t *ctx;
- PMemBlock MemBlock;
- GLuint offsets[MGA_TEX_MAXLEVELS];
- int lastLevel;
- GLuint dirty_images;
- GLuint totalSize;
- int texelBytes;
- GLuint age;
- int bound;
- int heap; /* agp or card */
+ 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;
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;
} 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. */
+ unsigned int lastStamp; /* fullscreen breaks dpriv->laststamp,
+ * need to shadow it here. */
+
+ /* Hardware state management
+ */
+ struct mga_hw_state hw;
/* Bookkeeping for texturing
*/
- int lastTexHeap;
- struct mga_texture_object_s TexObjList[MGA_NR_TEX_HEAPS];
- struct mga_texture_object_s SwappedOut;
+ unsigned nr_heaps;
+ driTexHeap * texture_heaps[ MGA_NR_TEX_HEAPS ];
+ driTextureObject swapped;
+
struct mga_texture_object_s *CurrentTexObj[2];
- memHeap_t *texHeap[MGA_NR_TEX_HEAPS];
- int c_texupload;
- int c_texusage;
- int tex_thrash;
/* Map GL texture units onto hardware.
@@ -166,7 +217,7 @@ struct mga_context_t {
GLenum raster_primitive;
GLenum render_primitive;
- char *verts;
+ GLubyte *verts;
GLint vertex_stride_shift;
GLuint vertex_format;
GLuint vertex_size;
@@ -180,8 +231,7 @@ struct mga_context_t {
/* Manage driver and hardware state
*/
- GLuint new_gl_state;
- GLuint new_state;
+ GLuint NewGLState;
GLuint dirty;
mga_context_regs_t setup;
@@ -205,13 +255,21 @@ struct mga_context_t {
/* VBI
*/
GLuint vbl_seq;
+ GLuint vblank_flags;
+
+ uint64_t swap_ust;
+ uint64_t swap_missed_ust;
+
+ GLuint swap_count;
+ GLuint swap_missed_count;
+
+ PFNGLXGETUSTPROC get_ust;
/* 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 read_buffer;
int readOffset;
int drawX, drawY; /* origin of drawable in draw buffer */
int lastX, lastY; /* detect DSTORG bug */
@@ -245,51 +303,38 @@ struct mga_context_t {
#define MGA_CONTEXT(ctx) ((mgaContextPtr)(ctx->DriverCtx))
-#define MGAPACKCOLOR555(r,g,b,a) \
- ((((r) & 0xf8) << 7) | (((g) & 0xf8) << 2) | (((b) & 0xf8) >> 3) | \
- ((a) ? 0x8000 : 0))
-#define MGAPACKCOLOR565(r,g,b) \
- ((((r) & 0xf8) << 8) | (((g) & 0xfc) << 3) | (((b) & 0xf8) >> 3))
-#define MGAPACKCOLOR88(l, a) \
- (((l) << 8) | (a))
-
-#define MGAPACKCOLOR888(r,g,b) \
- (((r) << 16) | ((g) << 8) | (b))
-
-#define MGAPACKCOLOR8888(r,g,b,a) \
- (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
-
-#define MGAPACKCOLOR4444(r,g,b,a) \
- ((((a) & 0xf0) << 8) | (((r) & 0xf0) << 4) | ((g) & 0xf0) | ((b) >> 4))
+/* ================================================================
+ * Debugging:
+ */
+#define DO_DEBUG 1
-#define MGA_DEBUG 0
-#ifndef MGA_DEBUG
+#if DO_DEBUG
extern int MGA_DEBUG;
+#else
+#define MGA_DEBUG 0
#endif
-#define DEBUG_ALWAYS_SYNC 0x1
-#define DEBUG_VERBOSE_MSG 0x2
-#define DEBUG_VERBOSE_LRU 0x4
-#define DEBUG_VERBOSE_DRI 0x8
-#define DEBUG_VERBOSE_IOCTL 0x10
-#define DEBUG_VERBOSE_2D 0x20
-#define DEBUG_VERBOSE_FALLBACK 0x40
+#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 MGAPACKCOLOR565(r,g,b);
- case 4:
- return MGAPACKCOLOR8888(r,g,b,a);
- default:
- return 0;
- }
+ switch (cpp) {
+ case 2:
+ return PACK_COLOR_565( r, g, b );
+ case 4:
+ return PACK_COLOR_8888( a, r, g, b );
+ default:
+ return 0;
+ }
}
diff --git a/src/mesa/drivers/dri/mga/mgadd.c b/src/mesa/drivers/dri/mga/mgadd.c
index 6ce50e6726..d2f11d8d45 100644
--- a/src/mesa/drivers/dri/mga/mgadd.c
+++ b/src/mesa/drivers/dri/mga/mgadd.c
@@ -29,10 +29,6 @@
#include "mtypes.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-
#include "mm.h"
#include "mgacontext.h"
#include "mgadd.h"
@@ -42,12 +38,9 @@
#include "mgatris.h"
#include "mgavb.h"
#include "mga_xmesa.h"
-#include "extensions.h"
-#if defined(USE_X86_ASM)
-#include "X86/common_x86_asm.h"
-#endif
+#include "utils.h"
-#define MGA_DATE "20020221"
+#define DRIVER_DATE "20030328"
/***************************************
@@ -59,52 +52,19 @@ static const GLubyte *mgaDDGetString( 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:
- sprintf( buffer, "Mesa DRI %s " MGA_DATE,
- MGA_IS_G400(mmesa) ? "G400" :
- MGA_IS_G200(mmesa) ? "G200" : "MGA" );
-
- /* Append any AGP-specific information.
- */
- switch ( mmesa->mgaScreen->agpMode ) {
- case 1:
- strncat( buffer, " AGP 1x", 7 );
- break;
- case 2:
- strncat( buffer, " AGP 2x", 7 );
- break;
- case 4:
- strncat( buffer, " AGP 4x", 7 );
- break;
- }
-
- /* Append any CPU-specific information.
- */
-#ifdef USE_X86_ASM
- if ( _mesa_x86_cpu_features ) {
- strncat( buffer, " x86", 4 );
- }
-#endif
-#ifdef USE_MMX_ASM
- if ( cpu_has_mmx ) {
- strncat( buffer, "/MMX", 4 );
- }
-#endif
-#ifdef USE_3DNOW_ASM
- if ( cpu_has_3dnow ) {
- strncat( buffer, "/3DNow!", 7 );
- }
-#endif
-#ifdef USE_SSE_ASM
- if ( cpu_has_xmm ) {
- strncat( buffer, "/SSE", 4 );
- }
-#endif
+ offset = driGetRendererString( buffer,
+ MGA_IS_G400(mmesa) ? "G400" :
+ MGA_IS_G200(mmesa) ? "G200" : "MGA",
+ DRIVER_DATE,
+ mmesa->mgaScreen->agpMode );
+
return (GLubyte *)buffer;
default:
@@ -129,40 +89,6 @@ static void mgaBufferSize(GLframebuffer *buffer, GLuint *width, GLuint *height)
UNLOCK_HARDWARE( mmesa );
}
-void mgaDDExtensionsInit( GLcontext *ctx )
-{
- /* paletted_textures currently doesn't work, but we could fix them later */
- /*
- _mesa_enable_extension( ctx, "GL_EXT_shared_texture_palette" );
- _mesa_enable_extension( ctx, "GL_EXT_paletted_texture" );
- */
-
- _mesa_enable_extension( ctx, "GL_ARB_texture_compression" );
- _mesa_enable_extension( ctx, "GL_ARB_multisample" );
-
- _mesa_enable_extension( ctx, "GL_SGIS_generate_mipmap" );
-
- /* Turn on multitexture and texenv_add for the G400.
- */
- if (MGA_IS_G400(MGA_CONTEXT(ctx))) {
- _mesa_enable_extension( ctx, "GL_ARB_multitexture" );
- _mesa_enable_extension( ctx, "GL_ARB_texture_env_add" );
-
- _mesa_enable_extension( ctx, "GL_EXT_texture_env_add" );
-
-#if defined (MESA_packed_depth_stencil)
- _mesa_enable_extension( ctx, "GL_MESA_packed_depth_stencil" );
-#endif
-
-#if defined (MESA_experimetal_agp_allocator)
- if (!getenv("MGA_DISABLE_AGP_ALLOCATOR"))
- _mesa_enable_extension( ctx, "GL_MESA_experimental_agp_allocator" );
-#endif
- }
-}
-
-
-
void mgaDDInitDriverFuncs( GLcontext *ctx )
{
ctx->Driver.GetBufferSize = mgaBufferSize;
diff --git a/src/mesa/drivers/dri/mga/mgadd.h b/src/mesa/drivers/dri/mga/mgadd.h
index 6072e6cfc9..919fd742d6 100644
--- a/src/mesa/drivers/dri/mga/mgadd.h
+++ b/src/mesa/drivers/dri/mga/mgadd.h
@@ -32,6 +32,5 @@
#include "context.h"
void mgaDDInitDriverFuncs( GLcontext *ctx );
-void mgaDDExtensionsInit( GLcontext *ctx );
#endif
diff --git a/src/mesa/drivers/dri/mga/mgaioctl.c b/src/mesa/drivers/dri/mga/mgaioctl.c
index f88c878060..6b50af202a 100644
--- a/src/mesa/drivers/dri/mga/mgaioctl.c
+++ b/src/mesa/drivers/dri/mga/mgaioctl.c
@@ -27,7 +27,7 @@
*/
/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgaioctl.c,v 1.16 2002/12/16 16:18:52 dawes Exp $ */
-#include <stdio.h>
+#include <sched.h>
#include <errno.h>
#include "mtypes.h"
@@ -43,11 +43,10 @@
#include "mgavb.h"
#include "mgaioctl.h"
#include "mgatris.h"
-#include "mgabuffers.h"
+#include "mga_common.h"
+#include "vblank.h"
-#include "xf86drm.h"
-#include "mga_common.h"
static void mga_iload_dma_ioctl(mgaContextPtr mmesa,
unsigned long dest,
@@ -61,6 +60,13 @@ static void mga_iload_dma_ioctl(mgaContextPtr mmesa,
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;
@@ -278,65 +284,11 @@ mgaDDClear( GLcontext *ctx, GLbitfield mask, GLboolean all,
}
-int nrswaps;
-
-
-void mgaWaitForVBlank( mgaContextPtr mmesa )
-{
-#if 0
- drmVBlank vbl;
- int ret;
-
- if ( !mmesa->mgaScreen->irq )
- return;
-
- if ( getenv("LIBGL_SYNC_REFRESH") ) {
- /* Wait for until the next vertical blank */
- vbl.request.type = DRM_VBLANK_RELATIVE;
- vbl.request.sequence = 1;
- } else if ( getenv("LIBGL_THROTTLE_REFRESH") ) {
- /* Wait for at least one vertical blank since the last call */
- vbl.request.type = DRM_VBLANK_ABSOLUTE;
- vbl.request.sequence = mmesa->vbl_seq + 1;
- } else {
- return;
- }
-
- if ((ret = drmWaitVBlank( mmesa->driFd, &vbl ))) {
- fprintf(stderr, "%s: drmWaitVBlank returned %d, IRQs don't seem to be"
- " working correctly.\nTry running with LIBGL_THROTTLE_REFRESH"
- " and LIBL_SYNC_REFRESH unset.\n", __FUNCTION__, ret);
- exit(1);
- }
-
- mmesa->vbl_seq = vbl.reply.sequence;
-#endif
-}
-
-
-/*
- * Copy the back buffer to the front buffer.
- */
-void mgaSwapBuffers(__DRIdrawablePrivate *dPriv)
+static void mgaWaitForFrameCompletion( mgaContextPtr mmesa )
{
- mgaContextPtr mmesa;
- XF86DRIClipRectPtr pbox;
- GLint nbox;
- GLint ret, wait = 0;
- GLint i;
+ unsigned wait = 0;
GLuint last_frame, last_wrap;
- assert(dPriv);
- assert(dPriv->driContextPriv);
- assert(dPriv->driContextPriv->driverPrivate);
-
- mmesa = (mgaContextPtr) dPriv->driContextPriv->driverPrivate;
-
- FLUSH_BATCH( mmesa );
-
- mgaWaitForVBlank( mmesa );
-
- LOCK_HARDWARE( mmesa );
last_frame = mmesa->sarea->last_frame.head;
last_wrap = mmesa->sarea->last_frame.wrap;
@@ -360,12 +312,46 @@ void mgaSwapBuffers(__DRIdrawablePrivate *dPriv)
}
UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH );
- for ( i = 0 ; i < 1024 ; i++ ) {
- /* Don't just hammer the register... */
- }
+ UNLOCK_HARDWARE( mmesa );
+ DO_USLEEP( 1 );
+ LOCK_HARDWARE( mmesa );
}
if ( wait )
fprintf( stderr, "\n" );
+}
+
+
+/*
+ * Copy the back buffer to the front buffer.
+ */
+void mgaSwapBuffers( __DRIdrawablePrivate *dPriv )
+{
+ mgaContextPtr mmesa;
+ XF86DRIClipRectPtr 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 );
+
+ LOCK_HARDWARE( mmesa );
+ mgaWaitForFrameCompletion( mmesa );
+ UNLOCK_HARDWARE( mmesa );
+ driWaitForVBlank( dPriv, & mmesa->vbl_seq, mmesa->vblank_flags,
+ & missed_target );
+ if ( missed_target ) {
+ mmesa->swap_missed_count++;
+ (void) (*mmesa->get_ust)( & mmesa->swap_missed_ust );
+ }
+ LOCK_HARDWARE( mmesa );
/* Use the frontbuffer cliprects
*/
@@ -399,6 +385,8 @@ void mgaSwapBuffers(__DRIdrawablePrivate *dPriv)
UNLOCK_HARDWARE( mmesa );
mmesa->dirty |= MGA_UPLOAD_CLIPRECTS;
+ mmesa->swap_count++;
+ (void) (*mmesa->get_ust)( & mmesa->swap_ust );
}
@@ -442,18 +430,17 @@ void mgaWaitAge( mgaContextPtr mmesa, int age )
}
-static int intersect_rect( XF86DRIClipRectPtr out,
- XF86DRIClipRectPtr a,
- XF86DRIClipRectPtr b )
+static GLboolean intersect_rect( XF86DRIClipRectPtr out,
+ const XF86DRIClipRectPtr a,
+ const XF86DRIClipRectPtr 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;
- if (out->x1 > out->x2) return 0;
- if (out->y1 > out->y2) return 0;
- return 1;
+
+ return ((out->x1 < out->x2) && (out->y1 < out->y2));
}
@@ -559,7 +546,7 @@ void mgaFlushVerticesLocked( mgaContextPtr mmesa )
vertex.idx = buffer->idx;
vertex.used = buffer->used;
vertex.discard = discard;
- drmCommandWrite( mmesa->driFd, DRM_MGA_VERTEX,
+ drmCommandWrite( mmesa->driFd, DRM_MGA_VERTEX,
&vertex, sizeof(drmMGAVertex) );
age_mmesa(mmesa, mmesa->sarea->last_enqueue);
diff --git a/src/mesa/drivers/dri/mga/mgaioctl.h b/src/mesa/drivers/dri/mga/mgaioctl.h
index b7cf44d6ff..2d959d8246 100644
--- a/src/mesa/drivers/dri/mga/mgaioctl.h
+++ b/src/mesa/drivers/dri/mga/mgaioctl.h
@@ -34,6 +34,7 @@
#include "mga_xmesa.h"
void mgaSwapBuffers( __DRIdrawablePrivate *dPriv );
+void mgaWaitForVBlank( mgaContextPtr mmesa );
GLuint *mgaAllocVertexDwords( mgaContextPtr mmesa, int dwords );
@@ -41,7 +42,6 @@ GLuint *mgaAllocVertexDwords( mgaContextPtr mmesa, int dwords );
void mgaGetILoadBufferLocked( mgaContextPtr mmesa );
drmBufPtr mgaGetBufferLocked( mgaContextPtr mmesa );
-void mgaWaitForVBlank( mgaContextPtr mmesa );
void mgaFireILoadLocked( mgaContextPtr mmesa,
GLuint offset, GLuint length );
@@ -104,8 +104,9 @@ do { \
if ( ret < 0 ) { \
drmCommandNone( mmesa->driFd, DRM_MGA_RESET ); \
UNLOCK_HARDWARE( mmesa ); \
- fprintf( stderr, "%s: flush ret=%d\n", __FUNCTION__, ret ); \
- /*fprintf( stderr, "drmMGAFlushDMA: return = %d\n", ret );*/ \
+ fprintf( stderr, "%s: flush return = %s (%d), flags = 0x%08x\n", \
+ __FUNCTION__, strerror( -ret ), -ret, \
+ (unsigned)(flags) ); \
exit( 1 ); \
} \
} while (0)
diff --git a/src/mesa/drivers/dri/mga/mgapixel.c b/src/mesa/drivers/dri/mga/mgapixel.c
index 0bc4b3fac5..07e0c3a756 100644
--- a/src/mesa/drivers/dri/mga/mgapixel.c
+++ b/src/mesa/drivers/dri/mga/mgapixel.c
@@ -35,12 +35,12 @@
#include "mgacontext.h"
#include "mgaioctl.h"
#include "mgapixel.h"
-#include "mgabuffers.h"
+#include "mgastate.h"
-#include "xf86drm.h"
#include "mga_common.h"
#include "swrast/swrast.h"
+#include "imports.h"
#define IS_AGP_MEM( mmesa, p ) \
((unsigned long)mmesa->mgaScreen->buffers.map <= ((unsigned long)p) && \
@@ -134,7 +134,7 @@ check_color_per_fragment_ops( const GLcontext *ctx )
!ctx->Color.ColorMask[2] ||
!ctx->Color.ColorMask[3] ||
ctx->Color.ColorLogicOpEnabled ||
- ctx->Texture.Unit[0]._ReallyEnabled ||
+ ctx->Texture._EnabledUnits ||
ctx->Depth.OcclusionTest
) &&
ctx->Current.RasterPosValid &&
@@ -596,7 +596,7 @@ mgaTryDrawPixels( GLcontext *ctx,
}
}
#else
- memcpy( address, pixels, rows*bufferpitch );
+ MEMCPY( address, pixels, rows*bufferpitch );
#endif
do_draw_pix( ctx, x, y, width, rows,
@@ -639,42 +639,8 @@ mgaDDDrawPixels( GLcontext *ctx,
* the same block of agp space which isn't used for anything else at
* present.
*/
-#if defined(MESA_hacked_agp_allocator)
-static void mgaDDFreeAgpMemory( GLcontext *ctx, void *ptr )
-{
- (void) ptr;
-}
-
-static void *mgaDDAllocateAgpMemory( GLcontext *ctx, GLsizei size )
-{
- mgaContextPtr mmesa = MGA_CONTEXT(ctx);
-
- if (size < mmesa->mgaScreen->textureSize[MGA_AGP_HEAP])
- return mmesa->mgaScreen->texVirtual[MGA_AGP_HEAP];
- else
- return 0;
-}
-
-static GLint mgaDDGetAgpOffset( GLcontext *ctx, const void *ptr )
-{
- mgaContextPtr mmesa = MGA_CONTEXT(ctx);
-
- if (!IS_AGP_MEM(mmesa, ptr))
- return -1;
-
- return AGP_OFFSET(mmesa, ptr);
-}
-#endif
-
-
void mgaDDInitPixelFuncs( GLcontext *ctx )
{
-#if defined (MESA_experimetal_agp_allocator)
- ctx->Driver.AllocateAgpMemory = mgaDDAllocateAgpMemory;
- ctx->Driver.GetAgpOffset = mgaDDGetAgpOffset;
- ctx->Driver.FreeAgpMemory = mgaDDFreeAgpMemory;
-#endif
-
/* Pixel path fallbacks.
*/
ctx->Driver.Accum = _swrast_Accum;
diff --git a/src/mesa/drivers/dri/mga/mgaregs.h b/src/mesa/drivers/dri/mga/mgaregs.h
index f07dc2de0b..e1291ca01b 100644
--- a/src/mesa/drivers/dri/mga/mgaregs.h
+++ b/src/mesa/drivers/dri/mga/mgaregs.h
@@ -1052,6 +1052,7 @@
# 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
@@ -1137,6 +1138,13 @@
# 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
@@ -1377,5 +1385,11 @@
/**************** (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/mesa/drivers/dri/mga/mgarender.c b/src/mesa/drivers/dri/mga/mgarender.c
index 53614c223f..516a99099f 100644
--- a/src/mesa/drivers/dri/mga/mgarender.c
+++ b/src/mesa/drivers/dri/mga/mgarender.c
@@ -42,9 +42,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "glheader.h"
#include "context.h"
#include "macros.h"
-/*//#include "mem.h"*/
+#include "imports.h"
#include "mtypes.h"
-/*#include "mmath.h" */
#include "tnl/t_context.h"
@@ -165,7 +164,7 @@ static GLboolean mga_run_render( GLcontext *ctx,
static void mga_check_render( GLcontext *ctx, struct gl_pipeline_stage *stage )
{
- GLuint inputs = VERT_BIT_POS | VERT_BIT_CLIP | VERT_BIT_COLOR0;
+ GLuint inputs = VERT_BIT_CLIP | VERT_BIT_COLOR0;
if (ctx->RenderMode == GL_RENDER) {
if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)
diff --git a/src/mesa/drivers/dri/mga/mgaspan.c b/src/mesa/drivers/dri/mga/mgaspan.c
index 8dc971cfc5..684239865f 100644
--- a/src/mesa/drivers/dri/mga/mgaspan.c
+++ b/src/mesa/drivers/dri/mga/mgaspan.c
@@ -116,7 +116,7 @@
#undef INIT_MONO_PIXEL
#define INIT_MONO_PIXEL(p, color) \
- p = MGAPACKCOLOR565( color[0], color[1], color[2] )
+ p = PACK_COLOR_565( color[0], color[1], color[2] )
#define WRITE_RGBA( _x, _y, r, g, b, a ) \
@@ -148,7 +148,7 @@ do { \
#undef INIT_MONO_PIXEL
#define INIT_MONO_PIXEL(p, color) \
- p = MGAPACKCOLOR8888( color[0], color[1], color[2], color[3] )
+ p = PACK_COLOR_8888( color[3], color[0], color[1], color[2] )
#define WRITE_RGBA(_x, _y, r, g, b, a) \
@@ -233,11 +233,38 @@ do { \
+/*
+ * This function is called to specify which buffer to read and write
+ * for software rasterization (swrast) fallbacks. This doesn't necessarily
+ * correspond to glDrawBuffer() or glReadBuffer() calls.
+ */
+static void mgaDDSetBuffer(GLcontext *ctx, GLframebuffer *buffer,
+ GLuint bufferBit)
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+
+ if (bufferBit == FRONT_LEFT_BIT)
+ {
+ mmesa->drawOffset = mmesa->mgaScreen->frontOffset;
+ mmesa->readOffset = mmesa->mgaScreen->frontOffset;
+ }
+ else if (bufferBit == BACK_LEFT_BIT)
+ {
+ mmesa->drawOffset = mmesa->mgaScreen->backOffset;
+ mmesa->readOffset = mmesa->mgaScreen->backOffset;
+ }
+ else {
+ assert(0);
+ }
+}
+
void mgaDDInitSpanFuncs( GLcontext *ctx )
{
mgaContextPtr mmesa = MGA_CONTEXT(ctx);
struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx);
+ swdd->SetBuffer = mgaDDSetBuffer;
+
switch (mmesa->mgaScreen->cpp) {
case 2:
swdd->WriteRGBASpan = mgaWriteRGBASpan_565;
diff --git a/src/mesa/drivers/dri/mga/mgastate.c b/src/mesa/drivers/dri/mga/mgastate.c
index 02b98fdb76..0d304966d7 100644
--- a/src/mesa/drivers/dri/mga/mgastate.c
+++ b/src/mesa/drivers/dri/mga/mgastate.c
@@ -26,9 +26,9 @@
*/
/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgastate.c,v 1.13 2002/10/30 12:51:36 alanh Exp $ */
-#include <stdio.h>
#include "mtypes.h"
+#include "colormac.h"
#include "dd.h"
#include "mm.h"
@@ -40,19 +40,22 @@
#include "mgatris.h"
#include "mgaioctl.h"
#include "mgaregs.h"
-#include "mgabuffers.h"
#include "swrast/swrast.h"
#include "array_cache/acache.h"
#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
#include "swrast_setup/swrast_setup.h"
+static void updateSpecularLighting( GLcontext *ctx );
+
/* Some outstanding problems with accelerating logic ops...
*/
#if defined(ACCEL_ROP)
-static GLuint mgarop_NoBLK[16] = {
+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,
@@ -65,221 +68,57 @@ static GLuint mgarop_NoBLK[16] = {
#endif
-static void mgaUpdateStencil(const GLcontext *ctx)
-{
- mgaContextPtr mmesa = MGA_CONTEXT(ctx);
- GLuint stencil = 0, stencilctl = 0;
-
- if (ctx->Stencil.Enabled)
- {
- stencil = ctx->Stencil.Ref[0] |
- ( ctx->Stencil.ValueMask[0] << 8 ) |
- ( ctx->Stencil.WriteMask[0] << 16 );
-
- switch (ctx->Stencil.Function[0])
- {
- case GL_NEVER:
- MGA_SET_FIELD(stencilctl, SC_smode_MASK, SC_smode_snever);
- break;
- case GL_LESS:
- MGA_SET_FIELD(stencilctl, SC_smode_MASK, SC_smode_slt);
- break;
- case GL_LEQUAL:
- MGA_SET_FIELD(stencilctl, SC_smode_MASK, SC_smode_slte);
- break;
- case GL_GREATER:
- MGA_SET_FIELD(stencilctl, SC_smode_MASK, SC_smode_sgt);
- break;
- case GL_GEQUAL:
- MGA_SET_FIELD(stencilctl, SC_smode_MASK, SC_smode_sgte);
- break;
- case GL_NOTEQUAL:
- MGA_SET_FIELD(stencilctl, SC_smode_MASK, SC_smode_sne);
- break;
- case GL_EQUAL:
- MGA_SET_FIELD(stencilctl, SC_smode_MASK, SC_smode_se);
- break;
- case GL_ALWAYS:
- MGA_SET_FIELD(stencilctl, SC_smode_MASK, SC_smode_salways);
- default:
- break;
- }
-
- switch (ctx->Stencil.FailFunc[0])
- {
- case GL_KEEP:
- MGA_SET_FIELD(stencilctl, SC_sfailop_MASK, SC_sfailop_keep);
- break;
- case GL_ZERO:
- MGA_SET_FIELD(stencilctl, SC_sfailop_MASK, SC_sfailop_zero);
- break;
- case GL_REPLACE:
- MGA_SET_FIELD(stencilctl, SC_sfailop_MASK, SC_sfailop_replace);
- break;
- case GL_INCR:
- MGA_SET_FIELD(stencilctl, SC_sfailop_MASK, SC_sfailop_incrsat);
- break;
- case GL_DECR:
- MGA_SET_FIELD(stencilctl, SC_sfailop_MASK, SC_sfailop_decrsat);
- break;
- case GL_INVERT:
- MGA_SET_FIELD(stencilctl, SC_sfailop_MASK, SC_sfailop_invert);
- break;
- default:
- break;
- }
-
- switch (ctx->Stencil.ZFailFunc[0])
- {
- case GL_KEEP:
- MGA_SET_FIELD(stencilctl, SC_szfailop_MASK, SC_szfailop_keep);
- break;
- case GL_ZERO:
- MGA_SET_FIELD(stencilctl, SC_szfailop_MASK, SC_szfailop_zero);
- break;
- case GL_REPLACE:
- MGA_SET_FIELD(stencilctl, SC_szfailop_MASK, SC_szfailop_replace);
- break;
- case GL_INCR:
- MGA_SET_FIELD(stencilctl, SC_szfailop_MASK, SC_szfailop_incrsat);
- break;
- case GL_DECR:
- MGA_SET_FIELD(stencilctl, SC_szfailop_MASK, SC_szfailop_decrsat);
- break;
- case GL_INVERT:
- MGA_SET_FIELD(stencilctl, SC_szfailop_MASK, SC_szfailop_invert);
- break;
- default:
- break;
- }
-
- switch (ctx->Stencil.ZPassFunc[0])
- {
- case GL_KEEP:
- MGA_SET_FIELD(stencilctl, SC_szpassop_MASK, SC_szpassop_keep);
- break;
- case GL_ZERO:
- MGA_SET_FIELD(stencilctl, SC_szpassop_MASK, SC_szpassop_zero);
- break;
- case GL_REPLACE:
- MGA_SET_FIELD(stencilctl, SC_szpassop_MASK, SC_szpassop_replace);
- break;
- case GL_INCR:
- MGA_SET_FIELD(stencilctl, SC_szpassop_MASK, SC_szpassop_incrsat);
- break;
- case GL_DECR:
- MGA_SET_FIELD(stencilctl, SC_szpassop_MASK, SC_szpassop_decrsat);
- break;
- case GL_INVERT:
- MGA_SET_FIELD(stencilctl, SC_szpassop_MASK, SC_szpassop_invert);
- break;
- default:
- break;
- }
- }
-
- mmesa->setup.stencil = stencil;
- mmesa->setup.stencilctl = stencilctl;
- mmesa->dirty |= MGA_UPLOAD_CONTEXT;
-}
-
-static void mgaDDStencilFunc(GLcontext *ctx, GLenum func, GLint ref,
- GLuint mask)
-{
- FLUSH_BATCH( MGA_CONTEXT(ctx) );
- MGA_CONTEXT(ctx)->new_state |= MGA_NEW_STENCIL;
-}
-
-static void mgaDDStencilMask(GLcontext *ctx, GLuint mask)
-{
- FLUSH_BATCH( MGA_CONTEXT(ctx) );
- MGA_CONTEXT(ctx)->new_state |= MGA_NEW_STENCIL;
-}
-
-static void mgaDDStencilOp(GLcontext *ctx, GLenum fail, GLenum zfail,
- GLenum zpass)
-{
- FLUSH_BATCH( MGA_CONTEXT(ctx) );
- MGA_CONTEXT(ctx)->new_state |= MGA_NEW_STENCIL;
-}
+/* =============================================================
+ * Alpha blending
+ */
-static void mgaDDClearDepth(GLcontext *ctx, GLclampd d)
+static void mgaDDAlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref)
{
mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ GLubyte refByte;
+ GLuint a;
- /* KW: should the ~ be there? */
- 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;
- }
-}
-
-static void mgaUpdateZMode(const GLcontext *ctx)
-{
- mgaContextPtr mmesa = MGA_CONTEXT( ctx );
- int zmode = 0;
-
- if (ctx->Depth.Test) {
- switch(ctx->Depth.Func) {
- case GL_NEVER:
- /* can't do this in h/w, we'll use a s/w fallback */
- zmode = DC_zmode_nozcmp;
- break;
- 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:
- break;
- }
+ CLAMPED_FLOAT_TO_UBYTE(refByte, ref);
- if (ctx->Depth.Mask)
- zmode |= DC_atype_zi;
- else
- zmode |= DC_atype_i;
- }
- else {
- zmode |= DC_zmode_nozcmp;
- zmode |= DC_atype_i; /* don't write to zbuffer */
+ 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;
}
-#if defined(ACCEL_ROP)
- mmesa->setup.dwgctl &= DC_bop_MASK;
- if (ctx->Color.ColorLogicOpEnabled)
- zmode |= mgarop_NoBLK[(ctx->Color.LogicOp)&0xf];
- else
- zmode |= mgarop_NoBLK[GL_COPY & 0xf];
-#endif
-
- mmesa->setup.dwgctl &= DC_zmode_MASK & DC_atype_MASK;
- mmesa->setup.dwgctl |= zmode;
+ FLUSH_BATCH( mmesa );
+ mmesa->hw.alpha_func = a | MGA_FIELD( AC_atref, refByte );
mmesa->dirty |= MGA_UPLOAD_CONTEXT;
}
-
-static void mgaDDAlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref)
-{
- FLUSH_BATCH( MGA_CONTEXT(ctx) );
- MGA_CONTEXT(ctx)->new_state |= MGA_NEW_ALPHA;
-}
-
-
static void mgaDDBlendEquation(GLcontext *ctx, GLenum mode)
{
FLUSH_BATCH( MGA_CONTEXT(ctx) );
- MGA_CONTEXT(ctx)->new_state |= MGA_NEW_ALPHA;
/* BlendEquation sets ColorLogicOpEnabled in an unexpected
* manner.
@@ -291,247 +130,169 @@ static void mgaDDBlendEquation(GLcontext *ctx, GLenum mode)
static void mgaDDBlendFunc(GLcontext *ctx, GLenum sfactor, GLenum dfactor)
{
- FLUSH_BATCH( MGA_CONTEXT(ctx) );
- MGA_CONTEXT(ctx)->new_state |= MGA_NEW_ALPHA;
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ mgaScreenPrivate *mgaScreen = mmesa->mgaScreen;
+ 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 = (mgaScreen->cpp == 4)
+ ? AC_src_dst_alpha : AC_src_one;
+ break;
+ case GL_ONE_MINUS_DST_ALPHA:
+ src = (mgaScreen->cpp == 4)
+ ? 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 = (mgaScreen->cpp == 4)
+ ? AC_dst_dst_alpha : AC_dst_one;
+ break;
+ case GL_ONE_MINUS_DST_ALPHA:
+ dst = (mgaScreen->cpp == 4)
+ ? AC_dst_om_dst_alpha : AC_dst_zero;
+ break;
+ }
+
+ FLUSH_BATCH( mmesa );
+ mmesa->hw.blend_func = (src | dst);
+ mmesa->dirty |= MGA_UPLOAD_CONTEXT;
}
static void mgaDDBlendFuncSeparate( GLcontext *ctx, GLenum sfactorRGB,
GLenum dfactorRGB, GLenum sfactorA,
GLenum dfactorA )
{
- FLUSH_BATCH( MGA_CONTEXT(ctx) );
- MGA_CONTEXT(ctx)->new_state |= MGA_NEW_ALPHA;
+ mgaDDBlendFunc( ctx, sfactorRGB, dfactorRGB );
}
+/* =============================================================
+ * Depth testing
+ */
-static void mgaDDLightModelfv(GLcontext *ctx, GLenum pname,
- const GLfloat *param)
+static void mgaDDDepthFunc(GLcontext *ctx, GLenum func)
{
- if (pname == GL_LIGHT_MODEL_COLOR_CONTROL) {
- FLUSH_BATCH( MGA_CONTEXT(ctx) );
- MGA_CONTEXT(ctx)->new_state |= MGA_NEW_TEXTURE;
+ 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;
}
-}
-
-static void mgaDDShadeModel(GLcontext *ctx, GLenum mode)
-{
- FLUSH_BATCH( MGA_CONTEXT(ctx) );
- MGA_CONTEXT(ctx)->new_state |= MGA_NEW_TEXTURE;
-}
-
-
-static void mgaDDDepthFunc(GLcontext *ctx, GLenum func)
-{
- FLUSH_BATCH( MGA_CONTEXT(ctx) );
- MGA_CONTEXT(ctx)->new_state |= MGA_NEW_DEPTH;
+ FLUSH_BATCH( mmesa );
+ mmesa->hw.zmode &= DC_zmode_MASK;
+ mmesa->hw.zmode |= zmode;
+ mmesa->dirty |= MGA_UPLOAD_CONTEXT;
}
static void mgaDDDepthMask(GLcontext *ctx, GLboolean flag)
{
- FLUSH_BATCH( MGA_CONTEXT(ctx) );
- MGA_CONTEXT(ctx)->new_state |= MGA_NEW_DEPTH;
-}
+ mgaContextPtr mmesa = MGA_CONTEXT( ctx );
-#if defined(ACCEL_ROP)
-static void mgaDDLogicOp( GLcontext *ctx, GLenum opcode )
-{
- FLUSH_BATCH( MGA_CONTEXT(ctx) );
- MGA_CONTEXT(ctx)->new_state |= MGA_NEW_DEPTH;
-}
-#else
-static void mgaDDLogicOp( GLcontext *ctx, GLenum opcode )
-{
- FLUSH_BATCH( MGA_CONTEXT(ctx) );
- FALLBACK( ctx, MGA_FALLBACK_LOGICOP,
- (ctx->Color.ColorLogicOpEnabled && opcode != GL_COPY) );
-}
-#endif
+ FLUSH_BATCH( mmesa );
+ mmesa->hw.zmode &= DC_atype_MASK;
+ mmesa->hw.zmode |= (flag) ? DC_atype_zi : DC_atype_i;
+ mmesa->dirty |= MGA_UPLOAD_CONTEXT;
+}
-static void mgaDDFogfv(GLcontext *ctx, GLenum pname, const GLfloat *param)
+static void mgaDDClearDepth(GLcontext *ctx, GLclampd d)
{
mgaContextPtr mmesa = MGA_CONTEXT(ctx);
- if (pname == GL_FOG_COLOR) {
- GLuint color = MGAPACKCOLOR888((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;
+ /* 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;
}
}
-
-
/* =============================================================
- * Alpha blending
+ * Fog
*/
-static void mgaUpdateAlphaMode(GLcontext *ctx)
+static void mgaDDFogfv(GLcontext *ctx, GLenum pname, const GLfloat *param)
{
- mgaContextPtr mmesa = MGA_CONTEXT( ctx );
- mgaScreenPrivate *mgaScreen = mmesa->mgaScreen;
- int a = 0;
-
- /* determine source of alpha for blending and testing */
- if ( !ctx->Texture.Unit[0]._ReallyEnabled ) {
- a |= AC_alphasel_diffused;
- }
- else {
- /* 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.
- */
- if (MGA_IS_G400(mmesa)) {
- a |= AC_alphasel_fromtex;
- }
- else {
- /* G200 */
- switch (ctx->Texture.Unit[0].EnvMode) {
- case GL_DECAL:
- a |= AC_alphasel_diffused;
- case GL_REPLACE:
- a |= AC_alphasel_fromtex;
- break;
- case GL_BLEND:
- case GL_MODULATE:
- a |= AC_alphasel_modulated;
- break;
- default:
- break;
- }
- }
- }
-
-
- /* alpha test control.
- */
- if (ctx->Color.AlphaEnabled) {
- GLubyte ref = ctx->Color.AlphaRef;
- switch (ctx->Color.AlphaFunc) {
- case GL_NEVER:
- a |= AC_atmode_alt;
- ref = 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:
- break;
- }
- a |= MGA_FIELD(AC_atref,ref);
- }
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
- /* blending control */
- if (ctx->Color.BlendEnabled) {
- switch (ctx->Color.BlendSrcRGB) {
- case GL_ZERO:
- a |= AC_src_zero; break;
- case GL_SRC_ALPHA:
- a |= AC_src_src_alpha; break;
- case GL_ONE:
- a |= AC_src_one; break;
- case GL_DST_COLOR:
- a |= AC_src_dst_color; break;
- case GL_ONE_MINUS_DST_COLOR:
- a |= AC_src_om_dst_color; break;
- case GL_ONE_MINUS_SRC_ALPHA:
- a |= AC_src_om_src_alpha; break;
- case GL_DST_ALPHA:
- if (mgaScreen->cpp == 4)
- a |= AC_src_dst_alpha;
- else
- a |= AC_src_one;
- break;
- case GL_ONE_MINUS_DST_ALPHA:
- if (mgaScreen->cpp == 4)
- a |= AC_src_om_dst_alpha;
- else
- a |= AC_src_zero;
- break;
- case GL_SRC_ALPHA_SATURATE:
- if (ctx->Visual.alphaBits > 0)
- a |= AC_src_src_alpha_sat;
- else
- a |= AC_src_zero;
- break;
- default: /* never happens */
- break;
- }
+ 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));
- switch (ctx->Color.BlendDstRGB) {
- case GL_SRC_ALPHA:
- a |= AC_dst_src_alpha; break;
- case GL_ONE_MINUS_SRC_ALPHA:
- a |= AC_dst_om_src_alpha; break;
- case GL_ZERO:
- a |= AC_dst_zero; break;
- case GL_ONE:
- a |= AC_dst_one; break;
- case GL_SRC_COLOR:
- a |= AC_dst_src_color; break;
- case GL_ONE_MINUS_SRC_COLOR:
- a |= AC_dst_om_src_color; break;
- case GL_DST_ALPHA:
- if (mgaScreen->cpp == 4)
- a |= AC_dst_dst_alpha;
- else
- a |= AC_dst_one;
- break;
- case GL_ONE_MINUS_DST_ALPHA:
- if (mgaScreen->cpp == 4)
- a |= AC_dst_om_dst_alpha;
- else
- a |= AC_dst_zero;
- break;
- default: /* never happens */
- break;
- }
- } else {
- a |= AC_src_one|AC_dst_zero;
+ MGA_STATECHANGE(mmesa, MGA_UPLOAD_CONTEXT);
+ mmesa->setup.fogcolor = color;
}
-
- mmesa->setup.alphactrl = (AC_amode_alpha_channel |
- AC_astipple_disable |
- AC_aten_disable |
- AC_atmode_noacmp |
- a);
-
- mmesa->dirty |= MGA_UPLOAD_CONTEXT;
}
-
/* =============================================================
- * Hardware clipping
+ * Scissoring
*/
+
void mgaUpdateClipping(const GLcontext *ctx)
{
mgaContextPtr mmesa = MGA_CONTEXT(ctx);
@@ -554,13 +315,6 @@ void mgaUpdateClipping(const GLcontext *ctx)
mmesa->scissor_rect.x2 = x2;
mmesa->scissor_rect.y2 = y2;
- if (MGA_DEBUG&DEBUG_VERBOSE_2D)
- fprintf(stderr, "SET SCISSOR %d,%d-%d,%d\n",
- mmesa->scissor_rect.x1,
- mmesa->scissor_rect.y1,
- mmesa->scissor_rect.x2,
- mmesa->scissor_rect.y2);
-
mmesa->dirty |= MGA_UPLOAD_CLIPRECTS;
}
}
@@ -569,19 +323,10 @@ void mgaUpdateClipping(const GLcontext *ctx)
static void mgaDDScissor( GLcontext *ctx, GLint x, GLint y,
GLsizei w, GLsizei h )
{
- FLUSH_BATCH( MGA_CONTEXT(ctx) );
- MGA_CONTEXT(ctx)->new_state |= MGA_NEW_CLIP;
-}
-
-
-static void mgaDDClearColor(GLcontext *ctx,
- const GLfloat color[4] )
-{
- mgaContextPtr mmesa = MGA_CONTEXT(ctx);
-
- mmesa->ClearColor = mgaPackColor( mmesa->mgaScreen->cpp,
- color[0], color[1],
- color[2], color[3]);
+ if ( ctx->Scissor.Enabled ) {
+ FLUSH_BATCH( MGA_CONTEXT(ctx) ); /* don't pipeline cliprect changes */
+ mgaUpdateClipping( ctx );
+ }
}
@@ -589,46 +334,42 @@ static void mgaDDClearColor(GLcontext *ctx,
* Culling
*/
+
#define _CULL_DISABLE 0
#define _CULL_NEGATIVE ((1<<11)|(1<<5)|(1<<16))
#define _CULL_POSITIVE (1<<11)
-
-void mgaUpdateCull( GLcontext *ctx )
+static void mgaDDCullFaceFrontFace(GLcontext *ctx, GLenum unused)
{
mgaContextPtr mmesa = MGA_CONTEXT(ctx);
- GLuint mode = _CULL_DISABLE;
+
+ FLUSH_BATCH( mmesa );
if (ctx->Polygon.CullFlag &&
- mmesa->raster_primitive == GL_TRIANGLES &&
ctx->Polygon.CullFaceMode != GL_FRONT_AND_BACK)
{
- mode = _CULL_NEGATIVE;
+ mmesa->hw.cull = _CULL_NEGATIVE;
+
if (ctx->Polygon.CullFaceMode == GL_FRONT)
- mode ^= (_CULL_POSITIVE ^ _CULL_NEGATIVE);
+ mmesa->hw.cull ^= (_CULL_POSITIVE ^ _CULL_NEGATIVE);
+
if (ctx->Polygon.FrontFace != GL_CCW)
- mode ^= (_CULL_POSITIVE ^ _CULL_NEGATIVE);
- if ((ctx->Texture.Unit[0]._ReallyEnabled & TEXTURE_2D_BIT) &&
- (ctx->Texture.Unit[1]._ReallyEnabled & TEXTURE_2D_BIT))
- mode ^= (_CULL_POSITIVE ^ _CULL_NEGATIVE); /* warp bug? */
+ 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;
}
- mmesa->setup.wflag = mode;
mmesa->dirty |= MGA_UPLOAD_CONTEXT;
}
-static void mgaDDCullFaceFrontFace(GLcontext *ctx, GLenum mode)
-{
- FLUSH_BATCH( MGA_CONTEXT(ctx) );
- MGA_CONTEXT(ctx)->new_state |= MGA_NEW_CULL;
-}
-
-
-
-
/* =============================================================
- * Color masks
+ * Masks
*/
static void mgaDDColorMask(GLcontext *ctx,
@@ -654,15 +395,11 @@ static void mgaDDColorMask(GLcontext *ctx,
}
}
+
/* =============================================================
- * Polygon stipple
- *
- * The mga supports a subset of possible 4x4 stipples natively, GL
- * wants 32x32. Fortunately stipple is usually a repeating pattern.
- *
- * Note: the fully opaque pattern (0xffff) has been disabled in order
- * to work around a conformance issue.
+ * Polygon state
*/
+
static int mgaStipples[16] = {
0xffff1, /* See above note */
0xa5a5,
@@ -682,6 +419,17 @@ static int mgaStipples[16] = {
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
+ *
+ * \note the fully opaque pattern (0xffff) has been disabled in order
+ * to work around a conformance issue.
+ */
+
static void mgaDDPolygonStipple( GLcontext *ctx, const GLubyte *mask )
{
mgaContextPtr mmesa = MGA_CONTEXT(ctx);
@@ -730,93 +478,216 @@ static void mgaDDPolygonStipple( GLcontext *ctx, const GLubyte *mask )
}
}
+
/* =============================================================
+ * 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 mgaDDPrintDirty( const char *msg, GLuint state )
+static void updateSpecularLighting( GLcontext *ctx )
{
- fprintf(stderr, "%s (0x%x): %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, " : ""
- );
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ unsigned int specen;
+
+ specen = (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR &&
+ ctx->Light.Enabled) ? TMC_specen_enable : 0;
+
+ if ( specen != mmesa->hw.specen ) {
+ mmesa->hw.specen = specen;
+ mmesa->dirty |= MGA_UPLOAD_TEX0 | MGA_UPLOAD_TEX1;
+
+ mgaChooseVertexState( ctx );
+ }
}
-/* Push the state into the sarea and/or texture memory.
+
+/* =============================================================
+ * Materials
*/
-void mgaEmitHwStateLocked( mgaContextPtr mmesa )
-{
- MGASAREAPrivPtr sarea = mmesa->sarea;
- if (MGA_DEBUG & DEBUG_VERBOSE_MSG)
- mgaDDPrintDirty( "mgaEmitHwStateLocked", mmesa->dirty );
- if ((mmesa->dirty & MGA_UPLOAD_TEX0IMAGE) && mmesa->CurrentTexObj[0])
- mgaUploadTexImages(mmesa, mmesa->CurrentTexObj[0]);
+static void mgaDDLightModelfv(GLcontext *ctx, GLenum pname,
+ const GLfloat *param)
+{
+ if (pname == GL_LIGHT_MODEL_COLOR_CONTROL) {
+ FLUSH_BATCH( MGA_CONTEXT(ctx) );
+ updateSpecularLighting( ctx );
+ }
+}
- if ((mmesa->dirty & MGA_UPLOAD_TEX1IMAGE) && mmesa->CurrentTexObj[1])
- mgaUploadTexImages(mmesa, mmesa->CurrentTexObj[1]);
- if (mmesa->dirty & MGA_UPLOAD_CONTEXT) {
- memcpy( &sarea->ContextState, &mmesa->setup, sizeof(mmesa->setup));
- }
+static void mgaDDShadeModel(GLcontext *ctx, GLenum mode)
+{
+ /* FIXME: This used to FLUSH_BATCH and set MGA_NEW_TEXTURE in new_state,
+ * FIXME: so I'm not sure what to do here now.
+ */
+}
- if ((mmesa->dirty & MGA_UPLOAD_TEX0) && mmesa->CurrentTexObj[0]) {
- memcpy(&sarea->TexState[0],
- &mmesa->CurrentTexObj[0]->setup,
- sizeof(sarea->TexState[0]));
- }
- if ((mmesa->dirty & MGA_UPLOAD_TEX1) && mmesa->CurrentTexObj[1]) {
- memcpy(&sarea->TexState[1],
- &mmesa->CurrentTexObj[1]->setup,
- sizeof(sarea->TexState[1]));
- }
+/* =============================================================
+ * Stencil
+ */
- if (sarea->TexState[0].texctl2 !=
- sarea->TexState[1].texctl2) {
- memcpy(&sarea->TexState[1],
- &sarea->TexState[0],
- sizeof(sarea->TexState[0]));
- mmesa->dirty |= MGA_UPLOAD_TEX1|MGA_UPLOAD_TEX0;
- }
- if (mmesa->dirty & MGA_UPLOAD_PIPE) {
-/* mmesa->sarea->wacceptseq = mmesa->hw_primitive; */
- mmesa->sarea->WarpPipe = mmesa->vertex_format;
- mmesa->sarea->vertsize = mmesa->vertex_size;
+static void mgaDDStencilFunc(GLcontext *ctx, GLenum func, GLint ref,
+ GLuint mask)
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ GLuint stencil;
+ GLuint stencilctl;
+
+ stencil = (ref << S_sref_SHIFT) | (mask << S_smsk_SHIFT);
+ 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;
}
- mmesa->sarea->dirty |= mmesa->dirty;
+ FLUSH_BATCH( mmesa );
+ mmesa->hw.stencil &= (S_sref_MASK & S_smsk_MASK);
+ mmesa->hw.stencil |= stencil;
+ mmesa->hw.stencilctl &= SC_smode_MASK;
+ mmesa->hw.stencilctl |= stencilctl;
+ mmesa->dirty |= MGA_UPLOAD_CONTEXT;
+}
- mmesa->dirty &= (MGA_UPLOAD_CLIPRECTS|MGA_WAIT_AGE);
+static void mgaDDStencilMask(GLcontext *ctx, GLuint mask)
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
- /* This is a bit of a hack but seems to be the best place to ensure
- * that separate specular is disabled when not needed.
- */
- if (mmesa->glCtx->Texture.Unit[0]._ReallyEnabled == 0 ||
- !mmesa->glCtx->Light.Enabled ||
- mmesa->glCtx->Light.Model.ColorControl == GL_SINGLE_COLOR) {
- sarea->TexState[0].texctl2 &= ~TMC_specen_enable;
- sarea->TexState[1].texctl2 &= ~TMC_specen_enable;
- }
+ FLUSH_BATCH( mmesa );
+ mmesa->hw.stencil &= S_swtmsk_MASK;
+ mmesa->hw.stencil |= (mask << S_swtmsk_SHIFT);
+ mmesa->dirty |= MGA_UPLOAD_CONTEXT;
}
-/* Fallback to swrast for select and feedback.
- */
-static void mgaRenderMode( GLcontext *ctx, GLenum mode )
+static void mgaDDStencilOp(GLcontext *ctx, GLenum fail, GLenum zfail,
+ GLenum zpass)
{
- FALLBACK( ctx, MGA_FALLBACK_RENDERMODE, (mode != GL_RENDER) );
+ 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_INVERT:
+ stencilctl |= SC_szpassop_invert;
+ break;
+ default:
+ break;
+ }
+
+ FLUSH_BATCH( mmesa );
+ mmesa->hw.stencilctl &= (SC_sfailop_MASK & SC_szfailop_MASK
+ & SC_szpassop_MASK);
+ mmesa->hw.stencilctl |= stencilctl;
+ mmesa->dirty |= MGA_UPLOAD_CONTEXT;
}
/* =============================================================
+ * Window position and viewport transformation
*/
void mgaCalcViewport( GLcontext *ctx )
@@ -850,8 +721,167 @@ static void mgaDepthRange( GLcontext *ctx,
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 );
+
+ FLUSH_BATCH( mmesa );
+#if defined(ACCEL_ROP)
+ mmesa->hw.rop = mgarop_NoBLK[ opcode & 0x0f ];
+ mmesa->dirty |= MGA_UPLOAD_CONTEXT;
+#else
+ FALLBACK( ctx, MGA_FALLBACK_LOGICOP,
+ (ctx->Color.ColorLogicOpEnabled && opcode != GL_COPY) );
+#endif
+}
+
+
+static void mgaXMesaSetFrontClipRects( mgaContextPtr mmesa )
+{
+ __DRIdrawablePrivate *driDrawable = mmesa->driDrawable;
+
+ if (driDrawable->numClipRects == 0) {
+ static XF86DRIClipRectRec 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;
+
+ mmesa->setup.dstorg = mmesa->drawOffset;
+ mmesa->dirty |= MGA_UPLOAD_CONTEXT | MGA_UPLOAD_CLIPRECTS;
+}
+
+
+static void mgaXMesaSetBackClipRects( mgaContextPtr mmesa )
+{
+ __DRIdrawablePrivate *driDrawable = mmesa->driDrawable;
+
+ if (driDrawable->numBackClipRects == 0)
+ {
+ if (driDrawable->numClipRects == 0) {
+ static XF86DRIClipRectRec 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 *driDrawable = mmesa->driDrawable;
+ MGASAREAPrivPtr sarea = mmesa->sarea;
+
+
+ DRI_VALIDATE_DRAWABLE_INFO(mmesa->driScreen, driDrawable);
+ mmesa->dirty_cliprects = 0;
+
+ if (mmesa->draw_buffer == MGA_FRONT)
+ mgaXMesaSetFrontClipRects( mmesa );
+ else
+ mgaXMesaSetBackClipRects( mmesa );
+
+ sarea->req_draw_buffer = mmesa->draw_buffer;
+
+ mgaUpdateClipping( mmesa->glCtx );
+ mgaCalcViewport( mmesa->glCtx );
+
+ mmesa->dirty |= MGA_UPLOAD_CLIPRECTS;
+}
+
+
+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->Color._DrawDestMask ) {
+ case FRONT_LEFT_BIT:
+ mmesa->setup.dstorg = mmesa->mgaScreen->frontOffset;
+ mmesa->dirty |= MGA_UPLOAD_CONTEXT;
+ mmesa->draw_buffer = MGA_FRONT;
+ mgaXMesaSetFrontClipRects( mmesa );
+ FALLBACK( ctx, MGA_FALLBACK_DRAW_BUFFER, GL_FALSE );
+ break;
+ case BACK_LEFT_BIT:
+ mmesa->setup.dstorg = mmesa->mgaScreen->backOffset;
+ mmesa->draw_buffer = MGA_BACK;
+ mmesa->dirty |= MGA_UPLOAD_CONTEXT;
+ mgaXMesaSetBackClipRects( mmesa );
+ FALLBACK( ctx, MGA_FALLBACK_DRAW_BUFFER, GL_FALSE );
+ break;
+ default:
+ /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
+ FALLBACK( ctx, MGA_FALLBACK_DRAW_BUFFER, GL_TRUE );
+ return;
+ }
+
+ /* We want to update the s/w rast state too so that r200SetBuffer()
+ * gets called.
+ */
+ _swrast_DrawBuffer(ctx, mode);
+}
+
+
+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)
{
@@ -860,11 +890,11 @@ static void mgaDDEnable(GLcontext *ctx, GLenum cap, GLboolean state)
switch(cap) {
case GL_ALPHA_TEST:
FLUSH_BATCH( mmesa );
- mmesa->new_state |= MGA_NEW_ALPHA;
+ mmesa->hw.alpha_func_enable = (state) ? ~0 : 0;
break;
case GL_BLEND:
FLUSH_BATCH( mmesa );
- mmesa->new_state |= MGA_NEW_ALPHA;
+ mmesa->hw.blend_func_enable = (state) ? ~0 : 0;
/* For some reason enable(GL_BLEND) affects ColorLogicOpEnabled.
*/
@@ -874,31 +904,31 @@ static void mgaDDEnable(GLcontext *ctx, GLenum cap, GLboolean state)
break;
case GL_DEPTH_TEST:
FLUSH_BATCH( mmesa );
- mmesa->new_state |= MGA_NEW_DEPTH;
FALLBACK (ctx, MGA_FALLBACK_DEPTH,
ctx->Depth.Func == GL_NEVER && ctx->Depth.Test);
break;
+
case GL_SCISSOR_TEST:
FLUSH_BATCH( mmesa );
mmesa->scissor = state;
- mmesa->new_state |= MGA_NEW_CLIP;
+ 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;
+
+ mgaChooseVertexState( ctx );
break;
case GL_CULL_FACE:
- FLUSH_BATCH( mmesa );
- mmesa->new_state |= MGA_NEW_CULL;
+ mgaDDCullFaceFrontFace( ctx, 0 );
break;
case GL_TEXTURE_1D:
case GL_TEXTURE_2D:
case GL_TEXTURE_3D:
- FLUSH_BATCH( mmesa );
- mmesa->new_state |= (MGA_NEW_TEXTURE|MGA_NEW_ALPHA);
break;
case GL_POLYGON_STIPPLE:
if (mmesa->haveHwStipple && mmesa->raster_primitive == GL_TRIANGLES) {
@@ -914,16 +944,16 @@ static void mgaDDEnable(GLcontext *ctx, GLenum cap, GLboolean state)
#if !defined(ACCEL_ROP)
FALLBACK( ctx, MGA_FALLBACK_LOGICOP,
(state && ctx->Color.LogicOp != GL_COPY));
-#else
- mmesa->new_state |= MGA_NEW_DEPTH;
#endif
break;
case GL_STENCIL_TEST:
FLUSH_BATCH( mmesa );
- if (mmesa->hw_stencil)
- mmesa->new_state |= MGA_NEW_STENCIL;
- else
+ if (mmesa->hw_stencil) {
+ mmesa->hw.stencil_enable = ( state ) ? ~0 : 0;
+ }
+ else {
FALLBACK( ctx, MGA_FALLBACK_STENCIL, state );
+ }
default:
break;
}
@@ -933,56 +963,150 @@ static void mgaDDEnable(GLcontext *ctx, GLenum cap, GLboolean state)
/* =============================================================
*/
-
-
-/* =============================================================
- */
-
-static void mgaDDPrintState( const char *msg, GLuint state )
+static void mgaDDPrintDirty( const char *msg, GLuint state )
{
- fprintf(stderr, "%s (0x%x): %s%s%s%s%s%s\n",
+ fprintf(stderr, "%s (0x%03x): %s%s%s%s%s%s%s\n",
msg,
- state,
- (state & MGA_NEW_DEPTH) ? "depth, " : "",
- (state & MGA_NEW_ALPHA) ? "alpha, " : "",
- (state & MGA_NEW_CLIP) ? "clip, " : "",
- (state & MGA_NEW_CULL) ? "cull, " : "",
- (state & MGA_NEW_TEXTURE) ? "texture, " : "",
- (state & MGA_NEW_CONTEXT) ? "context, " : "");
+ (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 " : ""
+ );
}
-void mgaDDUpdateHwState( GLcontext *ctx )
+/* Push the state into the sarea and/or texture memory.
+ */
+void mgaEmitHwStateLocked( mgaContextPtr mmesa )
{
- mgaContextPtr mmesa = MGA_CONTEXT( ctx );
- int new_state = mmesa->new_state;
+ MGASAREAPrivPtr sarea = mmesa->sarea;
+ GLcontext * ctx = mmesa->glCtx;
- if (new_state)
- {
- FLUSH_BATCH( mmesa );
+ if (MGA_DEBUG & DEBUG_VERBOSE_MSG)
+ mgaDDPrintDirty( __FUNCTION__, mmesa->dirty );
- mmesa->new_state = 0;
+ 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;
+ }
+ }
- if (MESA_VERBOSE&VERBOSE_DRIVER)
- mgaDDPrintState("UpdateHwState", new_state);
+ mmesa->setup.stencil = mmesa->hw.stencil
+ & mmesa->hw.stencil_enable;
+ mmesa->setup.stencilctl = mmesa->hw.stencilctl
+ & mmesa->hw.stencil_enable;
- if (new_state & MGA_NEW_DEPTH)
- mgaUpdateZMode(ctx);
+ /* 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);
- if (new_state & MGA_NEW_ALPHA)
- mgaUpdateAlphaMode(ctx);
+#if defined(ACCEL_ROP)
+ mmesa->setup.dwgctl &= DC_bop_MASK;
+ mmesa->setup.dwgctl |= (ctx->Color.ColorLogicOpEnabled)
+ ? mmesa->hw.rop : mgarop_NoBLK[ GL_COPY & 0x0f ];
+#endif
- if (new_state & MGA_NEW_CLIP)
- mgaUpdateClipping(ctx);
+ 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
+ | (AC_amode_alpha_channel
+ | AC_astipple_disable
+ | AC_aten_disable
+ | AC_atmode_noacmp));
- if (new_state & MGA_NEW_STENCIL)
- mgaUpdateStencil(ctx);
+ memcpy( &sarea->ContextState, &mmesa->setup, sizeof(mmesa->setup));
+ }
- if (new_state & (MGA_NEW_WARP|MGA_NEW_CULL))
- mgaUpdateCull(ctx);
+ if ((mmesa->dirty & MGA_UPLOAD_TEX0) && mmesa->CurrentTexObj[0]) {
+ mmesa->CurrentTexObj[0]->setup.texctl2 &= ~TMC_specen_enable;
+ mmesa->CurrentTexObj[0]->setup.texctl2 |= mmesa->hw.specen;
- if (new_state & (MGA_NEW_WARP|MGA_NEW_TEXTURE))
- mgaUpdateTextureState(ctx);
+ memcpy(&sarea->TexState[0],
+ &mmesa->CurrentTexObj[0]->setup,
+ sizeof(sarea->TexState[0]));
}
+
+ if ((mmesa->dirty & MGA_UPLOAD_TEX1) && mmesa->CurrentTexObj[1]) {
+ mmesa->CurrentTexObj[1]->setup.texctl2 &= ~TMC_specen_enable;
+ mmesa->CurrentTexObj[1]->setup.texctl2 |= mmesa->hw.specen;
+
+ memcpy(&sarea->TexState[1],
+ &mmesa->CurrentTexObj[1]->setup,
+ sizeof(sarea->TexState[1]));
+ }
+
+ if ( (sarea->TexState[0].texctl2 & TMC_borderen_MASK) !=
+ (sarea->TexState[1].texctl2 & TMC_borderen_MASK) ) {
+ const int borderen = sarea->TexState[1].texctl2 & ~TMC_borderen_MASK;
+
+ memcpy( &sarea->TexState[1], &sarea->TexState[0],
+ sizeof(sarea->TexState[0]) );
+ sarea->TexState[1].texctl2 |= borderen;
+ mmesa->dirty |= MGA_UPLOAD_TEX1|MGA_UPLOAD_TEX0;
+ }
+
+ if (mmesa->dirty & MGA_UPLOAD_PIPE) {
+/* mmesa->sarea->wacceptseq = mmesa->hw_primitive; */
+ mmesa->sarea->WarpPipe = mmesa->vertex_format;
+ mmesa->sarea->vertsize = mmesa->vertex_size;
+ }
+
+ mmesa->sarea->dirty |= mmesa->dirty;
+ mmesa->dirty &= MGA_UPLOAD_CLIPRECTS;
+
+ /* This is a bit of a hack but seems to be the best place to ensure
+ * that separate specular is disabled when not needed.
+ */
+ if (ctx->Texture._EnabledUnits == 0 ||
+ !ctx->Light.Enabled ||
+ ctx->Light.Model.ColorControl == GL_SINGLE_COLOR) {
+ sarea->TexState[0].texctl2 &= ~TMC_specen_enable;
+ sarea->TexState[1].texctl2 &= ~TMC_specen_enable;
+ }
+}
+
+
+/* =============================================================
+ */
+
+
+static void mgaDDValidateState( GLcontext *ctx )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT( ctx );
+ int new_state = mmesa->NewGLState;
+
+
+ FLUSH_BATCH( mmesa );
+
+ if (mmesa->NewGLState & _MGA_NEW_RASTERSETUP) {
+ mgaChooseVertexState( ctx );
+ }
+
+ if (mmesa->NewGLState & _MGA_NEW_RENDERSTATE) {
+ mgaChooseRenderState( ctx );
+ }
+
+ if (new_state & _NEW_TEXTURE) {
+ mgaUpdateTextureState(ctx);
+ }
+
+ mmesa->NewGLState = 0;
}
@@ -992,25 +1116,40 @@ static void mgaDDInvalidateState( GLcontext *ctx, GLuint new_state )
_swsetup_InvalidateState( ctx, new_state );
_ac_InvalidateState( ctx, new_state );
_tnl_InvalidateState( ctx, new_state );
- MGA_CONTEXT(ctx)->new_gl_state |= 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->Color._DrawDestMask == BACK_LEFT_BIT) {
+ if (ctx->Visual.doubleBufferMode) {
+ /* use back buffer by default */
mmesa->draw_buffer = MGA_BACK;
- mmesa->read_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->read_buffer = MGA_FRONT;
mmesa->drawOffset = mmesa->mgaScreen->frontOffset;
mmesa->readOffset = mmesa->mgaScreen->frontOffset;
mmesa->setup.dstorg = mgaScreen->frontOffset;
@@ -1043,14 +1182,21 @@ void mgaInitState( mgaContextPtr mmesa )
mmesa->setup.maccess |= MA_zwidth_24;
break;
case 32:
- mmesa->setup.maccess |= MA_pwidth_32;
+ mmesa->setup.maccess |= MA_zwidth_32;
break;
}
+ mmesa->hw.zmode = DC_zmode_zlt | DC_atype_zi;
+ mmesa->hw.stencil = (0x0ff << S_smsk_SHIFT) | (0x0ff << S_swtmsk_SHIFT);
+ mmesa->hw.stencilctl = SC_smode_salways | SC_sfailop_keep
+ | SC_szfailop_keep | SC_szpassop_keep;
+ mmesa->hw.stencil_enable = 0;
+ mmesa->hw.cull = _CULL_NEGATIVE;
+ mmesa->hw.cull_dualtex = _CULL_POSITIVE;
+ mmesa->hw.specen = 0;
+
mmesa->setup.dwgctl = (DC_opcod_trap |
- DC_atype_i |
DC_linear_xy |
- DC_zmode_nozcmp |
DC_solid_disable |
DC_arzero_disable |
DC_sgnzero_disable |
@@ -1072,16 +1218,15 @@ void mgaInitState( mgaContextPtr mmesa )
AC_atmode_noacmp |
AC_alphasel_fromtex );
- mmesa->setup.fogcolor =
- MGAPACKCOLOR888((GLubyte)(ctx->Fog.Color[0]*255.0F),
- (GLubyte)(ctx->Fog.Color[1]*255.0F),
- (GLubyte)(ctx->Fog.Color[2]*255.0F));
+ 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->new_state = ~0;
+ mmesa->dirty |= MGA_UPLOAD_CONTEXT;
}
@@ -1103,8 +1248,8 @@ void mgaDDInitStateFuncs( GLcontext *ctx )
ctx->Driver.FrontFace = mgaDDCullFaceFrontFace;
ctx->Driver.ColorMask = mgaDDColorMask;
- ctx->Driver.DrawBuffer = mgaDDSetDrawBuffer;
- ctx->Driver.ReadBuffer = mgaDDSetReadBuffer;
+ ctx->Driver.DrawBuffer = mgaDDDrawBuffer;
+ ctx->Driver.ReadBuffer = mgaDDReadBuffer;
ctx->Driver.ClearColor = mgaDDClearColor;
ctx->Driver.ClearDepth = mgaDDClearDepth;
ctx->Driver.LogicOpcode = mgaDDLogicOp;
@@ -1128,4 +1273,6 @@ void mgaDDInitStateFuncs( GLcontext *ctx )
ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable;
ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
+
+ TNL_CONTEXT(ctx)->Driver.RunPipeline = mgaRunPipeline;
}
diff --git a/src/mesa/drivers/dri/mga/mgastate.h b/src/mesa/drivers/dri/mga/mgastate.h
index a9f1039d76..afbe0aaf90 100644
--- a/src/mesa/drivers/dri/mga/mgastate.h
+++ b/src/mesa/drivers/dri/mga/mgastate.h
@@ -29,14 +29,11 @@
#ifndef _MGA_STATE_H
#define _MGA_STATE_H
-
extern void mgaInitState( mgaContextPtr mmesa );
extern void mgaDDInitStateFuncs(GLcontext *ctx);
-extern void mgaDDUpdateHwState( 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/mesa/drivers/dri/mga/mgatex.c b/src/mesa/drivers/dri/mga/mgatex.c
index b4ee787e0b..82eccc8149 100644
--- a/src/mesa/drivers/dri/mga/mgatex.c
+++ b/src/mesa/drivers/dri/mga/mgatex.c
@@ -26,10 +26,7 @@
*/
/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgatex.c,v 1.14 2002/10/30 12:51:36 alanh Exp $ */
-#include <stdlib.h>
-#include <stdio.h>
-#include <GL/gl.h>
-
+#include "glheader.h"
#include "mm.h"
#include "mgacontext.h"
#include "mgatex.h"
@@ -37,9 +34,11 @@
#include "mgatris.h"
#include "mgaioctl.h"
+#include "colormac.h"
+#include "context.h"
#include "enums.h"
#include "simple_list.h"
-/*#include "mem.h"*/
+#include "imports.h"
#include "macros.h"
#include "texformat.h"
#include "texstore.h"
@@ -47,67 +46,72 @@
#include "swrast/swrast.h"
-#define TEX_0 1
-#define TEX_1 2
-
-/*
- * mgaDestroyTexObj
- * Free all memory associated with a texture and NULL any pointers
- * to it.
+/**
+ * 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
*/
-void
-mgaDestroyTexObj( mgaContextPtr mmesa, mgaTextureObjectPtr t )
+
+static void
+mgaSetTexWrapping( mgaTextureObjectPtr t, GLenum swrap, GLenum twrap )
{
- if ( !t ) return;
+ GLboolean is_clamp = GL_FALSE;
+ GLboolean is_clamp_to_edge = GL_FALSE;
- /* free the texture memory */
- if (t->MemBlock) {
- mmFreeMem( t->MemBlock );
- t->MemBlock = 0;
+ t->setup.texctl &= (TMC_clampu_MASK & TMC_clampv_MASK);
+ t->setup.texctl2 &= (TMC_borderen_MASK);
- if (mmesa && t->age > mmesa->dirtyAge)
- mmesa->dirtyAge = t->age;
+ 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__);
}
- /* free mesa's link */
- if (t->tObj)
- t->tObj->DriverData = NULL;
-
- /* see if it was the driver's current object */
- if (mmesa) {
- if (t->bound & TEX_0) mmesa->CurrentTexObj[0] = 0;
- if (t->bound & TEX_1) mmesa->CurrentTexObj[1] = 0;
+ 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__);
}
-
- remove_from_list(t);
- free( t );
-}
+ if ( is_clamp ) {
+ t->setup.texctl2 |= TMC_borderen_enable;
+ }
-/*
- * mgaSetTexWrappings
- */
-static void mgaSetTexWrapping( mgaTextureObjectPtr t,
- GLenum sWrap,
- GLenum tWrap )
-{
- GLuint val = 0;
-
- if (sWrap != GL_REPEAT)
- val |= TMC_clampu_enable;
-
- if (tWrap != GL_REPEAT)
- val |= TMC_clampv_enable;
-
- t->setup.texctl &= ~(TMC_clampu_enable|TMC_clampv_enable);
- t->setup.texctl |= val;
+ t->border_fallback = (is_clamp && is_clamp_to_edge);
}
-/*
- * mgaSetTexFilter
+/**
+ * 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)
+
+static void
+mgaSetTexFilter( mgaTextureObjectPtr t, GLenum minf, GLenum magf )
{
GLuint val = 0;
@@ -136,123 +140,79 @@ static void mgaSetTexFilter(mgaTextureObjectPtr t, GLenum minf, GLenum magf)
}
- t->setup.texfilter &= (TF_minfilter_MASK |
- TF_magfilter_MASK |
+ /* 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;
}
-/*
- * mgaSetTexBorderColor
- */
static void mgaSetTexBorderColor(mgaTextureObjectPtr t, GLubyte color[4])
{
- t->setup.texbordercol = MGAPACKCOLOR8888(color[0],color[1],
- color[2],color[3]);
+ t->setup.texbordercol = PACK_COLOR_8888(color[3], color[0],
+ color[1], color[2] );
}
-static GLint mgaChooseTexFormat( mgaContextPtr mmesa,
- struct gl_texture_image *texImage,
- GLenum format, GLenum type )
+static const struct gl_texture_format *
+mgaChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
+ GLenum format, GLenum type )
{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
const GLboolean do32bpt = mmesa->default32BitTextures;
- const struct gl_texture_format *texFormat;
- GLint ret;
-
- if ( 0 )
- fprintf( stderr, "internal=%s format=%s type=%s\n",
- texImage->IntFormat == 3 ? "GL_RGB (3)" :
- texImage->IntFormat == 4 ? "GL_RGBA (4)" :
- _mesa_lookup_enum_by_nr( texImage->IntFormat ),
- _mesa_lookup_enum_by_nr( format ),
- _mesa_lookup_enum_by_nr( type ) );
-
-#define SET_FORMAT( r, gl ) \
- do { \
- ret = (r); \
- texFormat = &(gl); \
- } while (0)
-
-#define SET_FORMAT_32BPT( r32, gl32, r16, gl16 ) \
- do { \
- if ( do32bpt ) { \
- ret = (r32); \
- texFormat = &(gl32); \
- } else { \
- ret = (r16); \
- texFormat = &(gl16); \
- } \
- } while (0)
-
- switch ( texImage->IntFormat ) {
- /* GH: Bias towards GL_RGB, GL_RGBA texture formats. This has
- * got to be better than sticking them way down the end of this
- * huge list.
- */
+
+ switch ( internalFormat ) {
case 4:
case GL_RGBA:
case GL_COMPRESSED_RGBA:
if ( format == GL_BGRA ) {
if ( type == GL_UNSIGNED_INT_8_8_8_8_REV ) {
- SET_FORMAT( TMC_tformat_tw32, _mesa_texformat_argb8888 );
- break;
- } else if ( type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) {
- SET_FORMAT( TMC_tformat_tw12, _mesa_texformat_argb4444 );
- break;
- } else if ( type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) {
- SET_FORMAT( TMC_tformat_tw15, _mesa_texformat_argb1555 );
- break;
+ return &_mesa_texformat_argb8888;
+ }
+ else if ( type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) {
+ return &_mesa_texformat_argb4444;
+ }
+ else if ( type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) {
+ return &_mesa_texformat_argb1555;
}
}
- SET_FORMAT_32BPT( TMC_tformat_tw32, _mesa_texformat_argb8888,
- TMC_tformat_tw12, _mesa_texformat_argb4444 );
- break;
+ return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
case 3:
case GL_RGB:
case GL_COMPRESSED_RGB:
if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) {
- SET_FORMAT( TMC_tformat_tw16, _mesa_texformat_rgb565 );
- break;
+ return &_mesa_texformat_rgb565;
}
- SET_FORMAT_32BPT( TMC_tformat_tw32, _mesa_texformat_argb8888,
- TMC_tformat_tw16, _mesa_texformat_rgb565 );
- break;
+ return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565;
- /* GH: Okay, keep checking as normal. Still test for GL_RGB,
- * GL_RGBA formats first.
- */
case GL_RGBA8:
case GL_RGB10_A2:
case GL_RGBA12:
case GL_RGBA16:
- SET_FORMAT_32BPT( TMC_tformat_tw32, _mesa_texformat_argb8888,
- TMC_tformat_tw12, _mesa_texformat_argb4444 );
- break;
+ return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
case GL_RGBA4:
case GL_RGBA2:
- SET_FORMAT( TMC_tformat_tw12, _mesa_texformat_argb4444 );
- break;
+ return &_mesa_texformat_argb4444;
case GL_RGB5_A1:
- SET_FORMAT( TMC_tformat_tw15, _mesa_texformat_argb1555 );
- break;
+ return &_mesa_texformat_argb1555;
case GL_RGB8:
case GL_RGB10:
case GL_RGB12:
case GL_RGB16:
- SET_FORMAT_32BPT( TMC_tformat_tw32, _mesa_texformat_argb8888,
- TMC_tformat_tw16, _mesa_texformat_rgb565 );
- break;
+ return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565;
case GL_RGB5:
case GL_RGB4:
case GL_R3_G3_B2:
- SET_FORMAT( TMC_tformat_tw16, _mesa_texformat_rgb565 );
- break;
+ return &_mesa_texformat_rgb565;
case GL_ALPHA:
case GL_ALPHA4:
@@ -261,8 +221,7 @@ static GLint mgaChooseTexFormat( mgaContextPtr mmesa,
case GL_ALPHA16:
case GL_COMPRESSED_ALPHA:
/* FIXME: This will report incorrect component sizes... */
- SET_FORMAT( TMC_tformat_tw12, _mesa_texformat_argb4444 );
- break;
+ return &_mesa_texformat_argb4444;
case 1:
case GL_LUMINANCE:
@@ -272,8 +231,7 @@ static GLint mgaChooseTexFormat( mgaContextPtr mmesa,
case GL_LUMINANCE16:
case GL_COMPRESSED_LUMINANCE:
/* FIXME: This will report incorrect component sizes... */
- SET_FORMAT( TMC_tformat_tw16, _mesa_texformat_rgb565 );
- break;
+ return &_mesa_texformat_rgb565;
case 2:
case GL_LUMINANCE_ALPHA:
@@ -285,8 +243,7 @@ static GLint mgaChooseTexFormat( mgaContextPtr mmesa,
case GL_LUMINANCE16_ALPHA16:
case GL_COMPRESSED_LUMINANCE_ALPHA:
/* FIXME: This will report incorrect component sizes... */
- SET_FORMAT( TMC_tformat_tw12, _mesa_texformat_argb4444 );
- break;
+ return &_mesa_texformat_argb4444;
case GL_INTENSITY:
case GL_INTENSITY4:
@@ -295,8 +252,15 @@ static GLint mgaChooseTexFormat( mgaContextPtr mmesa,
case GL_INTENSITY16:
case GL_COMPRESSED_INTENSITY:
/* FIXME: This will report incorrect component sizes... */
- SET_FORMAT( TMC_tformat_tw12, _mesa_texformat_argb4444 );
- break;
+ return &_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:
@@ -305,502 +269,78 @@ static GLint mgaChooseTexFormat( mgaContextPtr mmesa,
case GL_COLOR_INDEX8_EXT:
case GL_COLOR_INDEX12_EXT:
case GL_COLOR_INDEX16_EXT:
- SET_FORMAT( TMC_tformat_tw8, _mesa_texformat_ci8 );
- break;
+ return &_mesa_texformat_ci8;
default:
- fprintf( stderr, "bad texture format in mgaChooseTexFormat() %d",
- texImage->IntFormat );
- return -1;
+ _mesa_problem( ctx, "unexpected texture format in %s", __FUNCTION__ );
+ return NULL;
}
- texImage->TexFormat = texFormat;
-
- return ret;
+ return NULL; /* never get here */
}
-/*
- * mgaCreateTexObj
+
+
+/**
* 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 void mgaCreateTexObj(mgaContextPtr mmesa,
- struct gl_texture_object *tObj)
-{
- const GLint baseLevel = tObj->BaseLevel;
- struct gl_texture_image *image = tObj->Image[baseLevel];
- mgaTextureObjectPtr t;
- int i, ofs;
- int LastLevel;
- int s, s2;
- int tformat;
-
- if (!image) return;
-
- tObj->DriverData = t = calloc( 1, sizeof( *t ) );
- if (!t) {
- fprintf(stderr, "mgaCreateTexObj: Failed to malloc mgaTextureObject\n" );
- return;
- }
-
- /* FIXME: Use the real DD interface...
- */
- tformat = mgaChooseTexFormat( mmesa, image, image->Format,
- GL_UNSIGNED_BYTE );
- t->texelBytes = image->TexFormat->TexelBytes;
-
- /* We are going to upload all levels that are present, even if
- * later levels wouldn't be used by the current filtering mode. This
- * allows the filtering mode to change without forcing another upload
- * of the images.
- */
- LastLevel = MGA_TEX_MAXLEVELS-1;
-
- ofs = 0;
- for ( i = 0 ; i <= LastLevel ; i++ ) {
- if ( !tObj->Image[i] ) {
- LastLevel = i - 1;
- break;
- }
-
- t->offsets[i] = ofs;
- t->dirty_images |= (1<<i);
-
- ofs += ((MAX2( tObj->Image[i]->Width, 8 ) *
- MAX2( tObj->Image[i]->Height, 8 ) *
- t->texelBytes) + 31) & ~31;
- }
- t->totalSize = ofs;
- t->lastLevel = LastLevel;
- t->tObj = tObj;
- t->ctx = mmesa;
- t->age = 0;
- t->bound = 0;
- t->MemBlock = 0;
-
- insert_at_tail(&(mmesa->SwappedOut), t);
-
-
- /* setup hardware register values */
- t->setup.texctl = TMC_takey_1 | TMC_tamask_0 | tformat;
-
- if (image->WidthLog2 >= 3)
- t->setup.texctl |= ((image->WidthLog2 - 3) << TMC_tpitch_SHIFT);
- else
- t->setup.texctl |= (TMC_tpitchlin_enable |
- (image->Width << TMC_tpitchext_SHIFT));
-
-
- t->setup.texctl2 = TMC_ckstransdis_enable;
-
- if ( mmesa->glCtx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR )
- t->setup.texctl2 |= TMC_specen_enable;
-
-
- t->setup.texfilter = (TF_minfilter_nrst |
- TF_magfilter_nrst |
- TF_filteralpha_enable |
- (0x10 << TF_fthres_SHIFT) |
- (LastLevel << TF_mapnb_SHIFT));
-
- /* warp texture registers */
- ofs = MGA_IS_G200(mmesa) ? 28 : 11;
- s = image->Width;
- s2 = image->WidthLog2;
- t->setup.texwidth = (MGA_FIELD(TW_twmask, s - 1) |
- MGA_FIELD(TW_rfw, (10 - s2 - 8) & 63 ) |
- MGA_FIELD(TW_tw, (s2 + ofs ) | 0x40 ));
-
- s = image->Height;
- s2 = image->HeightLog2;
- t->setup.texheight = (MGA_FIELD(TH_thmask, s - 1) |
- MGA_FIELD(TH_rfh, (10 - s2 - 8) & 63 ) |
- MGA_FIELD(TH_th, (s2 + ofs ) | 0x40 ));
-
-
- /* set all the register values for filtering, border, etc */
- mgaSetTexWrapping( t, tObj->WrapS, tObj->WrapT );
- mgaSetTexFilter( t, tObj->MinFilter, tObj->MagFilter );
- mgaSetTexBorderColor( t, tObj->_BorderChan );
-}
-
-
-
-
-static void mgaUpdateTextureEnvG200( GLcontext *ctx )
+static mgaTextureObjectPtr
+mgaAllocTexObj( struct gl_texture_object *tObj )
{
- struct gl_texture_object *tObj = ctx->Texture.Unit[0]._Current;
mgaTextureObjectPtr t;
- if (!tObj || !tObj->DriverData)
- return;
-
- t = (mgaTextureObjectPtr)tObj->DriverData;
-
- t->setup.texctl2 &= ~TMC_decalblend_enable;
-
- switch (ctx->Texture.Unit[0].EnvMode) {
- case GL_REPLACE:
- t->setup.texctl &= ~TMC_tmodulate_enable;
- break;
- case GL_MODULATE:
- t->setup.texctl |= TMC_tmodulate_enable;
- break;
- case GL_DECAL:
- t->setup.texctl &= ~TMC_tmodulate_enable;
- t->setup.texctl2 |= TMC_decalblend_enable;
- break;
- case GL_BLEND:
- FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE );
- break;
- default:
- break;
- }
-}
-
-static void mgaUpdateTextureEnvG400( GLcontext *ctx, int unit )
-{
- mgaContextPtr mmesa = MGA_CONTEXT( ctx );
- GLuint *reg = ((GLuint *)&mmesa->setup.tdualstage0 + unit);
- GLuint source = mmesa->tmu_source[unit];
- struct gl_texture_object *tObj = ctx->Texture.Unit[source]._Current;
- GLenum format;
-
- if ( tObj != ctx->Texture.Unit[source].Current2D || !tObj )
- return;
-
- format = tObj->Image[tObj->BaseLevel]->Format;
-
- switch (ctx->Texture.Unit[source].EnvMode) {
- case GL_REPLACE:
- if (format == GL_RGB || format == GL_LUMINANCE) {
- *reg = (TD0_color_sel_arg1 |
- TD0_alpha_arg2_diffuse |
- TD0_alpha_sel_arg2 );
- }
- else if (format == GL_ALPHA) {
- *reg = (TD0_color_sel_arg2 |
- TD0_color_arg2_diffuse |
- TD0_alpha_sel_arg1 );
- }
- else {
- *reg = (TD0_color_sel_arg1 |
- TD0_alpha_sel_arg1 );
- }
- break;
-
- case GL_MODULATE:
- if (unit == 0) {
- *reg = ( TD0_color_arg2_diffuse |
- TD0_color_sel_mul |
- TD0_alpha_arg2_diffuse |
- TD0_alpha_sel_mul);
- }
- else {
- *reg = ( TD0_color_arg2_prevstage |
- TD0_color_alpha_prevstage |
- TD0_color_sel_mul |
- TD0_alpha_arg2_prevstage |
- TD0_alpha_sel_mul);
- }
- break;
- case GL_DECAL:
- if (format == GL_RGB) {
- if (unit == 0) {
- *reg = (TD0_color_sel_arg1 |
- TD0_alpha_arg2_diffuse |
- TD0_alpha_sel_arg2 );
- }
- else {
- *reg = (TD0_color_sel_arg1 |
- TD0_alpha_arg2_prevstage |
- TD0_alpha_sel_arg2 );
- }
- }
- else if ( format == GL_RGBA ) {
-#if 0
- if (unit == 0) {
- /* this doesn't work */
- *reg = (TD0_color_arg2_diffuse |
- TD0_color_alpha_currtex |
- TD0_color_alpha2inv_enable |
- TD0_color_arg2mul_alpha2 |
- TD0_color_arg1mul_alpha1 |
- TD0_color_blend_enable |
- TD0_color_arg1add_mulout |
- TD0_color_arg2add_mulout |
- TD0_color_add_add |
- TD0_color_sel_mul |
- TD0_alpha_arg2_diffuse |
- TD0_alpha_sel_arg2 );
- }
- else {
- *reg = (TD0_color_arg2_prevstage |
- TD0_color_alpha_currtex |
- TD0_color_alpha2inv_enable |
- TD0_color_arg2mul_alpha2 |
- TD0_color_arg1mul_alpha1 |
- TD0_color_add_add |
- TD0_color_sel_add |
- TD0_alpha_arg2_prevstage |
- TD0_alpha_sel_arg2 );
- }
-#else
- /* s/w fallback, pretty sure we can't do in h/w */
- FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE );
- if ( MGA_DEBUG & DEBUG_VERBOSE_FALLBACK )
- fprintf( stderr, "FALLBACK: GL_DECAL RGBA texture, unit=%d\n",
- unit );
-#endif
- }
- else {
- if (unit == 0) {
- *reg = ( TD0_color_arg2_diffuse |
- TD0_color_sel_arg2 |
- TD0_alpha_arg2_diffuse |
- TD0_alpha_sel_arg2);
- }
- else {
- *reg = ( TD0_color_arg2_prevstage |
- TD0_color_sel_arg2 |
- TD0_alpha_arg2_prevstage |
- TD0_alpha_sel_arg2);
- }
- }
- break;
-
- case GL_ADD:
- if (unit == 0) {
- if (format == GL_INTENSITY)
- *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 if (format == GL_ALPHA)
- *reg = ( TD0_color_arg2_diffuse |
- TD0_color_sel_mul |
- TD0_alpha_arg2_diffuse |
- TD0_alpha_sel_mul);
- else
- *reg = ( TD0_color_arg2_diffuse |
- TD0_color_add_add |
- TD0_color_sel_add |
- TD0_alpha_arg2_diffuse |
- TD0_alpha_sel_mul);
- }
- else {
- if (format == GL_INTENSITY) {
- *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);
- }
- else if (format == GL_ALPHA) {
- *reg = ( TD0_color_arg2_prevstage |
- TD0_color_sel_mul |
- TD0_alpha_arg2_prevstage |
- TD0_alpha_sel_mul);
- }
- else {
- *reg = ( TD0_color_arg2_prevstage |
- TD0_color_alpha_prevstage |
- TD0_color_add_add |
- TD0_color_sel_add |
- TD0_alpha_arg2_prevstage |
- TD0_alpha_sel_mul);
- }
- }
- break;
-
- case GL_BLEND:
- if (format == GL_ALPHA) {
- *reg = ( TD0_color_arg2_diffuse |
- TD0_color_sel_mul |
- TD0_alpha_arg2_diffuse |
- TD0_alpha_sel_mul);
- }
- else {
- FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE );
- if ( MGA_DEBUG & DEBUG_VERBOSE_FALLBACK )
- fprintf( stderr, "FALLBACK: GL_BLEND envcolor=0x%08x\n",
- mmesa->envcolor );
-
- /* Do singletexture GL_BLEND with 'all ones' env-color
- * by using both texture units. Multitexture gl_blend
- * is a fallback.
- */
- if (unit == 0) {
- /* Part 1: R1 = Rf ( 1 - Rt )
- * A1 = Af At
- */
- *reg = ( TD0_color_arg2_diffuse |
- TD0_color_arg1_inv_enable |
- TD0_color_sel_mul |
- TD0_alpha_arg2_diffuse |
- TD0_alpha_sel_arg1);
- } else {
- /* Part 2: R2 = R1 + Rt
- * A2 = A1
- */
- *reg = ( TD0_color_arg2_prevstage |
- TD0_color_add_add |
- TD0_color_sel_add |
- TD0_alpha_arg2_prevstage |
- TD0_alpha_sel_arg2);
- }
- }
- break;
- default:
- break;
- }
-}
-
-
-
-static void mgaUpdateTextureObject( GLcontext *ctx, int hw_unit )
-{
- mgaTextureObjectPtr t;
- struct gl_texture_object *tObj;
- GLuint enabled;
- mgaContextPtr mmesa = MGA_CONTEXT( ctx );
- GLuint gl_unit = mmesa->tmu_source[hw_unit];
-
-
- enabled = ctx->Texture.Unit[gl_unit]._ReallyEnabled;
- tObj = ctx->Texture.Unit[gl_unit]._Current;
-
- if (enabled != TEXTURE_2D_BIT) {
- if (enabled)
- FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE );
- return;
- }
-
- if (tObj->Image[tObj->BaseLevel]->Border > 0) {
- FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE );
- if ( MGA_DEBUG & DEBUG_VERBOSE_FALLBACK )
- fprintf( stderr, "FALLBACK: texture border\n" );
- return;
- }
-
- if ( !tObj->DriverData ) {
- mgaCreateTexObj( mmesa, tObj );
- if ( !tObj->DriverData ) {
- FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE );
- return;
- }
- }
-
- t = (mgaTextureObjectPtr)tObj->DriverData;
-
- if (t->dirty_images)
- mmesa->dirty |= (MGA_UPLOAD_TEX0IMAGE << hw_unit);
-
- mmesa->CurrentTexObj[hw_unit] = t;
- t->bound |= hw_unit+1;
-
-/* if (t->MemBlock) */
-/* mgaUpdateTexLRU( mmesa, t ); */
-
- t->setup.texctl2 &= ~TMC_dualtex_enable;
- if ((ctx->Texture.Unit[0]._ReallyEnabled == TEXTURE_2D_BIT) &&
- (ctx->Texture.Unit[1]._ReallyEnabled == TEXTURE_2D_BIT))
- t->setup.texctl2 |= TMC_dualtex_enable;
-
- t->setup.texctl2 &= ~TMC_specen_enable;
- if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
- t->setup.texctl2 |= TMC_specen_enable;
-}
-
-
+ 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_minfilter_nrst
+ | TF_magfilter_nrst
+ | TF_filteralpha_enable
+ | TF_uvoffset_OGL);
+ t->border_fallback = GL_FALSE;
-/* The G400 is now programmed quite differently wrt texture environment.
- */
-void mgaUpdateTextureState( GLcontext *ctx )
-{
- mgaContextPtr mmesa = MGA_CONTEXT( ctx );
- FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_FALSE );
+ make_empty_list( & t->base );
- if (mmesa->CurrentTexObj[0]) {
- mmesa->CurrentTexObj[0]->bound = 0;
- mmesa->CurrentTexObj[0] = 0;
- }
-
- if (mmesa->CurrentTexObj[1]) {
- mmesa->CurrentTexObj[1]->bound = 0;
- mmesa->CurrentTexObj[1] = 0;
- }
-
- if (ctx->Texture.Unit[1]._ReallyEnabled == TEXTURE_2D_BIT) {
- mmesa->tmu_source[0] = 1;
- } else {
- mmesa->tmu_source[0] = 0;
- }
-
- if (MGA_IS_G400(mmesa)) {
- mgaUpdateTextureObject( ctx, 0 );
- mgaUpdateTextureEnvG400( ctx, 0 );
-
- mmesa->setup.tdualstage1 = mmesa->setup.tdualstage0;
-
- if ((ctx->Texture.Unit[0]._ReallyEnabled == TEXTURE_2D_BIT) &&
- (ctx->Texture.Unit[1]._ReallyEnabled == TEXTURE_2D_BIT)) {
- mgaUpdateTextureObject( ctx, 1 );
- mgaUpdateTextureEnvG400( ctx, 1 );
- mmesa->dirty |= MGA_UPLOAD_TEX1;
- }
- } else {
- mgaUpdateTextureObject( ctx, 0 );
- mgaUpdateTextureEnvG200( ctx );
+ mgaSetTexWrapping( t, tObj->WrapS, tObj->WrapT );
+ mgaSetTexFilter( t, tObj->MinFilter, tObj->MagFilter );
+ mgaSetTexBorderColor( t, tObj->_BorderChan );
}
- mmesa->dirty |= MGA_UPLOAD_CONTEXT | MGA_UPLOAD_TEX0;
-
- mmesa->setup.dwgctl &= DC_opcod_MASK;
- mmesa->setup.dwgctl |= (ctx->Texture.Unit[0]._ReallyEnabled
- ? DC_opcod_texture_trap
- : DC_opcod_trap);
+ return( t );
}
-
-
static void mgaDDTexEnv( 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);
- if (pname == GL_TEXTURE_ENV_MODE) {
- /* force the texture state to be updated */
- FLUSH_BATCH( MGA_CONTEXT(ctx) );
- MGA_CONTEXT(ctx)->new_state |= (MGA_NEW_TEXTURE |
- MGA_NEW_ALPHA);
- }
- else if (pname == GL_TEXTURE_ENV_COLOR)
- {
- struct gl_texture_unit *texUnit =
- &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
- GLfloat *fc = texUnit->EnvColor;
+ switch( pname ) {
+ case GL_TEXTURE_ENV_COLOR: {
GLubyte c[4];
- GLuint col;
+ GLuint envColor;
- COPY_4V(c, fc);
- col = mgaPackColor( mmesa->mgaScreen->cpp, c[0], c[1], c[2], c[3] );
- mmesa->envcolor = (c[3]<<24) | (c[0]<<16) | (c[1]<<8) | (c[2]);
+ UNCLAMPED_FLOAT_TO_RGBA_CHAN( c, texUnit->EnvColor );
+ envColor = mgaPackColor( mmesa->mgaScreen->cpp, c[0], c[1], c[2], c[3] );
+ mmesa->envcolor = PACK_COLOR_8888( c[3], c[0], c[1], c[2] );
- if (mmesa->setup.fcol != col) {
+ if (mmesa->setup.fcol != envColor) {
FLUSH_BATCH(mmesa);
- mmesa->setup.fcol = col;
+ mmesa->setup.fcol = envColor;
mmesa->dirty |= MGA_UPLOAD_CONTEXT;
mmesa->blend_flags &= ~MGA_BLEND_ENV_COLOR;
@@ -814,6 +354,8 @@ static void mgaDDTexEnv( GLcontext *ctx, GLenum target,
if (mmesa->envcolor != 0x0 && mmesa->envcolor != 0xffffffff)
mmesa->blend_flags |= MGA_BLEND_ENV_COLOR;
}
+ break;
+ }
}
}
@@ -826,14 +368,26 @@ static void mgaTexImage2D( GLcontext *ctx, GLenum target, GLint level,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
- mgaTextureObjectPtr t = (mgaTextureObjectPtr) texObj->DriverData;
- if (t) {
- mgaDestroyTexObj( MGA_CONTEXT(ctx), t );
- texObj->DriverData = 0;
+ 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,
@@ -847,44 +401,59 @@ static void mgaTexSubImage2D( GLcontext *ctx,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
- mgaTextureObjectPtr t = (mgaTextureObjectPtr) texObj->DriverData;
- if (t) {
- mgaDestroyTexObj( MGA_CONTEXT(ctx), t );
- texObj->DriverData = 0;
+ driTextureObject * t = (driTextureObject *) texObj->DriverData;
+
+
+ assert( t != NULL ); /* 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);
}
-
-
-/*
- * mgaTexParameter
- * This just changes variables and flags for a state update, which
- * will happen at the next mgaUpdateTextureState
+/**
+ * Changes variables and flags for a state update, which will happen at the
+ * next UpdateTextureState
*/
+
static void
mgaDDTexParameter( GLcontext *ctx, GLenum target,
struct gl_texture_object *tObj,
GLenum pname, const GLfloat *params )
{
- mgaContextPtr mmesa = MGA_CONTEXT( ctx );
+ mgaContextPtr mmesa = MGA_CONTEXT( ctx );
mgaTextureObjectPtr t;
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 || !t->bound || target != GL_TEXTURE_2D ) {
+ /* 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) ) {
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 );
@@ -898,14 +467,24 @@ mgaDDTexParameter( GLcontext *ctx, GLenum target,
case GL_TEXTURE_BORDER_COLOR:
FLUSH_BATCH(mmesa);
- mgaSetTexBorderColor(t,tObj->_BorderChan);
+ 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;
}
-
- mmesa->new_state |= MGA_NEW_TEXTURE;
}
@@ -913,19 +492,11 @@ static void
mgaDDBindTexture( GLcontext *ctx, GLenum target,
struct gl_texture_object *tObj )
{
- mgaContextPtr mmesa = MGA_CONTEXT( ctx );
- int unit = ctx->Texture.CurrentUnit;
-
- FLUSH_BATCH(mmesa);
-
- if (mmesa->CurrentTexObj[unit]) {
- mmesa->CurrentTexObj[unit]->bound &= ~(unit+1);
- mmesa->CurrentTexObj[unit] = 0;
+ if ( target == GL_TEXTURE_2D ) {
+ if ( tObj->DriverData == NULL ) {
+ mgaAllocTexObj( tObj );
+ }
}
-
- /* force the texture state to be updated
- */
- MGA_CONTEXT(ctx)->new_state |= MGA_NEW_TEXTURE;
}
@@ -933,53 +504,48 @@ static void
mgaDDDeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj )
{
mgaContextPtr mmesa = MGA_CONTEXT( ctx );
- mgaTextureObjectPtr t = (mgaTextureObjectPtr)tObj->DriverData;
+ driTextureObject * t = (driTextureObject *) tObj->DriverData;
if ( t ) {
- if (mmesa) {
- if (t->bound) {
- FLUSH_BATCH(mmesa);
- if (t->bound & TEX_0) mmesa->CurrentTexObj[0] = 0;
- if (t->bound & TEX_1) mmesa->CurrentTexObj[1] = 0;
- }
- mmesa->new_state |= MGA_NEW_TEXTURE;
+ if ( mmesa ) {
+ FLUSH_BATCH( mmesa );
}
- mgaDestroyTexObj( mmesa, t );
+ driDestroyTextureObject( t );
}
}
-static GLboolean
-mgaDDIsTextureResident( GLcontext *ctx, struct gl_texture_object *t )
-{
- mgaTextureObjectPtr mt = (mgaTextureObjectPtr)t->DriverData;
- return mt && mt->MemBlock;
-}
-
-
void
mgaDDInitTextureFuncs( GLcontext *ctx )
{
- ctx->Driver.TexEnv = mgaDDTexEnv;
-
- ctx->Driver.ChooseTextureFormat = _mesa_choose_tex_format;
- ctx->Driver.TexImage1D = _mesa_store_teximage1d;
- ctx->Driver.TexImage2D = mgaTexImage2D;
- ctx->Driver.TexImage3D = _mesa_store_teximage3d;
- ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d;
- ctx->Driver.TexSubImage2D = mgaTexSubImage2D;
- ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
- ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d;
- ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d;
- ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d;
- ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d;
- ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d;
- ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage;
-
- ctx->Driver.BindTexture = mgaDDBindTexture;
- ctx->Driver.DeleteTexture = mgaDDDeleteTexture;
- ctx->Driver.TexParameter = mgaDDTexParameter;
- ctx->Driver.UpdateTexturePalette = 0;
- ctx->Driver.IsTextureResident = mgaDDIsTextureResident;
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+
+
+ ctx->Driver.ChooseTextureFormat = mgaChooseTextureFormat;
+ ctx->Driver.TexImage1D = _mesa_store_teximage1d;
+ ctx->Driver.TexImage2D = mgaTexImage2D;
+ ctx->Driver.TexImage3D = _mesa_store_teximage3d;
+ ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d;
+ ctx->Driver.TexSubImage2D = mgaTexSubImage2D;
+ ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
+ ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d;
+ ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d;
+ ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d;
+ ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d;
+ ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d;
+ ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage;
+
+ ctx->Driver.BindTexture = mgaDDBindTexture;
+ ctx->Driver.CreateTexture = NULL; /* FIXME: Is this used??? */
+ ctx->Driver.DeleteTexture = mgaDDDeleteTexture;
+ ctx->Driver.IsTextureResident = driIsTextureResident;
+ ctx->Driver.PrioritizeTexture = NULL;
+ ctx->Driver.ActiveTexture = NULL;
+ ctx->Driver.UpdateTexturePalette = NULL;
+
+ ctx->Driver.TexEnv = mgaDDTexEnv;
+ ctx->Driver.TexParameter = mgaDDTexParameter;
+
+ driInitTextureObjects( ctx, & mmesa->swapped, DRI_TEXMGR_DO_TEXTURE_2D );
}
diff --git a/src/mesa/drivers/dri/mga/mgatex.h b/src/mesa/drivers/dri/mga/mgatex.h
index c9f87d997e..282577e9f8 100644
--- a/src/mesa/drivers/dri/mga/mgatex.h
+++ b/src/mesa/drivers/dri/mga/mgatex.h
@@ -40,23 +40,10 @@ typedef struct mga_texture_object_s *mgaTextureObjectPtr;
*/
void mgaUpdateTextureState( GLcontext *ctx );
-void mgaConvertTexture( GLuint *dest, int texelBytes,
- struct gl_texture_image *image,
- int x, int y, int width, int height );
-
-
-void mgaUploadSubImageLocked( mgaContextPtr mmesa,
- mgaTextureObjectPtr t,
- int level,
- int x, int y, int width, int height );
-
int mgaUploadTexImages( mgaContextPtr mmesa, mgaTextureObjectPtr t );
void mgaDestroyTexObj( mgaContextPtr mmesa, mgaTextureObjectPtr t );
-void mgaAgeTextures( mgaContextPtr mmesa, int heap );
-
void mgaDDInitTextureFuncs( GLcontext *ctx );
-
#endif
diff --git a/src/mesa/drivers/dri/mga/mgatexmem.c b/src/mesa/drivers/dri/mga/mgatexmem.c
index 7dbdbc582f..4e7fd6b24b 100644
--- a/src/mesa/drivers/dri/mga/mgatexmem.c
+++ b/src/mesa/drivers/dri/mga/mgatexmem.c
@@ -26,539 +26,257 @@
*/
/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgatexmem.c,v 1.7 2002/10/30 12:51:36 alanh Exp $ */
-#include <stdlib.h>
-#include <stdio.h>
-#include <GL/gl.h>
+#include "glheader.h"
#include "mm.h"
#include "mgacontext.h"
#include "mgatex.h"
#include "mgaregs.h"
#include "mgaioctl.h"
+#include "mga_xmesa.h"
-/*#include "mem.h" */
+#include "imports.h"
#include "simple_list.h"
-static void
-mgaSwapOutTexObj(mgaContextPtr mmesa, mgaTextureObjectPtr t)
-{
- if (t->MemBlock) {
- mmFreeMem(t->MemBlock);
- t->MemBlock = 0;
-
- if (t->age > mmesa->dirtyAge)
- mmesa->dirtyAge = t->age;
- }
-
- t->dirty_images = ~0;
- move_to_tail(&(mmesa->SwappedOut), t);
-}
-
-static void
-mgaPrintLocalLRU( mgaContextPtr mmesa, int heap )
-{
- mgaTextureObjectPtr t;
- int sz = 1 << (mmesa->mgaScreen->logTextureGranularity[heap]);
-
- fprintf(stderr, "\nLocal LRU, heap %d:\n", heap);
-
- foreach( t, &(mmesa->TexObjList[heap]) ) {
- if (!t->tObj)
- fprintf(stderr, "Placeholder %d at %x sz %x\n",
- t->MemBlock->ofs / sz,
- t->MemBlock->ofs,
- t->MemBlock->size);
- else
- fprintf(stderr, "Texture (bound %d) at %x sz %x\n",
- t->bound,
- t->MemBlock->ofs,
- t->MemBlock->size);
- }
-
- fprintf(stderr, "\n\n");
-}
-
-static void
-mgaPrintGlobalLRU( mgaContextPtr mmesa, int heap )
+/**
+ * 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 )
{
- int i, j;
- drmTextureRegion *list = mmesa->sarea->texList[heap];
+ unsigned i;
- fprintf(stderr, "\nGlobal LRU, heap %d list %p:\n", heap, list);
- for (i = 0, j = MGA_NR_TEX_REGIONS ; i < MGA_NR_TEX_REGIONS ; i++) {
- fprintf(stderr, "list[%d] age %d next %d prev %d\n",
- j, list[j].age, list[j].next, list[j].prev);
- j = list[j].next;
- if (j == MGA_NR_TEX_REGIONS) break;
- }
+ /* See if it was the driver's current object.
+ */
- if (j != MGA_NR_TEX_REGIONS) {
- fprintf(stderr, "Loop detected in global LRU\n\n\n");
- for (i = 0 ; i < MGA_NR_TEX_REGIONS ; i++) {
- fprintf(stderr, "list[%d] age %d next %d prev %d\n",
- i, list[i].age, list[i].next, list[i].prev);
- }
- }
+ if ( mmesa != NULL )
+ {
+ if ( t->age > mmesa->dirtyAge )
+ mmesa->dirtyAge = t->age;
- fprintf(stderr, "\n\n");
+ for ( i = 0 ; i < mmesa->glCtx->Const.MaxTextureUnits ; i++ )
+ {
+ if ( t == mmesa->CurrentTexObj[ i ] ) {
+ mmesa->CurrentTexObj[ i ] = NULL;
+ }
+ }
+ }
}
-static void mgaResetGlobalLRU( mgaContextPtr mmesa, GLuint heap )
+/**
+ * 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 )
{
- drmTextureRegion *list = mmesa->sarea->texList[heap];
- int sz = 1 << mmesa->mgaScreen->logTextureGranularity[heap];
- int i;
-
- mmesa->texAge[heap] = ++mmesa->sarea->texAge[heap];
+ struct gl_texture_image * texImage;
+ unsigned offset;
+ unsigned texelBytes;
+ unsigned length;
+ const int level = hwlevel + t->base.firstLevel;
- if (0) fprintf(stderr, "mgaResetGlobalLRU %d\n", (int)heap);
- /* (Re)initialize the global circular LRU list. The last element
- * in the array (MGA_NR_TEX_REGIONS) is the sentinal. Keeping it
- * at the end of the array allows it to be addressed rationally
- * when looking up objects at a particular location in texture
- * memory.
- */
- for (i = 0 ; (i+1) * sz <= mmesa->mgaScreen->textureSize[heap] ; i++) {
- list[i].prev = i-1;
- list[i].next = i+1;
- list[i].age = mmesa->sarea->texAge[heap];
+ 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;
}
- i--;
- list[0].prev = MGA_NR_TEX_REGIONS;
- list[i].prev = i-1;
- list[i].next = MGA_NR_TEX_REGIONS;
- list[MGA_NR_TEX_REGIONS].prev = i;
- list[MGA_NR_TEX_REGIONS].next = 0;
-
-}
-
-
-static void mgaUpdateTexLRU( mgaContextPtr mmesa, mgaTextureObjectPtr t )
-{
- int i;
- int heap = t->heap;
- int logsz = mmesa->mgaScreen->logTextureGranularity[heap];
- int start = t->MemBlock->ofs >> logsz;
- int end = (t->MemBlock->ofs + t->MemBlock->size - 1) >> logsz;
- drmTextureRegion *list = mmesa->sarea->texList[heap];
-
- mmesa->texAge[heap] = ++mmesa->sarea->texAge[heap];
-
- if (!t->MemBlock) {
- fprintf(stderr, "no memblock\n\n");
+ texImage = t->base.tObj->Image[level];
+ if ( texImage == NULL ) {
+ fprintf( stderr, "[%s:%d] Image[%d] = NULL\n", __FILE__, __LINE__,
+ level );
return;
}
- /* Update our local LRU
- */
- move_to_head( &(mmesa->TexObjList[heap]), t );
-
-
- if (0)
- fprintf(stderr, "mgaUpdateTexLRU heap %d list %p\n", heap, list);
-
- /* Update the global LRU
- */
- for (i = start ; i <= end ; i++) {
-
- list[i].in_use = 1;
- list[i].age = mmesa->texAge[heap];
-
- /* remove_from_list(i)
- */
- list[(unsigned)list[i].next].prev = list[i].prev;
- list[(unsigned)list[i].prev].next = list[i].next;
-
- /* insert_at_head(list, i)
- */
- list[i].prev = MGA_NR_TEX_REGIONS;
- list[i].next = list[MGA_NR_TEX_REGIONS].next;
- list[(unsigned)list[MGA_NR_TEX_REGIONS].next].prev = i;
- list[MGA_NR_TEX_REGIONS].next = i;
- }
-
- if (0) {
- mgaPrintGlobalLRU(mmesa, t->heap);
- mgaPrintLocalLRU(mmesa, t->heap);
+ if (texImage->Data == NULL) {
+ fprintf(stderr, "null texture image data tObj %p level %d\n",
+ t->base.tObj, level);
+ return;
}
-}
-
-/* Called for every shared texture region which has increased in age
- * since we last held the lock.
- *
- * Figures out which of our textures have been ejected by other clients,
- * and pushes a placeholder texture onto the LRU list to represent
- * the other client's textures.
- */
-static void mgaTexturesGone( mgaContextPtr mmesa,
- GLuint heap,
- GLuint offset,
- GLuint size,
- GLuint in_use )
-{
- mgaTextureObjectPtr t, tmp;
-
-
- foreach_s ( t, tmp, &(mmesa->TexObjList[heap]) ) {
- if (t->MemBlock->ofs >= offset + size ||
- t->MemBlock->ofs + t->MemBlock->size <= offset)
- continue;
-
-
-
-
- /* It overlaps - kick it off. Need to hold onto the currently bound
- * objects, however.
- */
- if (t->bound)
- mgaSwapOutTexObj( mmesa, t );
- else
- mgaDestroyTexObj( mmesa, t );
+ /* find the proper destination offset for this level */
+ if ( MGA_IS_G200(mmesa) ) {
+ offset = (t->base.memBlock->ofs + t->offsets[hwlevel]);
}
+ else {
+ unsigned i;
-
- if (in_use) {
- t = (mgaTextureObjectPtr) calloc(1, sizeof(*t));
- if (!t) return;
-
- t->heap = heap;
- t->MemBlock = mmAllocMem( mmesa->texHeap[heap], size, 0, offset);
- if (!t->MemBlock) {
- fprintf(stderr, "Couldn't alloc placeholder sz %x ofs %x\n",
- (int)size, (int)offset);
- mmDumpMemInfo( mmesa->texHeap[heap]);
- return;
+ offset = t->base.memBlock->ofs;
+ for ( i = 0 ; i < hwlevel ; i++ ) {
+ offset += (t->offsets[1] >> (i * 2));
}
- insert_at_head( &(mmesa->TexObjList[heap]), t );
- }
-}
-
-
-void mgaAgeTextures( mgaContextPtr mmesa, int heap )
-{
- MGASAREAPrivPtr sarea = mmesa->sarea;
- int sz = 1 << (mmesa->mgaScreen->logTextureGranularity[heap]);
- int idx, nr = 0;
- /* Have to go right round from the back to ensure stuff ends up
- * LRU in our local list... Fix with a cursor pointer.
- */
- for (idx = sarea->texList[heap][MGA_NR_TEX_REGIONS].prev ;
- idx != MGA_NR_TEX_REGIONS && nr < MGA_NR_TEX_REGIONS ;
- idx = sarea->texList[heap][idx].prev, nr++)
- {
- /* If switching texturing schemes, then the SAREA might not
- * have been properly cleared, so we need to reset the
- * global texture LRU.
+ /* Each mipmap must be DWORD aligned.
*/
- if ( idx * sz > mmesa->mgaScreen->textureSize[heap] ) {
- nr = MGA_NR_TEX_REGIONS;
- break;
- }
-
- if (sarea->texList[heap][idx].age > mmesa->texAge[heap]) {
- mgaTexturesGone(mmesa, heap, idx * sz, sz,
- sarea->texList[heap][idx].in_use);
- }
- }
-
- if (nr == MGA_NR_TEX_REGIONS) {
- mgaTexturesGone(mmesa, heap, 0,
- mmesa->mgaScreen->textureSize[heap], 0);
- mgaResetGlobalLRU( mmesa, heap );
+ offset &= ~0x03;
}
- if (0) {
- mgaPrintGlobalLRU( mmesa, heap );
- mgaPrintLocalLRU( mmesa, heap );
- }
-
- mmesa->texAge[heap] = sarea->texAge[heap];
- mmesa->dirty |= MGA_UPLOAD_TEX0IMAGE | MGA_UPLOAD_TEX1IMAGE;
-}
-
-/*
- * mgaUploadSubImageLocked
- *
- * Perform an iload based update of a resident buffer. This is used for
- * both initial loading of the entire image, and texSubImage updates.
- *
- * Performed with the hardware lock held.
- */
-void mgaUploadSubImageLocked( mgaContextPtr mmesa,
- mgaTextureObjectPtr t,
- int level,
- int x, int y, int width, int height )
-{
- int x2;
- int dwords;
- int offset;
- struct gl_texture_image *image;
- int texelBytes, texelsPerDword, texelMaccess, length;
-
- if ( level < 0 || level >= MGA_TEX_MAXLEVELS )
- return;
+ /* Copy the texture from system memory to a memory space that can be
+ * directly used by the hardware for texturing.
+ */
- image = t->tObj->Image[level];
- if ( !image ) return;
+ 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;
- if (image->Data == 0) {
- fprintf(stderr, "null texture image data tObj %p level %d\n",
- t->tObj, level);
- return;
- }
+ /* 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 );
- /* find the proper destination offset for this level */
- offset = (t->MemBlock->ofs +
- t->offsets[level]);
-
-
- texelBytes = t->texelBytes;
- switch( texelBytes ) {
- case 1:
- texelsPerDword = 4;
- texelMaccess = 0;
- break;
- case 2:
- texelsPerDword = 2;
- texelMaccess = 1;
- break;
- case 4:
- texelsPerDword = 1;
- texelMaccess = 2;
- break;
- default:
- return;
- }
+ /* 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 );
- /* We can't do a subimage update if pitch is < 32 texels due
- * to hardware XY addressing limits, so we will need to
- * linearly upload all modified rows.
- */
- if ( image->Width < 32 ) {
- x = 0;
- width = image->Width * height;
- height = 1;
-
- /* Assume that 1x1 textures aren't going to cause a
- * bus error if we read up to four texels from that
- * location:
- */
-/* if ( width < texelsPerDword ) { */
-/* width = texelsPerDword; */
-/* } */
- } else {
- /* pad the size out to dwords. The image is a pointer
- to the entire image, so we can safely reference
- outside the x,y,width,height bounds if we need to */
- x2 = x + width;
- x2 = (x2 + (texelsPerDword-1)) & ~(texelsPerDword-1);
- x = (x + (texelsPerDword-1)) & ~(texelsPerDword-1);
- width = x2 - x;
- }
+ if ( MGA_DEBUG & DEBUG_VERBOSE_TEXTURE )
+ fprintf(stderr, "[%s:%d] address/size = 0x%08lx/%d\n",
+ __FILE__, __LINE__,
+ (long) (offset + tex_offset),
+ to_copy );
- /* we may not be able to upload the entire texture in one
- batch due to register limits or dma buffer limits.
- Recursively split it up. */
- while ( 1 ) {
- dwords = height * width / texelsPerDword;
- if ( dwords * 4 <= MGA_BUFFER_SIZE ) {
- break;
+ mgaFireILoadLocked( mmesa, offset + tex_offset, to_copy );
+ tex_offset += to_copy;
+ length -= to_copy;
}
-
- mgaUploadSubImageLocked( mmesa, t, level, x, y,
- width, height >> 1 );
- y += ( height >> 1 );
- height -= ( height >> 1 );
- }
-
- length = dwords * 4;
-
- /* Fill in the secondary buffer with properly converted texels
- * from the mesa buffer. */
- /* FIXME: the sync for direct copy reduces speed.. */
- if(t->heap == MGA_CARD_HEAP ) {
- mgaGetILoadBufferLocked( mmesa );
- mgaConvertTexture( (GLuint *)mmesa->iload_buffer->address,
- texelBytes, image, x, y, width, height );
- if(length < 64) length = 64;
-
- if (0)
- fprintf(stderr, "TexelBytes : %d, offset: %d, length : %d\n",
- texelBytes,
- mmesa->mgaScreen->textureOffset[t->heap] +
- offset +
- y * width * 4/texelsPerDword,
- length);
-
- mgaFireILoadLocked( mmesa,
- mmesa->mgaScreen->textureOffset[t->heap] +
- offset +
- y * width * 4/texelsPerDword,
- length);
} 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);
- mgaConvertTexture( (GLuint *)
- (mmesa->mgaScreen->texVirtual[t->heap] +
- offset +
- y * width * 4/texelsPerDword),
- texelBytes, image, x, y, width, height );
- }
-}
-
-
-static void mgaUploadTexLevel( mgaContextPtr mmesa,
- mgaTextureObjectPtr t,
- int l )
-{
- mgaUploadSubImageLocked( mmesa,
- t,
- l,
- 0, 0,
- t->tObj->Image[l]->Width,
- t->tObj->Image[l]->Height);
-}
-
-
-
-
-#if 0
-static void mgaMigrateTexture( mgaContextPtr mmesa, mgaTextureObjectPtr t )
-{
- /* NOT DONE */
-}
-#endif
-
-
-static int mgaChooseTexHeap( mgaContextPtr mmesa, mgaTextureObjectPtr t )
-{
- int freeagp, freecard;
- int fitincard, fitinagp;
- int totalcard, totalagp;
- TMemBlock *b;
-
- totalcard = totalagp = fitincard = fitinagp = freeagp = freecard = 0;
-
- b = mmesa->texHeap[0];
- while(b)
- {
- totalcard += b->size;
- if(b->free) if(t->totalSize <= b->size)fitincard = 1;
- b = b->next;
- }
-
- b = mmesa->texHeap[1];
- while(b)
- {
- totalagp += b->size;
- if(b->free) if(t->totalSize <= b->size)fitinagp = 1;
- b = b->next;
- }
- if(fitincard)return 0;
- if(fitinagp)return 1;
+ memcpy( mmesa->mgaScreen->texVirtual[t->base.heap->heapId] + offset,
+ texImage->Data, length );
- if(totalcard && totalagp)
- {
- int ages;
- int ratio = (totalcard > totalagp) ? totalcard / totalagp : totalagp / totalcard;
- ages = mmesa->sarea->texAge[0] + mmesa->sarea->texAge[1];
- if( (ages % ratio) == 0)return totalcard > totalagp ? 1 : 0;
- else return totalcard > totalagp ? 0 : 1;
+ 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);
}
-
- if(totalagp) return 1;
- return 0;
}
+/**
+ * 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 heap;
int i;
int ofs;
- heap = t->heap = mgaChooseTexHeap( mmesa, t );
- /* Do we need to eject LRU texture objects?
- */
- if (!t->MemBlock) {
- while (1)
- {
- mgaTextureObjectPtr tmp = mmesa->TexObjList[heap].prev;
-
- t->MemBlock = mmAllocMem( mmesa->texHeap[heap],
- t->totalSize,
- 6, 0 );
- if (t->MemBlock)
- break;
-
- if (mmesa->TexObjList[heap].prev->bound) {
- fprintf(stderr, "Hit bound texture in upload\n");
- return -1;
- }
+ if ( (t == NULL) || (t->base.totalSize == 0) )
+ return 0;
- if (mmesa->TexObjList[heap].prev ==
- &(mmesa->TexObjList[heap]))
- {
- fprintf(stderr, "Failed to upload texture, sz %d\n", t->totalSize);
- mmDumpMemInfo( mmesa->texHeap[heap] );
- return -1;
- }
+ LOCK_HARDWARE( mmesa );
- mgaDestroyTexObj( mmesa, tmp );
+ 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 = t->MemBlock->ofs
- + mmesa->mgaScreen->textureOffset[heap]
- ;
+ ofs = mmesa->mgaScreen->textureOffset[ heap ]
+ + t->base.memBlock->ofs;
- 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];
+ 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.
*/
- mgaUpdateTexLRU( mmesa, t );
-
+ driUpdateTextureLRU( (driTextureObject *) t );
- if (MGA_DEBUG&DEBUG_VERBOSE_LRU)
- fprintf(stderr, "dispatch age: %d age freed memory: %d\n",
+ 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->dirty_images) {
- if (MGA_DEBUG&DEBUG_VERBOSE_LRU)
- fprintf(stderr, "*");
+ if (t->base.dirty_images[0]) {
+ const int numLevels = t->base.lastLevel - t->base.firstLevel + 1;
- for (i = 0 ; i <= t->lastLevel ; i++)
- if (t->dirty_images & (1<<i))
- mgaUploadTexLevel( mmesa, t, i );
+ 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;
}
- t->dirty_images = 0;
+ UNLOCK_HARDWARE( mmesa );
+
return 0;
}
diff --git a/src/mesa/drivers/dri/mga/mgatris.c b/src/mesa/drivers/dri/mga/mgatris.c
index e47cfc171f..054c7f0635 100644
--- a/src/mesa/drivers/dri/mga/mgatris.c
+++ b/src/mesa/drivers/dri/mga/mgatris.c
@@ -26,9 +26,6 @@
*/
/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgatris.c,v 1.10 2002/10/30 12:51:36 alanh Exp $ */
-#include <stdio.h>
-#include <math.h>
-
#include "mtypes.h"
#include "macros.h"
#include "colormac.h"
@@ -676,15 +673,6 @@ static void mgaFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
/**********************************************************************/
-
-#define _MGA_NEW_RENDERSTATE (_DD_NEW_LINE_STIPPLE | \
- _DD_NEW_TRI_UNFILLED | \
- _DD_NEW_TRI_LIGHT_TWOSIDE | \
- _DD_NEW_TRI_OFFSET | \
- _DD_NEW_TRI_STIPPLE | \
- _NEW_POLYGONSTIPPLE)
-
-
#define POINT_FALLBACK (DD_POINT_SMOOTH)
#define LINE_FALLBACK (DD_LINE_SMOOTH | DD_LINE_STIPPLE)
#define TRI_FALLBACK (DD_TRI_SMOOTH | DD_TRI_UNFILLED)
@@ -693,7 +681,7 @@ static void mgaFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
#define ANY_RASTER_FLAGS (DD_FLATSHADE|DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET| \
DD_TRI_UNFILLED)
-static void mgaChooseRenderState(GLcontext *ctx)
+void mgaChooseRenderState(GLcontext *ctx)
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
mgaContextPtr mmesa = MGA_CONTEXT(ctx);
@@ -759,36 +747,6 @@ static void mgaChooseRenderState(GLcontext *ctx)
/**********************************************************************/
-static void mgaRunPipeline( GLcontext *ctx )
-{
- mgaContextPtr mmesa = MGA_CONTEXT(ctx);
-
- if (mmesa->new_state) {
- mgaDDUpdateHwState( ctx );
- }
-
- if (!mmesa->Fallback && mmesa->new_gl_state) {
- if (mmesa->new_gl_state & _MGA_NEW_RASTERSETUP)
- mgaChooseVertexState( ctx );
-
- if (mmesa->new_gl_state & _MGA_NEW_RENDERSTATE)
- mgaChooseRenderState( ctx );
-
- mmesa->new_gl_state = 0;
-
- /* Circularity: mgaDDUpdateHwState can affect mmesa->Fallback,
- * but mgaChooseVertexState can affect mmesa->new_state. Hence
- * the second check. (Fix this...)
- */
- if (mmesa->new_state) {
- mgaDDUpdateHwState( ctx );
- }
- }
-
- _tnl_run_pipeline( ctx );
-}
-
-
static GLenum reduced_prim[GL_POLYGON+1] = {
GL_POINTS,
GL_LINES,
@@ -812,10 +770,14 @@ 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 */
- mgaUpdateCull(ctx);
if (ctx->Polygon.StippleFlag && mmesa->haveHwStipple)
{
@@ -864,6 +826,28 @@ static void mgaRenderFinish( GLcontext *ctx )
/* Manage total rasterization fallbacks */
/**********************************************************************/
+static const char * const fallbackStrings[] = {
+ "Texture mode",
+ "glDrawBuffer(GL_FRONT_AND_BACK)",
+ "read buffer",
+ "LogicOp != GL_COPY",
+ "glRenderMode(selection or feedback)",
+ "No hardware stencil",
+ "glDepthFunc( GL_NEVER )",
+ "Mixing GL_CLAMP_TO_EDGE and GL_CLAMP"
+};
+
+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);
@@ -876,6 +860,10 @@ void mgaFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
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 {
@@ -886,8 +874,12 @@ void mgaFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
tnl->Driver.Render.PrimitiveNotify = mgaRenderPrimitive;
tnl->Driver.Render.Finish = mgaRenderFinish;
tnl->Driver.Render.BuildVertices = mgaBuildVertices;
- mmesa->new_gl_state |= (_MGA_NEW_RENDERSTATE |
- _MGA_NEW_RASTERSETUP);
+ 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));
+ }
}
}
}
@@ -905,7 +897,6 @@ void mgaDDInitTriFuncs( GLcontext *ctx )
mmesa->RenderIndex = ~0;
- tnl->Driver.RunPipeline = mgaRunPipeline;
tnl->Driver.Render.Start = mgaCheckTexSizes;
tnl->Driver.Render.Finish = mgaRenderFinish;
tnl->Driver.Render.PrimitiveNotify = mgaRenderPrimitive;
diff --git a/src/mesa/drivers/dri/mga/mgatris.h b/src/mesa/drivers/dri/mga/mgatris.h
index 88eda91e13..a8c0b8936b 100644
--- a/src/mesa/drivers/dri/mga/mgatris.h
+++ b/src/mesa/drivers/dri/mga/mgatris.h
@@ -32,12 +32,17 @@
#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_LINE_STIPPLE | \
+ _DD_NEW_TRI_UNFILLED | \
+ _DD_NEW_TRI_LIGHT_TWOSIDE | \
+ _DD_NEW_TRI_OFFSET | \
+ _DD_NEW_TRI_STIPPLE | \
+ _NEW_POLYGONSTIPPLE)
#endif
diff --git a/src/mesa/drivers/dri/mga/mgavb.c b/src/mesa/drivers/dri/mga/mgavb.c
index d354fa43d2..34906865e8 100644
--- a/src/mesa/drivers/dri/mga/mgavb.c
+++ b/src/mesa/drivers/dri/mga/mgavb.c
@@ -24,7 +24,7 @@
* 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 $ */
+/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgavb.c,v 1.14 2002/10/30 12:51:36 alanh Exp $ */
#include "mgacontext.h"
#include "mgavb.h"
@@ -34,18 +34,14 @@
#include "glheader.h"
#include "mtypes.h"
-/*#include "mem.h" */
+#include "imports.h"
#include "macros.h"
#include "colormac.h"
-/*#include "mmath.h"*/
#include "tnl/t_context.h"
#include "swrast_setup/swrast_setup.h"
#include "swrast/swrast.h"
-#include <stdio.h>
-#include <stdlib.h>
-
#define MGA_TEX1_BIT 0x1
#define MGA_TEX0_BIT 0x2
@@ -93,7 +89,7 @@ static struct {
#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() ((GLubyte *)mmesa->verts)
+#define GET_VERTEX_STORE() mmesa->verts
#define GET_VERTEX_STRIDE_SHIFT() mmesa->vertex_stride_shift
#define GET_UBYTE_COLOR_STORE() &mmesa->UbyteColor
#define GET_UBYTE_SPEC_COLOR_STORE() &mmesa->UbyteSecondaryColor
@@ -407,15 +403,18 @@ void mgaChooseVertexState( GLcontext *ctx )
if (ctx->Fog.Enabled)
ind |= MGA_FOG_BIT;
- if (ctx->Texture.Unit[1]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) {
- if (ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_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.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) {
+ else if (ctx->Texture._EnabledUnits & 0x1) {
+ /* unit 0 enabled */
ind |= MGA_TEX0_BIT;
}
@@ -431,7 +430,6 @@ void mgaChooseVertexState( GLcontext *ctx )
if (setup_tab[ind].vertex_format != mmesa->vertex_format) {
FLUSH_BATCH(mmesa);
- mmesa->new_state |= MGA_NEW_WARP;
mmesa->dirty |= MGA_UPLOAD_PIPE;
mmesa->vertex_format = setup_tab[ind].vertex_format;
mmesa->vertex_size = setup_tab[ind].vertex_size;
@@ -458,7 +456,7 @@ void mgaInitVB( GLcontext *ctx )
mgaContextPtr mmesa = MGA_CONTEXT(ctx);
GLuint size = TNL_CONTEXT(ctx)->vb.Size;
- mmesa->verts = (char *)ALIGN_MALLOC(size * sizeof(mgaVertex), 32);
+ mmesa->verts = ALIGN_MALLOC(size * sizeof(mgaVertex), 32);
{
static int firsttime = 1;
@@ -468,7 +466,6 @@ void mgaInitVB( GLcontext *ctx )
}
}
- mmesa->new_state |= MGA_NEW_WARP;
mmesa->dirty |= MGA_UPLOAD_PIPE;
mmesa->vertex_format = setup_tab[0].vertex_format;
mmesa->vertex_size = setup_tab[0].vertex_size;
diff --git a/src/mesa/drivers/dri/mga/server/mga_common.h b/src/mesa/drivers/dri/mga/server/mga_common.h
index 90f6b37f4e..dcc260a1a5 100644
--- a/src/mesa/drivers/dri/mga/server/mga_common.h
+++ b/src/mesa/drivers/dri/mga/server/mga_common.h
@@ -146,7 +146,7 @@ typedef struct {
typedef struct {
int param;
- int *value;
+ void *value;
} drmMGAGetParam;
#endif
diff --git a/src/mesa/drivers/dri/r128/Makefile.X11 b/src/mesa/drivers/dri/r128/Makefile.X11
new file mode 100644
index 0000000000..8ae146af91
--- /dev/null
+++ b/src/mesa/drivers/dri/r128/Makefile.X11
@@ -0,0 +1,116 @@
+# $Id: Makefile.X11,v 1.1 2003/08/22 20:11:44 brianp Exp $
+
+# Mesa 3-D graphics library
+# Version: 5.0
+# Copyright (C) 1995-2002 Brian Paul
+
+TOP = ../../../../..
+
+default: linux-solo
+
+SHARED_INCLUDES = $(INCLUDE_DIRS) -I. -I../common -Iserver
+MINIGLX_INCLUDES = -I$(TOP)/src/glx/mini
+
+DEFINES += \
+ -D_HAVE_SWRAST=1 \
+ -D_HAVE_SWTNL=1 \
+ -D_HAVE_SANITY=1 \
+ -D_HAVE_CODEGEN=1 \
+ -D_HAVE_LIGHTING=1 \
+ -D_HAVE_TEXGEN=1 \
+ -D_HAVE_USERCLIP=1 \
+ -DGLX_DIRECT_RENDERING
+
+MINIGLX_SOURCES = server/r128_dri.c
+
+DRIVER_SOURCES = \
+ r128_context.c \
+ r128_lock.c \
+ r128_state.c \
+ r128_texstate.c \
+ r128_dd.c \
+ r128_screen.c \
+ r128_tex.c \
+ r128_tris.c \
+ r128_ioctl.c \
+ r128_span.c \
+ r128_texmem.c \
+ r128_vb.c \
+ ../common/mm.c \
+ ../common/utils.c \
+ ../common/texmem.c \
+ ../common/vblank.c
+
+INCLUDES = $(MINIGLX_INCLUDES) \
+ $(SHARED_INCLUDES)
+
+
+C_SOURCES = $(DRIVER_SOURCES) \
+ $(MINIGLX_SOURCES)
+
+MESA_MODULES = $(TOP)/src/mesa/mesa.a
+
+
+ifeq ($(WINDOW_SYSTEM),dri)
+WINOBJ=$(MESABUILDDIR)/dri/dri.a
+WINLIB=
+else
+WINOBJ=
+WINLIB=-L$(MESA)/src/glx/mini
+endif
+
+ASM_SOURCES =
+OBJECTS = $(C_SOURCES:.c=.o) \
+ $(ASM_SOURCES:.S=.o)
+
+### Include directories
+
+INCLUDE_DIRS = \
+ -I$(TOP)/include \
+ -I$(TOP)/src/mesa \
+ -I$(TOP)/src/mesa/main \
+ -I$(TOP)/src/mesa/glapi \
+ -I$(TOP)/src/mesa/math \
+ -I$(TOP)/src/mesa/transform \
+ -I$(TOP)/src/mesa/swrast \
+ -I$(TOP)/src/mesa/swrast_setup
+
+
+##### RULES #####
+
+.c.o:
+ $(CC) -c $(SHARED_INCLUDES) $(MINIGLX_INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
+
+.S.o:
+ $(CC) -c $(SHARED_INCLUDES) $(MINIGLX_INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
+
+
+##### TARGETS #####
+
+targets: depend r128_dri.so
+
+r128_dri.so: $(OBJECTS) $(MESA_MODULES) $(WINOBJ) Makefile.X11
+ rm -f $@ && gcc -o $@ -shared $(OBJECTS) $(MESA_MODULES) $(WINOBJ) $(WINLIB) -lc $(GL_LIB_DEPS)
+ rm -f $(TOP)/lib/r128_dri.so && \
+ install r128_dri.so $(TOP)/lib/r128_dri.so
+
+# Run 'make -f Makefile.X11 dep' to update the dependencies if you change
+# what's included by any source file.
+depend: $(C_SOURCES) $(ASM_SOURCES)
+ makedepend -fdepend -Y $(SHARED_INCLUDES) $(MINIGLX_INCLUDES) \
+ $(C_SOURCES) $(ASM_SOURCES)
+
+
+# Emacs tags
+tags:
+ etags `find . -name \*.[ch]` `find ../include`
+
+
+# Remove .o and backup files
+clean:
+ -rm -f *.o */*.o *~ *.o *~ *.so server/*.o
+
+
+include $(TOP)/Make-config
+
+include depend
diff --git a/src/mesa/drivers/dri/r128/r128_context.c b/src/mesa/drivers/dri/r128/r128_context.c
new file mode 100644
index 0000000000..f7f6d7141d
--- /dev/null
+++ b/src/mesa/drivers/dri/r128/r128_context.c
@@ -0,0 +1,335 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_context.c,v 1.8 2002/10/30 12:51:38 alanh Exp $ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+ Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+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, PRECISION INSIGHT 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:
+ * Kevin E. Martin <martin@valinux.com>
+ * Gareth Hughes <gareth@valinux.com>
+ *
+ */
+
+#include "glheader.h"
+#include "context.h"
+#include "simple_list.h"
+#include "imports.h"
+#include "matrix.h"
+#include "extensions.h"
+
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "array_cache/acache.h"
+
+#include "tnl/tnl.h"
+#include "tnl/t_pipeline.h"
+
+#include "r128_context.h"
+#include "r128_ioctl.h"
+#include "r128_dd.h"
+#include "r128_state.h"
+#include "r128_span.h"
+#include "r128_tex.h"
+#include "r128_tris.h"
+#include "r128_vb.h"
+
+#include "vblank.h"
+#include "utils.h"
+#include "texmem.h"
+
+#ifndef R128_DEBUG
+int R128_DEBUG = 0;
+#endif
+
+static const char * const card_extensions[] =
+{
+ "GL_ARB_multitexture",
+ "GL_ARB_texture_env_add",
+ "GL_ARB_texture_mirrored_repeat",
+ "GL_EXT_texture_edge_clamp",
+ "GL_EXT_texture_env_add",
+ "GL_IBM_texture_mirrored_repeat",
+ "GL_SGIS_generate_mipmap",
+ "GL_SGIS_texture_edge_clamp",
+ NULL
+};
+
+static const struct dri_debug_control debug_control[] =
+{
+ { "ioctl", DEBUG_VERBOSE_IOCTL },
+ { "verb", DEBUG_VERBOSE_MSG },
+ { "dri", DEBUG_VERBOSE_DRI },
+ { "2d", DEBUG_VERBOSE_2D },
+ { "sync", DEBUG_ALWAYS_SYNC },
+ { "api", DEBUG_VERBOSE_API },
+ { NULL, 0 }
+};
+
+/* Create the device specific context.
+ */
+GLboolean r128CreateContext( const __GLcontextModes *glVisual,
+ __DRIcontextPrivate *driContextPriv,
+ void *sharedContextPrivate )
+{
+ GLcontext *ctx, *shareCtx;
+ __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
+ r128ContextPtr rmesa;
+ r128ScreenPtr r128scrn;
+ int i;
+
+ /* Allocate the r128 context */
+ rmesa = (r128ContextPtr) CALLOC( sizeof(*rmesa) );
+ if ( !rmesa )
+ return GL_FALSE;
+
+ /* Allocate the Mesa context */
+ if (sharedContextPrivate)
+ shareCtx = ((r128ContextPtr) sharedContextPrivate)->glCtx;
+ else
+ shareCtx = NULL;
+ rmesa->glCtx = _mesa_create_context(glVisual, shareCtx, (void *) rmesa, GL_TRUE);
+ if (!rmesa->glCtx) {
+ FREE(rmesa);
+ return GL_FALSE;
+ }
+ driContextPriv->driverPrivate = rmesa;
+ ctx = rmesa->glCtx;
+
+ rmesa->driContext = driContextPriv;
+ rmesa->driScreen = sPriv;
+ rmesa->driDrawable = NULL;
+ rmesa->hHWContext = driContextPriv->hHWContext;
+ rmesa->driHwLock = &sPriv->pSAREA->lock;
+ rmesa->driFd = sPriv->fd;
+
+ r128scrn = rmesa->r128Screen = (r128ScreenPtr)(sPriv->private);
+
+ rmesa->sarea = (R128SAREAPrivPtr)((char *)sPriv->pSAREA +
+ r128scrn->sarea_priv_offset);
+
+ rmesa->CurrentTexObj[0] = NULL;
+ rmesa->CurrentTexObj[1] = NULL;
+
+ (void) memset( rmesa->texture_heaps, 0, sizeof( rmesa->texture_heaps ) );
+ make_empty_list( & rmesa->swapped );
+
+ rmesa->nr_heaps = r128scrn->numTexHeaps;
+ for ( i = 0 ; i < rmesa->nr_heaps ; i++ ) {
+ rmesa->texture_heaps[i] = driCreateTextureHeap( i, rmesa,
+ r128scrn->texSize[i],
+ 12,
+ R128_NR_TEX_REGIONS,
+ rmesa->sarea->texList[i],
+ & rmesa->sarea->texAge[i],
+ & rmesa->swapped,
+ sizeof( r128TexObj ),
+ (destroy_texture_object_t *) r128DestroyTexObj );
+
+ driSetTextureSwapCounterLocation( rmesa->texture_heaps[i],
+ & rmesa->c_textureSwaps );
+ }
+
+
+ rmesa->RenderIndex = -1; /* Impossible value */
+ rmesa->vert_buf = NULL;
+ rmesa->num_verts = 0;
+
+ /* Set the maximum texture size small enough that we can guarentee that
+ * all texture units can bind a maximal texture and have them both in
+ * texturable memory at once.
+ */
+
+ ctx->Const.MaxTextureUnits = 2;
+
+ driCalculateMaxTextureLevels( rmesa->texture_heaps,
+ rmesa->nr_heaps,
+ & ctx->Const,
+ 4,
+ 10, /* max 2D texture size is 1024x1024 */
+ 0, /* 3D textures unsupported. */
+ 0, /* cube textures unsupported. */
+ 0, /* texture rectangles unsupported. */
+ 11,
+ GL_FALSE );
+
+ /* No wide points.
+ */
+ ctx->Const.MinPointSize = 1.0;
+ ctx->Const.MinPointSizeAA = 1.0;
+ ctx->Const.MaxPointSize = 1.0;
+ ctx->Const.MaxPointSizeAA = 1.0;
+
+ /* No wide lines.
+ */
+ ctx->Const.MinLineWidth = 1.0;
+ ctx->Const.MinLineWidthAA = 1.0;
+ ctx->Const.MaxLineWidth = 1.0;
+ ctx->Const.MaxLineWidthAA = 1.0;
+ ctx->Const.LineWidthGranularity = 1.0;
+
+#if ENABLE_PERF_BOXES
+ rmesa->boxes = (getenv( "LIBGL_PERFORMANCE_BOXES" ) != NULL);
+#endif
+
+ /* Initialize the software rasterizer and helper modules.
+ */
+ _swrast_CreateContext( ctx );
+ _ac_CreateContext( ctx );
+ _tnl_CreateContext( ctx );
+ _swsetup_CreateContext( ctx );
+
+ /* Install the customized pipeline:
+ */
+/* _tnl_destroy_pipeline( ctx ); */
+/* _tnl_install_pipeline( ctx, r128_pipeline ); */
+
+ /* Configure swrast to match hardware characteristics:
+ */
+ _swrast_allow_pixel_fog( ctx, GL_FALSE );
+ _swrast_allow_vertex_fog( ctx, GL_TRUE );
+
+ driInitExtensions( ctx, card_extensions, GL_TRUE );
+ if (sPriv->drmMinor >= 4)
+ _mesa_enable_extension( ctx, "GL_MESA_ycbcr_texture" );
+
+ r128InitVB( ctx );
+ r128InitTriFuncs( ctx );
+ r128DDInitDriverFuncs( ctx );
+ r128DDInitIoctlFuncs( ctx );
+ r128DDInitStateFuncs( ctx );
+ r128DDInitSpanFuncs( ctx );
+ r128DDInitTextureFuncs( ctx );
+ r128DDInitState( rmesa );
+
+ rmesa->do_irqs = (rmesa->r128Screen->irq && !getenv("R128_NO_IRQS"));
+
+ rmesa->vblank_flags = (rmesa->do_irqs)
+ ? driGetDefaultVBlankFlags() : VBLANK_FLAG_NO_IRQ;
+
+ driContextPriv->driverPrivate = (void *)rmesa;
+
+#if DO_DEBUG
+ R128_DEBUG = driParseDebugString( getenv( "R128_DEBUG" ),
+ debug_control );
+#endif
+
+ return GL_TRUE;
+}
+
+/* Destroy the device specific context.
+ */
+void r128DestroyContext( __DRIcontextPrivate *driContextPriv )
+{
+ r128ContextPtr rmesa = (r128ContextPtr) driContextPriv->driverPrivate;
+
+ assert(rmesa); /* should never be null */
+ if ( rmesa ) {
+ GLboolean release_texture_heaps;
+
+
+ release_texture_heaps = (rmesa->glCtx->Shared->RefCount == 1);
+
+ _swsetup_DestroyContext( rmesa->glCtx );
+ _tnl_DestroyContext( rmesa->glCtx );
+ _ac_DestroyContext( rmesa->glCtx );
+ _swrast_DestroyContext( rmesa->glCtx );
+
+ r128FreeVB( rmesa->glCtx );
+
+ /* free the Mesa context */
+ rmesa->glCtx->DriverCtx = NULL;
+ _mesa_destroy_context(rmesa->glCtx);
+
+ if ( release_texture_heaps ) {
+ /* This share group is about to go away, free our private
+ * texture object data.
+ */
+ int i;
+
+ assert( is_empty_list( & rmesa->swapped ) );
+
+ for ( i = 0 ; i < rmesa->nr_heaps ; i++ ) {
+ driDestroyTextureHeap( rmesa->texture_heaps[ i ] );
+ rmesa->texture_heaps[ i ] = NULL;
+ }
+ }
+
+ FREE( rmesa );
+ }
+
+#if 0
+ /* Use this to force shared object profiling. */
+ glx_fini_prof();
+#endif
+}
+
+
+/* Force the context `c' to be the current context and associate with it
+ * buffer `b'.
+ */
+GLboolean
+r128MakeCurrent( __DRIcontextPrivate *driContextPriv,
+ __DRIdrawablePrivate *driDrawPriv,
+ __DRIdrawablePrivate *driReadPriv )
+{
+ if ( driContextPriv ) {
+ GET_CURRENT_CONTEXT(ctx);
+ r128ContextPtr oldR128Ctx = ctx ? R128_CONTEXT(ctx) : NULL;
+ r128ContextPtr newR128Ctx = (r128ContextPtr) driContextPriv->driverPrivate;
+
+ if ( newR128Ctx != oldR128Ctx ) {
+ newR128Ctx->new_state |= R128_NEW_CONTEXT;
+ newR128Ctx->dirty = R128_UPLOAD_ALL;
+ }
+
+ newR128Ctx->driDrawable = driDrawPriv;
+
+ _mesa_make_current2( newR128Ctx->glCtx,
+ (GLframebuffer *) driDrawPriv->driverPrivate,
+ (GLframebuffer *) driReadPriv->driverPrivate );
+
+
+ newR128Ctx->new_state |= R128_NEW_WINDOW | R128_NEW_CLIP;
+
+ if ( !newR128Ctx->glCtx->Viewport.Width ) {
+ _mesa_set_viewport(newR128Ctx->glCtx, 0, 0,
+ driDrawPriv->w, driDrawPriv->h);
+ }
+ } else {
+ _mesa_make_current( 0, 0 );
+ }
+
+ return GL_TRUE;
+}
+
+
+/* Force the context `c' to be unbound from its buffer.
+ */
+GLboolean
+r128UnbindContext( __DRIcontextPrivate *driContextPriv )
+{
+ return GL_TRUE;
+}
diff --git a/src/mesa/drivers/dri/r128/r128_context.h b/src/mesa/drivers/dri/r128/r128_context.h
new file mode 100644
index 0000000000..9c93012eb0
--- /dev/null
+++ b/src/mesa/drivers/dri/r128/r128_context.h
@@ -0,0 +1,270 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_context.h,v 1.12 2002/12/16 16:18:52 dawes Exp $ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+ Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+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, PRECISION INSIGHT 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:
+ * Kevin E. Martin <martin@valinux.com>
+ * Gareth Hughes <gareth@valinux.com>
+ *
+ */
+
+#ifndef __R128_CONTEXT_H__
+#define __R128_CONTEXT_H__
+
+#ifdef GLX_DIRECT_RENDERING
+
+#include "dri_util.h"
+
+#include "xf86drm.h"
+#include "r128_common.h"
+
+#include "mtypes.h"
+
+#include "r128_reg.h"
+
+#include "texmem.h"
+
+struct r128_context;
+typedef struct r128_context r128ContextRec;
+typedef struct r128_context *r128ContextPtr;
+
+#include "r128_lock.h"
+#include "r128_texobj.h"
+#include "r128_screen.h"
+
+/* Flags for what context state needs to be updated:
+ */
+#define R128_NEW_ALPHA 0x0001
+#define R128_NEW_DEPTH 0x0002
+#define R128_NEW_FOG 0x0004
+#define R128_NEW_CLIP 0x0008
+#define R128_NEW_CULL 0x0010
+#define R128_NEW_MASKS 0x0020
+#define R128_NEW_RENDER_NOT 0x0040
+#define R128_NEW_WINDOW 0x0080
+#define R128_NEW_CONTEXT 0x0100
+#define R128_NEW_ALL 0x01ff
+
+/* Flags for software fallback cases:
+ */
+#define R128_FALLBACK_TEXTURE 0x0001
+#define R128_FALLBACK_DRAW_BUFFER 0x0002
+#define R128_FALLBACK_READ_BUFFER 0x0004
+#define R128_FALLBACK_STENCIL 0x0008
+#define R128_FALLBACK_RENDER_MODE 0x0010
+#define R128_FALLBACK_MULTIDRAW 0x0020
+#define R128_FALLBACK_LOGICOP 0x0040
+#define R128_FALLBACK_SEP_SPECULAR 0x0080
+#define R128_FALLBACK_BLEND_EQ 0x0100
+#define R128_FALLBACK_BLEND_FUNC 0x0200
+
+
+/* Use the templated vertex format:
+ */
+#define TAG(x) r128##x
+#include "tnl_dd/t_dd_vertex.h"
+#undef TAG
+
+/* Reasons why the GL_BLEND fallback mightn't work:
+ */
+#define R128_BLEND_ENV_COLOR 0x1
+#define R128_BLEND_MULTITEX 0x2
+
+/* Subpixel offsets for window coordinates (triangles):
+ */
+#define SUBPIXEL_X (0.0F)
+#define SUBPIXEL_Y (0.125F)
+
+
+typedef void (*r128_tri_func)( r128ContextPtr,
+ r128Vertex *,
+ r128Vertex *,
+ r128Vertex * );
+
+typedef void (*r128_line_func)( r128ContextPtr,
+ r128Vertex *,
+ r128Vertex * );
+
+typedef void (*r128_point_func)( r128ContextPtr,
+ r128Vertex * );
+
+
+struct r128_context {
+ GLcontext *glCtx; /* Mesa context */
+
+ /* Driver and hardware state management
+ */
+ GLuint new_state;
+ GLuint dirty; /* Hardware state to be updated */
+ r128_context_regs_t setup;
+
+ /* Temporaries for translating away float colors:
+ */
+ struct gl_client_array UbyteColor;
+ struct gl_client_array UbyteSecondaryColor;
+
+ GLuint NewGLState;
+ GLuint Fallback;
+ GLuint SetupIndex;
+ GLuint SetupNewInputs;
+ GLuint RenderIndex;
+ GLfloat hw_viewport[16];
+ GLfloat depth_scale;
+ GLuint vertex_size;
+ GLuint vertex_stride_shift;
+ GLuint vertex_format;
+ GLuint num_verts;
+ GLubyte *verts;
+
+ CARD32 ClearColor; /* Color used to clear color buffer */
+ CARD32 ClearDepth; /* Value used to clear depth buffer */
+ CARD32 ClearStencil; /* Value used to clear stencil */
+
+ /* Map GL texture units onto hardware
+ */
+ GLint multitex;
+ GLint tmu_source[2];
+ GLuint tex_combine[2];
+ GLuint blend_flags;
+ GLuint env_color;
+
+ /* Texture object bookkeeping
+ */
+ unsigned nr_heaps;
+ driTexHeap * texture_heaps[ R128_NR_TEX_HEAPS ];
+ driTextureObject swapped;
+
+ r128TexObjPtr CurrentTexObj[2];
+
+ /* Fallback rasterization functions
+ */
+ r128_point_func draw_point;
+ r128_line_func draw_line;
+ r128_tri_func draw_tri;
+
+ /* Vertex buffers
+ */
+ drmBufPtr vert_buf;
+
+ GLuint hw_primitive;
+ GLenum render_primitive;
+
+ /* Page flipping
+ */
+ GLuint doPageFlip;
+
+ /* Busy waiting
+ */
+ GLuint do_irqs;
+
+ /* Drawable, cliprect and scissor information
+ */
+ GLint drawOffset, drawPitch;
+ GLint readOffset, readPitch;
+
+ GLuint numClipRects; /* Cliprects for the draw buffer */
+ XF86DRIClipRectPtr pClipRects;
+
+ GLuint scissor;
+ XF86DRIClipRectRec ScissorRect; /* Current software scissor */
+
+ /* Mirrors of some DRI state
+ */
+ __DRIcontextPrivate *driContext; /* DRI context */
+ __DRIscreenPrivate *driScreen; /* DRI screen */
+ __DRIdrawablePrivate *driDrawable; /* DRI drawable bound to this ctx */
+
+ unsigned int lastStamp; /* mirror driDrawable->lastStamp */
+
+ drmContext hHWContext;
+ drmLock *driHwLock;
+ int driFd;
+
+ r128ScreenPtr r128Screen; /* Screen private DRI data */
+ R128SAREAPrivPtr sarea; /* Private SAREA data */
+
+ /* Performance counters
+ */
+ GLuint boxes; /* Draw performance boxes */
+ GLuint hardwareWentIdle;
+ GLuint c_clears;
+ GLuint c_drawWaits;
+ GLuint c_textureSwaps;
+ GLuint c_textureBytes;
+ GLuint c_vertexBuffers;
+
+ /* VBI
+ */
+ GLuint vbl_seq;
+ GLuint vblank_flags;
+};
+
+#define R128_CONTEXT(ctx) ((r128ContextPtr)(ctx->DriverCtx))
+
+#define R128_IS_PLAIN( rmesa ) \
+ (rmesa->r128Screen->chipset == R128_CARD_TYPE_R128)
+#define R128_IS_PRO( rmesa ) \
+ (rmesa->r128Screen->chipset == R128_CARD_TYPE_R128_PRO)
+#define R128_IS_MOBILITY( rmesa ) \
+ (rmesa->r128Screen->chipset == R128_CARD_TYPE_R128_MOBILITY)
+
+
+extern GLboolean r128CreateContext( const __GLcontextModes *glVisual,
+ __DRIcontextPrivate *driContextPriv,
+ void *sharedContextPrivate );
+
+extern void r128DestroyContext( __DRIcontextPrivate * );
+
+extern GLboolean r128MakeCurrent( __DRIcontextPrivate *driContextPriv,
+ __DRIdrawablePrivate *driDrawPriv,
+ __DRIdrawablePrivate *driReadPriv );
+
+extern GLboolean r128UnbindContext( __DRIcontextPrivate *driContextPriv );
+
+/* ================================================================
+ * Debugging:
+ */
+#define DO_DEBUG 0
+#define ENABLE_PERF_BOXES 0
+
+#if DO_DEBUG
+extern int R128_DEBUG;
+#else
+#define R128_DEBUG 0
+#endif
+
+#define DEBUG_ALWAYS_SYNC 0x01
+#define DEBUG_VERBOSE_API 0x02
+#define DEBUG_VERBOSE_MSG 0x04
+#define DEBUG_VERBOSE_LRU 0x08
+#define DEBUG_VERBOSE_DRI 0x10
+#define DEBUG_VERBOSE_IOCTL 0x20
+#define DEBUG_VERBOSE_2D 0x40
+
+#endif
+#endif /* __R128_CONTEXT_H__ */
diff --git a/src/mesa/drivers/dri/r128/r128_dd.c b/src/mesa/drivers/dri/r128/r128_dd.c
new file mode 100644
index 0000000000..b64c26b4bd
--- /dev/null
+++ b/src/mesa/drivers/dri/r128/r128_dd.c
@@ -0,0 +1,148 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_dd.c,v 1.15 2002/10/30 12:51:38 alanh Exp $ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+ Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+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, PRECISION INSIGHT 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:
+ * Gareth Hughes <gareth@valinux.com>
+ * Kevin E. Martin <martin@valinux.com>
+ *
+ */
+
+#include "r128_context.h"
+#include "r128_ioctl.h"
+#include "r128_state.h"
+#include "r128_vb.h"
+#include "r128_dd.h"
+
+#include "context.h"
+
+#include "utils.h"
+
+#define DRIVER_DATE "20030328"
+
+
+/* Return the width and height of the current color buffer.
+ */
+static void r128DDGetBufferSize( GLframebuffer *buffer,
+ GLuint *width, GLuint *height )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+ LOCK_HARDWARE( rmesa );
+ *width = rmesa->driDrawable->w;
+ *height = rmesa->driDrawable->h;
+ UNLOCK_HARDWARE( rmesa );
+}
+
+/* Return various strings for glGetString().
+ */
+static const GLubyte *r128DDGetString( GLcontext *ctx, GLenum name )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+ static char buffer[128];
+ unsigned offset;
+ const char * card_name = "Rage 128";
+ GLuint agp_mode = rmesa->r128Screen->IsPCI ? 0 :
+ rmesa->r128Screen->AGPMode;
+
+ switch ( name ) {
+ case GL_VENDOR:
+ return (GLubyte *)"VA Linux Systems, Inc.";
+
+ case GL_RENDERER:
+ /* Select the spefic chipset.
+ */
+ if ( R128_IS_PRO( rmesa ) ) {
+ card_name = "Rage 128 Pro";
+ }
+ else if ( R128_IS_MOBILITY( rmesa ) ) {
+ card_name = "Rage 128 Mobility";
+ }
+
+ offset = driGetRendererString( buffer, card_name, DRIVER_DATE,
+ agp_mode );
+
+ return (GLubyte *)buffer;
+
+ default:
+ return NULL;
+ }
+}
+
+/* Send all commands to the hardware. If vertex buffers or indirect
+ * buffers are in use, then we need to make sure they are sent to the
+ * hardware. All commands that are normally sent to the ring are
+ * already considered `flushed'.
+ */
+static void r128DDFlush( GLcontext *ctx )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+ FLUSH_BATCH( rmesa );
+
+#if ENABLE_PERF_BOXES
+ if ( rmesa->boxes ) {
+ LOCK_HARDWARE( rmesa );
+ r128PerformanceBoxesLocked( rmesa );
+ UNLOCK_HARDWARE( rmesa );
+ }
+
+ /* Log the performance counters if necessary */
+ r128PerformanceCounters( rmesa );
+#endif
+}
+
+/* Make sure all commands have been sent to the hardware and have
+ * completed processing.
+ */
+static void r128DDFinish( GLcontext *ctx )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+#if ENABLE_PERF_BOXES
+ /* Bump the performance counter */
+ rmesa->c_drawWaits++;
+#endif
+
+ r128DDFlush( ctx );
+ r128WaitForIdle( rmesa );
+}
+
+
+/* Initialize the driver's misc functions.
+ */
+void r128DDInitDriverFuncs( GLcontext *ctx )
+{
+ ctx->Driver.GetBufferSize = r128DDGetBufferSize;
+ ctx->Driver.ResizeBuffers = _swrast_alloc_buffers;
+ ctx->Driver.GetString = r128DDGetString;
+ ctx->Driver.Finish = r128DDFinish;
+ ctx->Driver.Flush = r128DDFlush;
+ ctx->Driver.Error = NULL;
+}
diff --git a/src/mesa/drivers/dri/r128/r128_dd.h b/src/mesa/drivers/dri/r128/r128_dd.h
new file mode 100644
index 0000000000..b8fc7ad9bf
--- /dev/null
+++ b/src/mesa/drivers/dri/r128/r128_dd.h
@@ -0,0 +1,44 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_dd.h,v 1.3 2001/01/08 01:07:20 martin Exp $ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+ Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+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, PRECISION INSIGHT 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:
+ * Gareth Hughes <gareth@valinux.com>
+ * Kevin E. Martin <martin@valinux.com>
+ *
+ */
+
+#ifndef __R128_DD_H__
+#define __R128_DD_H__
+
+#ifdef GLX_DIRECT_RENDERING
+
+extern void r128DDInitDriverFuncs( GLcontext *ctx );
+
+#endif
+#endif
diff --git a/src/mesa/drivers/dri/r128/r128_ioctl.c b/src/mesa/drivers/dri/r128/r128_ioctl.c
new file mode 100644
index 0000000000..c5843473e1
--- /dev/null
+++ b/src/mesa/drivers/dri/r128/r128_ioctl.c
@@ -0,0 +1,812 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_ioctl.c,v 1.10 2002/12/16 16:18:53 dawes Exp $ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+ Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+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, PRECISION INSIGHT 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:
+ * Gareth Hughes <gareth@valinux.com>
+ *
+ */
+#include <errno.h>
+
+#include "r128_context.h"
+#include "r128_state.h"
+#include "r128_ioctl.h"
+#include "r128_macros.h"
+
+#include "imports.h"
+#include "macros.h"
+
+#include "swrast/swrast.h"
+
+#include "vblank.h"
+
+#define R128_TIMEOUT 2048
+#define R128_IDLE_RETRY 32
+
+
+/* =============================================================
+ * Hardware vertex buffer handling
+ */
+
+/* Get a new VB from the pool of vertex buffers in AGP space.
+ */
+drmBufPtr r128GetBufferLocked( r128ContextPtr rmesa )
+{
+ int fd = rmesa->r128Screen->driScreen->fd;
+ int index = 0;
+ int size = 0;
+ drmDMAReq dma;
+ drmBufPtr buf = NULL;
+ int to = 0;
+ int ret;
+
+ dma.context = rmesa->hHWContext;
+ dma.send_count = 0;
+ dma.send_list = NULL;
+ dma.send_sizes = NULL;
+ dma.flags = 0;
+ dma.request_count = 1;
+ dma.request_size = R128_BUFFER_SIZE;
+ dma.request_list = &index;
+ dma.request_sizes = &size;
+ dma.granted_count = 0;
+
+ while ( !buf && ( to++ < R128_TIMEOUT ) ) {
+ ret = drmDMA( fd, &dma );
+
+ if ( ret == 0 ) {
+ buf = &rmesa->r128Screen->buffers->list[index];
+ buf->used = 0;
+#if ENABLE_PERF_BOXES
+ /* Bump the performance counter */
+ rmesa->c_vertexBuffers++;
+#endif
+ return buf;
+ }
+ }
+
+ if ( !buf ) {
+ drmCommandNone( fd, DRM_R128_CCE_RESET);
+ UNLOCK_HARDWARE( rmesa );
+ fprintf( stderr, "Error: Could not get new VB... exiting\n" );
+ exit( -1 );
+ }
+
+ return buf;
+}
+
+void r128FlushVerticesLocked( r128ContextPtr rmesa )
+{
+ XF86DRIClipRectPtr pbox = rmesa->pClipRects;
+ int nbox = rmesa->numClipRects;
+ drmBufPtr buffer = rmesa->vert_buf;
+ int count = rmesa->num_verts;
+ int prim = rmesa->hw_primitive;
+ int fd = rmesa->driScreen->fd;
+ drmR128Vertex vertex;
+ int i;
+
+ rmesa->num_verts = 0;
+ rmesa->vert_buf = NULL;
+
+ if ( !buffer )
+ return;
+
+ if ( rmesa->dirty & ~R128_UPLOAD_CLIPRECTS )
+ r128EmitHwStateLocked( rmesa );
+
+ if ( !nbox )
+ count = 0;
+
+ if ( nbox >= R128_NR_SAREA_CLIPRECTS )
+ rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
+
+ if ( !count || !(rmesa->dirty & R128_UPLOAD_CLIPRECTS) )
+ {
+ if ( nbox < 3 ) {
+ rmesa->sarea->nbox = 0;
+ } else {
+ rmesa->sarea->nbox = nbox;
+ }
+
+ vertex.prim = prim;
+ vertex.idx = buffer->idx;
+ vertex.count = count;
+ vertex.discard = 1;
+ drmCommandWrite( fd, DRM_R128_VERTEX, &vertex, sizeof(drmR128Vertex) );
+ }
+ else
+ {
+ for ( i = 0 ; i < nbox ; ) {
+ int nr = MIN2( i + R128_NR_SAREA_CLIPRECTS, nbox );
+ XF86DRIClipRectPtr b = rmesa->sarea->boxes;
+ int discard = 0;
+
+ rmesa->sarea->nbox = nr - i;
+ for ( ; i < nr ; i++ ) {
+ *b++ = pbox[i];
+ }
+
+ /* Finished with the buffer?
+ */
+ if ( nr == nbox ) {
+ discard = 1;
+ }
+
+ rmesa->sarea->dirty |= R128_UPLOAD_CLIPRECTS;
+
+ vertex.prim = prim;
+ vertex.idx = buffer->idx;
+ vertex.count = count;
+ vertex.discard = discard;
+ drmCommandWrite( fd, DRM_R128_VERTEX, &vertex, sizeof(drmR128Vertex) );
+ }
+ }
+
+ rmesa->dirty &= ~R128_UPLOAD_CLIPRECTS;
+}
+
+
+
+
+
+/* ================================================================
+ * Texture uploads
+ */
+
+void r128FireBlitLocked( r128ContextPtr rmesa, drmBufPtr buffer,
+ GLint offset, GLint pitch, GLint format,
+ GLint x, GLint y, GLint width, GLint height )
+{
+ drmR128Blit blit;
+ GLint ret;
+
+ blit.idx = buffer->idx;
+ blit.offset = offset;
+ blit.pitch = pitch;
+ blit.format = format;
+ blit.x = x;
+ blit.y = y;
+ blit.width = width;
+ blit.height = height;
+
+ ret = drmCommandWrite( rmesa->driFd, DRM_R128_BLIT,
+ &blit, sizeof(drmR128Blit) );
+
+ if ( ret ) {
+ UNLOCK_HARDWARE( rmesa );
+ fprintf( stderr, "DRM_R128_BLIT: return = %d\n", ret );
+ exit( 1 );
+ }
+}
+
+
+/* ================================================================
+ * SwapBuffers with client-side throttling
+ */
+
+static void delay( void ) {
+/* Prevent an optimizing compiler from removing a spin loop */
+}
+
+#define R128_MAX_OUTSTANDING 2
+
+/* Throttle the frame rate -- only allow one pending swap buffers
+ * request at a time.
+ * GH: We probably don't want a timeout here, as we can wait as
+ * long as we want for a frame to complete. If it never does, then
+ * the card has locked.
+ */
+static int r128WaitForFrameCompletion( r128ContextPtr rmesa )
+{
+ unsigned char *R128MMIO = rmesa->r128Screen->mmio.map;
+ CARD32 frame;
+ int i;
+ int wait = 0;
+
+ while ( 1 ) {
+ frame = INREG( R128_LAST_FRAME_REG );
+ if ( rmesa->sarea->last_frame - frame <= R128_MAX_OUTSTANDING ) {
+ break;
+ }
+
+ /* Spin in place a bit so we aren't hammering the register */
+ wait++;
+ for ( i = 0 ; i < 1024 ; i++ ) {
+ delay();
+ }
+ }
+
+ return wait;
+}
+
+/* Copy the back color buffer to the front color buffer.
+ */
+void r128CopyBuffer( const __DRIdrawablePrivate *dPriv )
+{
+ r128ContextPtr rmesa;
+ GLint nbox, i, ret;
+ GLboolean missed_target;
+
+ assert(dPriv);
+ assert(dPriv->driContextPriv);
+ assert(dPriv->driContextPriv->driverPrivate);
+
+ rmesa = (r128ContextPtr) dPriv->driContextPriv->driverPrivate;
+
+ if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
+ fprintf( stderr, "\n********************************\n" );
+ fprintf( stderr, "\n%s( %p )\n\n",
+ __FUNCTION__, rmesa->glCtx );
+ fflush( stderr );
+ }
+
+ FLUSH_BATCH( rmesa );
+
+ LOCK_HARDWARE( rmesa );
+
+ /* Throttle the frame rate -- only allow one pending swap buffers
+ * request at a time.
+ */
+ if ( !r128WaitForFrameCompletion( rmesa ) ) {
+ rmesa->hardwareWentIdle = 1;
+ } else {
+ rmesa->hardwareWentIdle = 0;
+ }
+
+ UNLOCK_HARDWARE( rmesa );
+ driWaitForVBlank( dPriv, &rmesa->vbl_seq, rmesa->vblank_flags, &missed_target );
+ LOCK_HARDWARE( rmesa );
+
+ nbox = dPriv->numClipRects; /* must be in locked region */
+
+ for ( i = 0 ; i < nbox ; ) {
+ GLint nr = MIN2( i + R128_NR_SAREA_CLIPRECTS , nbox );
+ XF86DRIClipRectPtr box = dPriv->pClipRects;
+ XF86DRIClipRectPtr b = rmesa->sarea->boxes;
+ GLint n = 0;
+
+ for ( ; i < nr ; i++ ) {
+ *b++ = *(XF86DRIClipRectRec *)&box[i];
+ n++;
+ }
+ rmesa->sarea->nbox = n;
+
+ ret = drmCommandNone( rmesa->driFd, DRM_R128_SWAP );
+
+ if ( ret ) {
+ UNLOCK_HARDWARE( rmesa );
+ fprintf( stderr, "DRM_R128_SWAP: return = %d\n", ret );
+ exit( 1 );
+ }
+ }
+
+ if ( R128_DEBUG & DEBUG_ALWAYS_SYNC ) {
+ i = 0;
+ do {
+ ret = drmCommandNone(rmesa->driFd, DRM_R128_CCE_IDLE);
+ } while ( ret && errno == EBUSY && i++ < R128_IDLE_RETRY );
+ }
+
+ UNLOCK_HARDWARE( rmesa );
+
+ rmesa->new_state |= R128_NEW_CONTEXT;
+ rmesa->dirty |= (R128_UPLOAD_CONTEXT |
+ R128_UPLOAD_MASKS |
+ R128_UPLOAD_CLIPRECTS);
+
+#if ENABLE_PERF_BOXES
+ /* Log the performance counters if necessary */
+ r128PerformanceCounters( rmesa );
+#endif
+}
+
+void r128PageFlip( const __DRIdrawablePrivate *dPriv )
+{
+ r128ContextPtr rmesa;
+ GLint ret;
+ GLboolean missed_target;
+
+ assert(dPriv);
+ assert(dPriv->driContextPriv);
+ assert(dPriv->driContextPriv->driverPrivate);
+
+ rmesa = (r128ContextPtr) dPriv->driContextPriv->driverPrivate;
+
+ if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
+ fprintf( stderr, "\n%s( %p ): page=%d\n\n",
+ __FUNCTION__, rmesa->glCtx, rmesa->sarea->pfCurrentPage );
+ }
+
+ FLUSH_BATCH( rmesa );
+
+ LOCK_HARDWARE( rmesa );
+
+ /* Throttle the frame rate -- only allow one pending swap buffers
+ * request at a time.
+ */
+ if ( !r128WaitForFrameCompletion( rmesa ) ) {
+ rmesa->hardwareWentIdle = 1;
+ } else {
+ rmesa->hardwareWentIdle = 0;
+ }
+
+ UNLOCK_HARDWARE( rmesa );
+ driWaitForVBlank( dPriv, &rmesa->vbl_seq, rmesa->vblank_flags, &missed_target );
+ LOCK_HARDWARE( rmesa );
+
+ /* The kernel will have been initialized to perform page flipping
+ * on a swapbuffers ioctl.
+ */
+ ret = drmCommandNone( rmesa->driFd, DRM_R128_FLIP );
+
+ UNLOCK_HARDWARE( rmesa );
+
+ if ( ret ) {
+ fprintf( stderr, "DRM_R128_FLIP: return = %d\n", ret );
+ exit( 1 );
+ }
+
+ if ( rmesa->sarea->pfCurrentPage == 1 ) {
+ rmesa->drawOffset = rmesa->r128Screen->frontOffset;
+ rmesa->drawPitch = rmesa->r128Screen->frontPitch;
+ } else {
+ rmesa->drawOffset = rmesa->r128Screen->backOffset;
+ rmesa->drawPitch = rmesa->r128Screen->backPitch;
+ }
+
+ rmesa->setup.dst_pitch_offset_c = (((rmesa->drawPitch/8) << 21) |
+ (rmesa->drawOffset >> 5));
+ rmesa->new_state |= R128_NEW_WINDOW;
+
+ /* FIXME: Do we need this anymore? */
+ rmesa->new_state |= R128_NEW_CONTEXT;
+ rmesa->dirty |= (R128_UPLOAD_CONTEXT |
+ R128_UPLOAD_MASKS |
+ R128_UPLOAD_CLIPRECTS);
+
+#if ENABLE_PERF_BOXES
+ /* Log the performance counters if necessary */
+ r128PerformanceCounters( rmesa );
+#endif
+}
+
+
+/* ================================================================
+ * Buffer clear
+ */
+
+static void r128DDClear( GLcontext *ctx, GLbitfield mask, GLboolean all,
+ GLint cx, GLint cy, GLint cw, GLint ch )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+ __DRIdrawablePrivate *dPriv = rmesa->driDrawable;
+ drmR128Clear clear;
+ GLuint flags = 0;
+ GLint i;
+ GLint ret;
+
+ if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
+ fprintf( stderr, "%s:\n", __FUNCTION__ );
+ }
+
+ FLUSH_BATCH( rmesa );
+
+ /* The only state change we care about here is the RGBA colormask
+ * We'll just update that state, if needed. If we do more then
+ * there's some strange side-effects that the conformance tests find.
+ */
+ if ( rmesa->new_state & R128_NEW_MASKS) {
+ const GLuint save_state = rmesa->new_state;
+ rmesa->new_state = R128_NEW_MASKS;
+ r128DDUpdateHWState( ctx );
+ rmesa->new_state = save_state & ~R128_NEW_MASKS;
+ }
+
+ if ( mask & DD_FRONT_LEFT_BIT ) {
+ flags |= DRM_R128_FRONT_BUFFER;
+ mask &= ~DD_FRONT_LEFT_BIT;
+ }
+
+ if ( mask & DD_BACK_LEFT_BIT ) {
+ flags |= DRM_R128_BACK_BUFFER;
+ mask &= ~DD_BACK_LEFT_BIT;
+ }
+
+ if ( ( mask & DD_DEPTH_BIT ) && ctx->Depth.Mask ) {
+ flags |= DRM_R128_DEPTH_BUFFER;
+ mask &= ~DD_DEPTH_BIT;
+ }
+#if 0
+ /* FIXME: Add stencil support */
+ if ( mask & DD_STENCIL_BIT ) {
+ flags |= DRM_R128_DEPTH_BUFFER;
+ mask &= ~DD_STENCIL_BIT;
+ }
+#endif
+
+ if ( flags ) {
+
+ /* Flip top to bottom */
+ cx += dPriv->x;
+ cy = dPriv->y + dPriv->h - cy - ch;
+
+ LOCK_HARDWARE( rmesa );
+
+ /* FIXME: Do we actually need this?
+ */
+ if ( rmesa->dirty & ~R128_UPLOAD_CLIPRECTS ) {
+ r128EmitHwStateLocked( rmesa );
+ }
+
+ for ( i = 0 ; i < rmesa->numClipRects ; ) {
+ GLint nr = MIN2( i + R128_NR_SAREA_CLIPRECTS , rmesa->numClipRects );
+ XF86DRIClipRectPtr box = rmesa->pClipRects;
+ XF86DRIClipRectPtr b = rmesa->sarea->boxes;
+ GLint n = 0;
+
+ if ( !all ) {
+ 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 {
+ for ( ; i < nr ; i++ ) {
+ *b++ = *(XF86DRIClipRectPtr)&box[i];
+ n++;
+ }
+ }
+
+ rmesa->sarea->nbox = n;
+
+ if ( R128_DEBUG & DEBUG_VERBOSE_IOCTL ) {
+ fprintf( stderr,
+ "DRM_R128_CLEAR: flag 0x%x color %x depth %x nbox %d\n",
+ flags,
+ (GLuint)rmesa->ClearColor,
+ (GLuint)rmesa->ClearDepth,
+ rmesa->sarea->nbox );
+ }
+
+ clear.flags = flags;
+ clear.clear_color = rmesa->ClearColor;
+ clear.clear_depth = rmesa->ClearDepth;
+ clear.color_mask = rmesa->setup.plane_3d_mask_c;
+ clear.depth_mask = ~0;
+
+ ret = drmCommandWrite( rmesa->driFd, DRM_R128_CLEAR,
+ &clear, sizeof(drmR128Clear) );
+
+ if ( ret ) {
+ UNLOCK_HARDWARE( rmesa );
+ fprintf( stderr, "DRM_R128_CLEAR: return = %d\n", ret );
+ exit( 1 );
+ }
+ }
+
+ UNLOCK_HARDWARE( rmesa );
+
+ rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
+ }
+
+ if ( mask )
+ _swrast_Clear( ctx, mask, all, cx, cy, cw, ch );
+}
+
+
+/* ================================================================
+ * Depth spans, pixels
+ */
+
+void r128WriteDepthSpanLocked( r128ContextPtr rmesa,
+ GLuint n, GLint x, GLint y,
+ const GLdepth depth[],
+ const GLubyte mask[] )
+{
+ XF86DRIClipRectPtr pbox = rmesa->pClipRects;
+ drmR128Depth d;
+ int nbox = rmesa->numClipRects;
+ int fd = rmesa->driScreen->fd;
+ int i;
+
+ if ( !nbox || !n ) {
+ return;
+ }
+ if ( nbox >= R128_NR_SAREA_CLIPRECTS ) {
+ rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
+ }
+
+ if ( !(rmesa->dirty & R128_UPLOAD_CLIPRECTS) )
+ {
+ if ( nbox < 3 ) {
+ rmesa->sarea->nbox = 0;
+ } else {
+ rmesa->sarea->nbox = nbox;
+ }
+
+ d.func = DRM_R128_WRITE_SPAN;
+ d.n = n;
+ d.x = (int*)&x;
+ d.y = (int*)&y;
+ d.buffer = (unsigned int *)depth;
+ d.mask = (unsigned char *)mask;
+
+ drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(drmR128Depth));
+
+ }
+ else
+ {
+ for (i = 0 ; i < nbox ; ) {
+ int nr = MIN2( i + R128_NR_SAREA_CLIPRECTS, nbox );
+ XF86DRIClipRectPtr b = rmesa->sarea->boxes;
+
+ rmesa->sarea->nbox = nr - i;
+ for ( ; i < nr ; i++) {
+ *b++ = pbox[i];
+ }
+
+ rmesa->sarea->dirty |= R128_UPLOAD_CLIPRECTS;
+
+ d.func = DRM_R128_WRITE_SPAN;
+ d.n = n;
+ d.x = (int*)&x;
+ d.y = (int*)&y;
+ d.buffer = (unsigned int *)depth;
+ d.mask = (unsigned char *)mask;
+
+ drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(drmR128Depth));
+ }
+ }
+
+ rmesa->dirty &= ~R128_UPLOAD_CLIPRECTS;
+}
+
+void r128WriteDepthPixelsLocked( r128ContextPtr rmesa, GLuint n,
+ const GLint x[], const GLint y[],
+ const GLdepth depth[],
+ const GLubyte mask[] )
+{
+ XF86DRIClipRectPtr pbox = rmesa->pClipRects;
+ drmR128Depth d;
+ int nbox = rmesa->numClipRects;
+ int fd = rmesa->driScreen->fd;
+ int i;
+
+ if ( !nbox || !n ) {
+ return;
+ }
+ if ( nbox >= R128_NR_SAREA_CLIPRECTS ) {
+ rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
+ }
+
+ if ( !(rmesa->dirty & R128_UPLOAD_CLIPRECTS) )
+ {
+ if ( nbox < 3 ) {
+ rmesa->sarea->nbox = 0;
+ } else {
+ rmesa->sarea->nbox = nbox;
+ }
+
+ d.func = DRM_R128_WRITE_PIXELS;
+ d.n = n;
+ d.x = (int*)&x;
+ d.y = (int*)&y;
+ d.buffer = (unsigned int *)depth;
+ d.mask = (unsigned char *)mask;
+
+ drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(drmR128Depth));
+ }
+ else
+ {
+ for (i = 0 ; i < nbox ; ) {
+ int nr = MIN2( i + R128_NR_SAREA_CLIPRECTS, nbox );
+ XF86DRIClipRectPtr b = rmesa->sarea->boxes;
+
+ rmesa->sarea->nbox = nr - i;
+ for ( ; i < nr ; i++) {
+ *b++ = pbox[i];
+ }
+
+ rmesa->sarea->dirty |= R128_UPLOAD_CLIPRECTS;
+
+ d.func = DRM_R128_WRITE_PIXELS;
+ d.n = n;
+ d.x = (int*)&x;
+ d.y = (int*)&y;
+ d.buffer = (unsigned int *)depth;
+ d.mask = (unsigned char *)mask;
+
+ drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(drmR128Depth));
+ }
+ }
+
+ rmesa->dirty &= ~R128_UPLOAD_CLIPRECTS;
+}
+
+void r128ReadDepthSpanLocked( r128ContextPtr rmesa,
+ GLuint n, GLint x, GLint y )
+{
+ XF86DRIClipRectPtr pbox = rmesa->pClipRects;
+ drmR128Depth d;
+ int nbox = rmesa->numClipRects;
+ int fd = rmesa->driScreen->fd;
+ int i;
+
+ if ( !nbox || !n ) {
+ return;
+ }
+ if ( nbox >= R128_NR_SAREA_CLIPRECTS ) {
+ rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
+ }
+
+ if ( !(rmesa->dirty & R128_UPLOAD_CLIPRECTS) )
+ {
+ if ( nbox < 3 ) {
+ rmesa->sarea->nbox = 0;
+ } else {
+ rmesa->sarea->nbox = nbox;
+ }
+
+ d.func = DRM_R128_READ_SPAN;
+ d.n = n;
+ d.x = (int*)&x;
+ d.y = (int*)&y;
+ d.buffer = NULL;
+ d.mask = NULL;
+
+ drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(drmR128Depth));
+ }
+ else
+ {
+ for (i = 0 ; i < nbox ; ) {
+ int nr = MIN2( i + R128_NR_SAREA_CLIPRECTS, nbox );
+ XF86DRIClipRectPtr b = rmesa->sarea->boxes;
+
+ rmesa->sarea->nbox = nr - i;
+ for ( ; i < nr ; i++) {
+ *b++ = pbox[i];
+ }
+
+ rmesa->sarea->dirty |= R128_UPLOAD_CLIPRECTS;
+
+ d.func = DRM_R128_READ_SPAN;
+ d.n = n;
+ d.x = (int*)&x;
+ d.y = (int*)&y;
+ d.buffer = NULL;
+ d.mask = NULL;
+
+ drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(drmR128Depth));
+ }
+ }
+
+ rmesa->dirty &= ~R128_UPLOAD_CLIPRECTS;
+}
+
+void r128ReadDepthPixelsLocked( r128ContextPtr rmesa, GLuint n,
+ const GLint x[], const GLint y[] )
+{
+ XF86DRIClipRectPtr pbox = rmesa->pClipRects;
+ drmR128Depth d;
+ int nbox = rmesa->numClipRects;
+ int fd = rmesa->driScreen->fd;
+ int i;
+
+ if ( !nbox || !n ) {
+ return;
+ }
+ if ( nbox >= R128_NR_SAREA_CLIPRECTS ) {
+ rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
+ }
+
+ if ( !(rmesa->dirty & R128_UPLOAD_CLIPRECTS) )
+ {
+ if ( nbox < 3 ) {
+ rmesa->sarea->nbox = 0;
+ } else {
+ rmesa->sarea->nbox = nbox;
+ }
+
+ d.func = DRM_R128_READ_PIXELS;
+ d.n = n;
+ d.x = (int*)&x;
+ d.y = (int*)&y;
+ d.buffer = NULL;
+ d.mask = NULL;
+
+ drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(drmR128Depth));
+ }
+ else
+ {
+ for (i = 0 ; i < nbox ; ) {
+ int nr = MIN2( i + R128_NR_SAREA_CLIPRECTS, nbox );
+ XF86DRIClipRectPtr b = rmesa->sarea->boxes;
+
+ rmesa->sarea->nbox = nr - i;
+ for ( ; i < nr ; i++) {
+ *b++ = pbox[i];
+ }
+
+ rmesa->sarea->dirty |= R128_UPLOAD_CLIPRECTS;
+
+ d.func = DRM_R128_READ_PIXELS;
+ d.n = n;
+ d.x = (int*)&x;
+ d.y = (int*)&y;
+ d.buffer = NULL;
+ d.mask = NULL;
+
+ drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(drmR128Depth));
+ }
+ }
+
+ rmesa->dirty &= ~R128_UPLOAD_CLIPRECTS;
+}
+
+
+void r128WaitForIdleLocked( r128ContextPtr rmesa )
+{
+ int fd = rmesa->r128Screen->driScreen->fd;
+ int to = 0;
+ int ret, i;
+
+ do {
+ i = 0;
+ do {
+ ret = drmCommandNone( fd, DRM_R128_CCE_IDLE);
+ } while ( ret && errno == EBUSY && i++ < R128_IDLE_RETRY );
+ } while ( ( ret == -EBUSY ) && ( to++ < R128_TIMEOUT ) );
+
+ if ( ret < 0 ) {
+ drmCommandNone( fd, DRM_R128_CCE_RESET);
+ UNLOCK_HARDWARE( rmesa );
+ fprintf( stderr, "Error: Rage 128 timed out... exiting\n" );
+ exit( -1 );
+ }
+}
+
+void r128DDInitIoctlFuncs( GLcontext *ctx )
+{
+ ctx->Driver.Clear = r128DDClear;
+}
diff --git a/src/mesa/drivers/dri/r128/r128_ioctl.h b/src/mesa/drivers/dri/r128/r128_ioctl.h
new file mode 100644
index 0000000000..b0f6b363a5
--- /dev/null
+++ b/src/mesa/drivers/dri/r128/r128_ioctl.h
@@ -0,0 +1,146 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_ioctl.h,v 1.6 2002/12/16 16:18:53 dawes Exp $ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+ Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+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, PRECISION INSIGHT 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:
+ * Gareth Hughes <gareth@valinux.com>
+ *
+ */
+
+#ifndef __R128_IOCTL_H__
+#define __R128_IOCTL_H__
+
+#ifdef GLX_DIRECT_RENDERING
+
+#include "r128_dri.h"
+#include "r128_reg.h"
+#include "r128_lock.h"
+
+#include "xf86drm.h"
+#include "r128_common.h"
+
+#define R128_BUFFER_MAX_DWORDS (R128_BUFFER_SIZE / sizeof(CARD32))
+
+
+extern drmBufPtr r128GetBufferLocked( r128ContextPtr rmesa );
+extern void r128FlushVerticesLocked( r128ContextPtr rmesa );
+
+static __inline void *r128AllocDmaLow( r128ContextPtr rmesa, int bytes )
+{
+ CARD32 *head;
+
+ if ( !rmesa->vert_buf ) {
+ LOCK_HARDWARE( rmesa );
+ rmesa->vert_buf = r128GetBufferLocked( rmesa );
+ UNLOCK_HARDWARE( rmesa );
+ } else if ( rmesa->vert_buf->used + bytes > rmesa->vert_buf->total ) {
+ LOCK_HARDWARE( rmesa );
+ r128FlushVerticesLocked( rmesa );
+ rmesa->vert_buf = r128GetBufferLocked( rmesa );
+ UNLOCK_HARDWARE( rmesa );
+ }
+
+ head = (CARD32 *)((char *)rmesa->vert_buf->address + rmesa->vert_buf->used);
+ rmesa->vert_buf->used += bytes;
+ return head;
+}
+
+extern void r128FireBlitLocked( r128ContextPtr rmesa, drmBufPtr buffer,
+ GLint offset, GLint pitch, GLint format,
+ GLint x, GLint y, GLint width, GLint height );
+
+extern void r128WriteDepthSpanLocked( r128ContextPtr rmesa,
+ GLuint n, GLint x, GLint y,
+ const GLdepth depth[],
+ const GLubyte mask[] );
+extern void r128WriteDepthPixelsLocked( r128ContextPtr rmesa, GLuint n,
+ const GLint x[], const GLint y[],
+ const GLdepth depth[],
+ const GLubyte mask[] );
+extern void r128ReadDepthSpanLocked( r128ContextPtr rmesa,
+ GLuint n, GLint x, GLint y );
+extern void r128ReadDepthPixelsLocked( r128ContextPtr rmesa, GLuint n,
+ const GLint x[], const GLint y[] );
+
+extern void r128CopyBuffer( const __DRIdrawablePrivate *dPriv );
+extern void r128PageFlip( const __DRIdrawablePrivate *dPriv );
+void r128WaitForVBlank( r128ContextPtr rmesa );
+
+extern void r128WaitForIdleLocked( r128ContextPtr rmesa );
+
+
+extern void r128DDInitIoctlFuncs( GLcontext *ctx );
+
+
+/* ================================================================
+ * Helper macros:
+ */
+
+#define FLUSH_BATCH( rmesa ) \
+do { \
+ if ( R128_DEBUG & DEBUG_VERBOSE_IOCTL ) \
+ fprintf( stderr, "FLUSH_BATCH in %s\n", __FUNCTION__ ); \
+ if ( rmesa->vert_buf ) { \
+ r128FlushVertices( rmesa ); \
+ } \
+} while (0)
+
+/* 64-bit align the next element address, and then make room for the
+ * next indexed prim packet header.
+ */
+#define ALIGN_NEXT_ELT( rmesa ) \
+do { \
+ rmesa->next_elt = (GLushort *) \
+ (((GLuint)rmesa->next_elt + 7) & ~0x7); \
+ rmesa->next_elt = (GLushort *) \
+ ((GLubyte *)rmesa->next_elt + R128_INDEX_PRIM_OFFSET); \
+} while (0)
+
+#define r128FlushVertices( rmesa ) \
+do { \
+ LOCK_HARDWARE( rmesa ); \
+ r128FlushVerticesLocked( rmesa ); \
+ UNLOCK_HARDWARE( rmesa ); \
+} while (0)
+
+#define r128FlushElts( rmesa ) \
+do { \
+ LOCK_HARDWARE( rmesa ); \
+ r128FlushEltsLocked( rmesa ); \
+ UNLOCK_HARDWARE( rmesa ); \
+} while (0)
+
+#define r128WaitForIdle( rmesa ) \
+ do { \
+ LOCK_HARDWARE( rmesa ); \
+ r128WaitForIdleLocked( rmesa ); \
+ UNLOCK_HARDWARE( rmesa ); \
+ } while (0)
+
+#endif
+#endif /* __R128_IOCTL_H__ */
diff --git a/src/mesa/drivers/dri/r128/r128_lock.c b/src/mesa/drivers/dri/r128/r128_lock.c
new file mode 100644
index 0000000000..12eb0128b0
--- /dev/null
+++ b/src/mesa/drivers/dri/r128/r128_lock.c
@@ -0,0 +1,123 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_lock.c,v 1.5 2002/10/30 12:51:38 alanh Exp $ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+ Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+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, PRECISION INSIGHT 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:
+ * Gareth Hughes <gareth@valinux.com>
+ *
+ */
+
+#include "r128_context.h"
+#include "r128_lock.h"
+#include "r128_tex.h"
+#include "r128_state.h"
+
+#if DEBUG_LOCKING
+char *prevLockFile = NULL;
+int prevLockLine = 0;
+#endif
+
+
+/* Turn on/off page flipping according to the flags in the sarea:
+ */
+static void
+r128UpdatePageFlipping( r128ContextPtr rmesa )
+{
+ int use_back;
+
+ rmesa->doPageFlip = rmesa->sarea->pfAllowPageFlip;
+
+ use_back = (rmesa->glCtx->Color._DrawDestMask == BACK_LEFT_BIT);
+ use_back ^= (rmesa->sarea->pfCurrentPage == 1);
+
+ if ( R128_DEBUG & DEBUG_VERBOSE_API )
+ fprintf(stderr, "%s allow %d current %d\n", __FUNCTION__,
+ rmesa->doPageFlip,
+ rmesa->sarea->pfCurrentPage );
+
+ if ( use_back ) {
+ rmesa->drawOffset = rmesa->r128Screen->backOffset;
+ rmesa->drawPitch = rmesa->r128Screen->backPitch;
+ } else {
+ rmesa->drawOffset = rmesa->r128Screen->frontOffset;
+ rmesa->drawPitch = rmesa->r128Screen->frontPitch;
+ }
+
+ rmesa->setup.dst_pitch_offset_c = (((rmesa->drawPitch/8) << 21) |
+ (rmesa->drawOffset >> 5));
+ rmesa->new_state |= R128_NEW_WINDOW;
+}
+
+/* Update the hardware state. This is called if another context has
+ * grabbed the hardware lock, which includes the X server. This
+ * function also updates the driver's window state after the X server
+ * moves, resizes or restacks a window -- the change will be reflected
+ * in the drawable position and clip rects. Since the X server grabs
+ * the hardware lock when it changes the window state, this routine will
+ * automatically be called after such a change.
+ */
+void r128GetLock( r128ContextPtr rmesa, GLuint flags )
+{
+ __DRIdrawablePrivate *dPriv = rmesa->driDrawable;
+ __DRIscreenPrivate *sPriv = rmesa->driScreen;
+ R128SAREAPrivPtr sarea = rmesa->sarea;
+ int i;
+
+ drmGetLock( rmesa->driFd, rmesa->hHWContext, flags );
+
+ /* The window might have moved, so we might need to get new clip
+ * rects.
+ *
+ * NOTE: This releases and regrabs the hw lock to allow the X server
+ * to respond to the DRI protocol request for new drawable info.
+ * Since the hardware state depends on having the latest drawable
+ * clip rects, all state checking must be done _after_ this call.
+ */
+ DRI_VALIDATE_DRAWABLE_INFO( sPriv, dPriv );
+
+ if ( rmesa->lastStamp != dPriv->lastStamp ) {
+ r128UpdatePageFlipping( rmesa );
+ rmesa->lastStamp = dPriv->lastStamp;
+ rmesa->new_state |= R128_NEW_CLIP;
+ rmesa->SetupNewInputs = ~0;
+ }
+
+ rmesa->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_CLIPRECTS;
+
+ rmesa->numClipRects = dPriv->numClipRects;
+ rmesa->pClipRects = dPriv->pClipRects;
+
+ if ( sarea->ctxOwner != rmesa->hHWContext ) {
+ sarea->ctxOwner = rmesa->hHWContext;
+ rmesa->dirty = R128_UPLOAD_ALL;
+ }
+
+ for ( i = 0 ; i < rmesa->nr_heaps ; i++ ) {
+ DRI_AGE_TEXTURES( rmesa->texture_heaps[i] );
+ }
+}
diff --git a/src/mesa/drivers/dri/r128/r128_lock.h b/src/mesa/drivers/dri/r128/r128_lock.h
new file mode 100644
index 0000000000..e734ba29de
--- /dev/null
+++ b/src/mesa/drivers/dri/r128/r128_lock.h
@@ -0,0 +1,111 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_lock.h,v 1.4 2001/01/08 01:07:21 martin Exp $ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+ Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+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, PRECISION INSIGHT 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:
+ * Kevin E. Martin <martin@valinux.com>
+ * Gareth Hughes <gareth@valinux.com>
+ *
+ */
+
+#ifndef __R128_LOCK_H__
+#define __R128_LOCK_H__
+
+#ifdef GLX_DIRECT_RENDERING
+
+extern void r128GetLock( r128ContextPtr rmesa, GLuint flags );
+
+/* Turn DEBUG_LOCKING on to find locking conflicts.
+ */
+#define DEBUG_LOCKING 0
+
+#if DEBUG_LOCKING
+extern char *prevLockFile;
+extern int prevLockLine;
+
+#define DEBUG_LOCK() \
+ do { \
+ prevLockFile = (__FILE__); \
+ prevLockLine = (__LINE__); \
+ } while (0)
+
+#define DEBUG_RESET() \
+ do { \
+ prevLockFile = 0; \
+ prevLockLine = 0; \
+ } while (0)
+
+#define DEBUG_CHECK_LOCK() \
+ do { \
+ if ( prevLockFile ) { \
+ fprintf( stderr, \
+ "LOCK SET!\n\tPrevious %s:%d\n\tCurrent: %s:%d\n", \
+ prevLockFile, prevLockLine, __FILE__, __LINE__ ); \
+ exit( 1 ); \
+ } \
+ } while (0)
+
+#else
+
+#define DEBUG_LOCK()
+#define DEBUG_RESET()
+#define DEBUG_CHECK_LOCK()
+
+#endif
+
+/*
+ * !!! We may want to separate locks from locks with validation. This
+ * could be used to improve performance for those things commands that
+ * do not do any drawing !!!
+ */
+
+/* Lock the hardware and validate our state.
+ */
+#define LOCK_HARDWARE( rmesa ) \
+ do { \
+ char __ret = 0; \
+ DEBUG_CHECK_LOCK(); \
+ DRM_CAS( rmesa->driHwLock, rmesa->hHWContext, \
+ (DRM_LOCK_HELD | rmesa->hHWContext), __ret ); \
+ if ( __ret ) \
+ r128GetLock( rmesa, 0 ); \
+ DEBUG_LOCK(); \
+ } while (0)
+
+/* Unlock the hardware.
+ */
+#define UNLOCK_HARDWARE( rmesa ) \
+ do { \
+ DRM_UNLOCK( rmesa->driFd, \
+ rmesa->driHwLock, \
+ rmesa->hHWContext ); \
+ DEBUG_RESET(); \
+ } while (0)
+
+#endif
+#endif /* __R128_LOCK_H__ */
diff --git a/src/mesa/drivers/dri/r128/r128_screen.c b/src/mesa/drivers/dri/r128/r128_screen.c
new file mode 100644
index 0000000000..8a8fc25217
--- /dev/null
+++ b/src/mesa/drivers/dri/r128/r128_screen.c
@@ -0,0 +1,357 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_screen.c,v 1.8 2002/12/16 16:18:53 dawes Exp $ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+ Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+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, PRECISION INSIGHT 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:
+ * Gareth Hughes <gareth@valinux.com>
+ * Kevin E. Martin <martin@valinux.com>
+ *
+ */
+
+#include "r128_dri.h"
+
+#include "r128_context.h"
+#include "r128_ioctl.h"
+#include "r128_tris.h"
+#include "r128_vb.h"
+
+#include "context.h"
+#include "imports.h"
+
+#include "utils.h"
+#include "vblank.h"
+
+#ifndef _SOLO
+#include "glxextensions.h"
+#endif
+
+#if 1
+/* Including xf86PciInfo.h introduces a bunch of errors...
+ */
+#define PCI_CHIP_RAGE128LE 0x4C45
+#define PCI_CHIP_RAGE128LF 0x4C46
+#define PCI_CHIP_RAGE128PD 0x5044
+#define PCI_CHIP_RAGE128PF 0x5046
+#define PCI_CHIP_RAGE128PR 0x5052
+#define PCI_CHIP_RAGE128RE 0x5245
+#define PCI_CHIP_RAGE128RF 0x5246
+#define PCI_CHIP_RAGE128RK 0x524B
+#define PCI_CHIP_RAGE128RL 0x524C
+#endif
+
+
+/* Create the device specific screen private data struct.
+ */
+static r128ScreenPtr
+r128CreateScreen( __DRIscreenPrivate *sPriv )
+{
+ r128ScreenPtr r128Screen;
+ R128DRIPtr r128DRIPriv = (R128DRIPtr)sPriv->pDevPriv;
+
+ if ( ! driCheckDriDdxDrmVersions( sPriv, "Rage128", 4, 0, 4, 0, 2, 2 ) )
+ return NULL;
+
+ /* Allocate the private area */
+ r128Screen = (r128ScreenPtr) CALLOC( sizeof(*r128Screen) );
+ if ( !r128Screen ) return NULL;
+
+ /* This is first since which regions we map depends on whether or
+ * not we are using a PCI card.
+ */
+ r128Screen->IsPCI = r128DRIPriv->IsPCI;
+ r128Screen->sarea_priv_offset = r128DRIPriv->sarea_priv_offset;
+
+ if (sPriv->drmMinor >= 3) {
+ drmR128GetParam gp;
+ int ret;
+
+ gp.param = R128_PARAM_IRQ_NR;
+ gp.value = &r128Screen->irq;
+
+ ret = drmCommandWriteRead( sPriv->fd, DRM_R128_GETPARAM,
+ &gp, sizeof(gp));
+ if (ret) {
+ fprintf(stderr, "drmR128GetParam (R128_PARAM_IRQ_NR): %d\n", ret);
+ FREE( r128Screen );
+ return NULL;
+ }
+ }
+
+ r128Screen->mmio.handle = r128DRIPriv->registerHandle;
+ r128Screen->mmio.size = r128DRIPriv->registerSize;
+ if ( drmMap( sPriv->fd,
+ r128Screen->mmio.handle,
+ r128Screen->mmio.size,
+ (drmAddressPtr)&r128Screen->mmio.map ) ) {
+ FREE( r128Screen );
+ return NULL;
+ }
+
+ r128Screen->buffers = drmMapBufs( sPriv->fd );
+ if ( !r128Screen->buffers ) {
+ drmUnmap( (drmAddress)r128Screen->mmio.map, r128Screen->mmio.size );
+ FREE( r128Screen );
+ return NULL;
+ }
+
+ if ( !r128Screen->IsPCI ) {
+ r128Screen->agpTextures.handle = r128DRIPriv->agpTexHandle;
+ r128Screen->agpTextures.size = r128DRIPriv->agpTexMapSize;
+ if ( drmMap( sPriv->fd,
+ r128Screen->agpTextures.handle,
+ r128Screen->agpTextures.size,
+ (drmAddressPtr)&r128Screen->agpTextures.map ) ) {
+ drmUnmapBufs( r128Screen->buffers );
+ drmUnmap( (drmAddress)r128Screen->mmio.map, r128Screen->mmio.size );
+ FREE( r128Screen );
+ return NULL;
+ }
+ }
+
+ switch ( r128DRIPriv->deviceID ) {
+ case PCI_CHIP_RAGE128RE:
+ case PCI_CHIP_RAGE128RF:
+ case PCI_CHIP_RAGE128RK:
+ case PCI_CHIP_RAGE128RL:
+ r128Screen->chipset = R128_CARD_TYPE_R128;
+ break;
+ case PCI_CHIP_RAGE128PD:
+ case PCI_CHIP_RAGE128PF:
+ r128Screen->chipset = R128_CARD_TYPE_R128_PRO;
+ break;
+ case PCI_CHIP_RAGE128LE:
+ case PCI_CHIP_RAGE128LF:
+ r128Screen->chipset = R128_CARD_TYPE_R128_MOBILITY;
+ break;
+ default:
+ r128Screen->chipset = R128_CARD_TYPE_R128;
+ break;
+ }
+
+ r128Screen->cpp = r128DRIPriv->bpp / 8;
+ r128Screen->AGPMode = r128DRIPriv->AGPMode;
+
+ r128Screen->frontOffset = r128DRIPriv->frontOffset;
+ r128Screen->frontPitch = r128DRIPriv->frontPitch;
+ r128Screen->backOffset = r128DRIPriv->backOffset;
+ r128Screen->backPitch = r128DRIPriv->backPitch;
+ r128Screen->depthOffset = r128DRIPriv->depthOffset;
+ r128Screen->depthPitch = r128DRIPriv->depthPitch;
+ r128Screen->spanOffset = r128DRIPriv->spanOffset;
+
+ r128Screen->texOffset[R128_CARD_HEAP] = r128DRIPriv->textureOffset;
+ r128Screen->texSize[R128_CARD_HEAP] = r128DRIPriv->textureSize;
+ r128Screen->logTexGranularity[R128_CARD_HEAP] = r128DRIPriv->log2TexGran;
+
+ if ( r128Screen->IsPCI ) {
+ r128Screen->numTexHeaps = R128_NR_TEX_HEAPS - 1;
+ r128Screen->texOffset[R128_AGP_HEAP] = 0;
+ r128Screen->texSize[R128_AGP_HEAP] = 0;
+ r128Screen->logTexGranularity[R128_AGP_HEAP] = 0;
+ } else {
+ r128Screen->numTexHeaps = R128_NR_TEX_HEAPS;
+ r128Screen->texOffset[R128_AGP_HEAP] =
+ r128DRIPriv->agpTexOffset + R128_AGP_TEX_OFFSET;
+ r128Screen->texSize[R128_AGP_HEAP] = r128DRIPriv->agpTexMapSize;
+ r128Screen->logTexGranularity[R128_AGP_HEAP] =
+ r128DRIPriv->log2AGPTexGran;
+ }
+
+ r128Screen->driScreen = sPriv;
+
+ return r128Screen;
+}
+
+/* Destroy the device specific screen private data struct.
+ */
+static void
+r128DestroyScreen( __DRIscreenPrivate *sPriv )
+{
+ r128ScreenPtr r128Screen = (r128ScreenPtr)sPriv->private;
+
+ if ( !r128Screen )
+ return;
+
+ if ( !r128Screen->IsPCI ) {
+ drmUnmap( (drmAddress)r128Screen->agpTextures.map,
+ r128Screen->agpTextures.size );
+ }
+ drmUnmapBufs( r128Screen->buffers );
+ drmUnmap( (drmAddress)r128Screen->mmio.map, r128Screen->mmio.size );
+
+ FREE( r128Screen );
+ sPriv->private = NULL;
+}
+
+
+/* Initialize the fullscreen mode.
+ */
+static GLboolean
+r128OpenCloseFullScreen( __DRIcontextPrivate *driContextPriv )
+{
+ return GL_TRUE;
+}
+
+
+/* Create and initialize the Mesa and driver specific pixmap buffer
+ * data.
+ */
+static GLboolean
+r128CreateBuffer( __DRIscreenPrivate *driScrnPriv,
+ __DRIdrawablePrivate *driDrawPriv,
+ const __GLcontextModes *mesaVis,
+ GLboolean isPixmap )
+{
+ if (isPixmap) {
+ return GL_FALSE; /* not implemented */
+ }
+ else {
+ driDrawPriv->driverPrivate = (void *)
+ _mesa_create_framebuffer( mesaVis,
+ GL_FALSE, /* software depth buffer? */
+ mesaVis->stencilBits > 0,
+ mesaVis->accumRedBits > 0,
+ mesaVis->alphaBits > 0 );
+ return (driDrawPriv->driverPrivate != NULL);
+ }
+}
+
+
+static void
+r128DestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
+{
+ _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
+}
+
+
+/* Copy the back color buffer to the front color buffer */
+static void
+r128SwapBuffers(__DRIdrawablePrivate *dPriv)
+{
+ if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
+ r128ContextPtr rmesa;
+ GLcontext *ctx;
+ rmesa = (r128ContextPtr) dPriv->driContextPriv->driverPrivate;
+ ctx = rmesa->glCtx;
+ if (ctx->Visual.doubleBufferMode) {
+ _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
+ if ( rmesa->doPageFlip ) {
+ r128PageFlip( dPriv );
+ }
+ else {
+ r128CopyBuffer( 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!", __FUNCTION__);
+ }
+}
+
+
+/* Initialize the driver specific screen private data.
+ */
+static GLboolean
+r128InitDriver( __DRIscreenPrivate *sPriv )
+{
+ sPriv->private = (void *) r128CreateScreen( sPriv );
+
+ if ( !sPriv->private ) {
+ r128DestroyScreen( sPriv );
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+
+#ifndef _SOLO
+/* This function is called by libGL.so as soon as libGL.so is loaded.
+ * This is where we register new extension functions with the dispatcher.
+ */
+void __driRegisterExtensions( void )
+{
+ PFNGLXENABLEEXTENSIONPROC glx_enable_extension;
+
+ if ( driCompareGLXAPIVersion( 20030317 ) >= 0 ) {
+ glx_enable_extension = (PFNGLXENABLEEXTENSIONPROC)
+ glXGetProcAddress( "__glXEnableExtension" );
+
+ if ( glx_enable_extension != NULL ) {
+ glx_enable_extension( "GLX_SGI_swap_control", GL_FALSE );
+ glx_enable_extension( "GLX_SGI_video_sync", GL_FALSE );
+ glx_enable_extension( "GLX_MESA_swap_control", GL_FALSE );
+ }
+ }
+}
+#endif
+
+static struct __DriverAPIRec r128API = {
+ .InitDriver = r128InitDriver,
+ .DestroyScreen = r128DestroyScreen,
+ .CreateContext = r128CreateContext,
+ .DestroyContext = r128DestroyContext,
+ .CreateBuffer = r128CreateBuffer,
+ .DestroyBuffer = r128DestroyBuffer,
+ .SwapBuffers = r128SwapBuffers,
+ .MakeCurrent = r128MakeCurrent,
+ .UnbindContext = r128UnbindContext,
+ .OpenFullScreen = r128OpenCloseFullScreen,
+ .CloseFullScreen = r128OpenCloseFullScreen,
+ .GetSwapInfo = NULL,
+ .GetMSC = driGetMSC32,
+ .WaitForMSC = driWaitForMSC32,
+ .WaitForSBC = NULL,
+ .SwapBuffersMSC = NULL
+
+};
+
+
+/*
+ * This is the bootstrap function for the driver.
+ * The __driCreateScreen name is the symbol that libGL.so fetches.
+ * Return: pointer to a __DRIscreenPrivate.
+ */
+#ifndef _SOLO
+void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
+ int numConfigs, __GLXvisualConfig *config)
+{
+ __DRIscreenPrivate *psp;
+ psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &r128API);
+ return (void *) psp;
+}
+#else
+void *__driCreateScreen(struct DRIDriverRec *driver,
+ struct DRIDriverContextRec *driverContext)
+{
+ __DRIscreenPrivate *psp;
+ psp = __driUtilCreateScreen(driver, driverContext, &r128API);
+ return (void *) psp;
+}
+#endif
diff --git a/src/mesa/drivers/dri/r128/r128_screen.h b/src/mesa/drivers/dri/r128/r128_screen.h
new file mode 100644
index 0000000000..4b1a57292d
--- /dev/null
+++ b/src/mesa/drivers/dri/r128/r128_screen.h
@@ -0,0 +1,84 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_screen.h,v 1.7 2002/12/16 16:18:53 dawes Exp $ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+ Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+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, PRECISION INSIGHT 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:
+ * Gareth Hughes <gareth@valinux.com>
+ * Kevin E. Martin <martin@valinux.com>
+ *
+ */
+
+#ifndef __R128_SCREEN_H__
+#define __R128_SCREEN_H__
+
+#ifdef GLX_DIRECT_RENDERING
+
+#include "r128_sarea.h"
+
+typedef struct {
+ drmHandle handle; /* Handle to the DRM region */
+ drmSize size; /* Size of the DRM region */
+ unsigned char *map; /* Mapping of the DRM region */
+} r128RegionRec, *r128RegionPtr;
+
+typedef struct {
+
+ GLint chipset;
+ GLint cpp;
+ GLint IsPCI; /* Current card is a PCI card */
+ GLint AGPMode;
+ unsigned int irq; /* IRQ number (0 means none) */
+
+ GLuint frontOffset;
+ GLuint frontPitch;
+ GLuint backOffset;
+ GLuint backPitch;
+
+ GLuint depthOffset;
+ GLuint depthPitch;
+ GLuint spanOffset;
+
+ /* Shared texture data */
+ GLint numTexHeaps;
+ GLint texOffset[R128_NR_TEX_HEAPS];
+ GLint texSize[R128_NR_TEX_HEAPS];
+ GLint logTexGranularity[R128_NR_TEX_HEAPS];
+
+ r128RegionRec mmio;
+ r128RegionRec agpTextures;
+
+ drmBufMapPtr buffers;
+
+ __DRIscreenPrivate *driScreen;
+ unsigned int sarea_priv_offset;
+
+} r128ScreenRec, *r128ScreenPtr;
+
+
+#endif
+#endif /* __R128_SCREEN_H__ */
diff --git a/src/mesa/drivers/dri/r128/r128_span.c b/src/mesa/drivers/dri/r128/r128_span.c
new file mode 100644
index 0000000000..c6f3195942
--- /dev/null
+++ b/src/mesa/drivers/dri/r128/r128_span.c
@@ -0,0 +1,475 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_span.c,v 1.8 2002/10/30 12:51:39 alanh Exp $ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+ Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+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, PRECISION INSIGHT 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:
+ * Gareth Hughes <gareth@valinux.com>
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Kevin E. Martin <martin@valinux.com>
+ *
+ */
+
+#include "r128_context.h"
+#include "r128_ioctl.h"
+#include "r128_state.h"
+#include "r128_span.h"
+#include "r128_tex.h"
+
+#include "swrast/swrast.h"
+
+#define DBG 0
+
+#define HAVE_HW_DEPTH_SPANS 1
+#define HAVE_HW_DEPTH_PIXELS 1
+
+#define LOCAL_VARS \
+ r128ContextPtr rmesa = R128_CONTEXT(ctx); \
+ r128ScreenPtr r128scrn = rmesa->r128Screen; \
+ __DRIscreenPrivate *sPriv = rmesa->driScreen; \
+ __DRIdrawablePrivate *dPriv = rmesa->driDrawable; \
+ GLuint pitch = r128scrn->frontPitch * r128scrn->cpp; \
+ GLuint height = dPriv->h; \
+ char *buf = (char *)(sPriv->pFB + \
+ rmesa->drawOffset + \
+ (dPriv->x * r128scrn->cpp) + \
+ (dPriv->y * pitch)); \
+ char *read_buf = (char *)(sPriv->pFB + \
+ rmesa->readOffset + \
+ (dPriv->x * r128scrn->cpp) + \
+ (dPriv->y * pitch)); \
+ GLuint p; \
+ (void) read_buf; (void) buf; (void) p
+
+#define LOCAL_DEPTH_VARS \
+ r128ContextPtr rmesa = R128_CONTEXT(ctx); \
+ r128ScreenPtr r128scrn = rmesa->r128Screen; \
+ __DRIscreenPrivate *sPriv = rmesa->driScreen; \
+ __DRIdrawablePrivate *dPriv = rmesa->driDrawable; \
+ GLuint height = dPriv->h; \
+ (void) r128scrn; (void) sPriv; (void) height
+
+#define LOCAL_STENCIL_VARS LOCAL_DEPTH_VARS
+
+
+#define CLIPPIXEL( _x, _y ) \
+ ((_x >= minx) && (_x < maxx) && (_y >= miny) && (_y < maxy))
+
+
+#define CLIPSPAN( _x, _y, _n, _x1, _n1, _i ) \
+ if ( _y < miny || _y >= maxy ) { \
+ _n1 = 0, _x1 = x; \
+ } else { \
+ _n1 = _n; \
+ _x1 = _x; \
+ if ( _x1 < minx ) _i += (minx-_x1), n1 -= (minx-_x1), _x1 = minx; \
+ if ( _x1 + _n1 >= maxx ) n1 -= (_x1 + n1 - maxx); \
+ }
+
+#define Y_FLIP( _y ) (height - _y - 1)
+
+
+#define HW_LOCK() \
+ r128ContextPtr rmesa = R128_CONTEXT(ctx); \
+ FLUSH_BATCH( rmesa ); \
+ LOCK_HARDWARE( rmesa ); \
+ r128WaitForIdleLocked( rmesa );
+
+#define HW_CLIPLOOP() \
+ do { \
+ __DRIdrawablePrivate *dPriv = rmesa->driDrawable; \
+ int _nc = dPriv->numClipRects; \
+ \
+ while ( _nc-- ) { \
+ int minx = dPriv->pClipRects[_nc].x1 - dPriv->x; \
+ int miny = dPriv->pClipRects[_nc].y1 - dPriv->y; \
+ int maxx = dPriv->pClipRects[_nc].x2 - dPriv->x; \
+ int maxy = dPriv->pClipRects[_nc].y2 - dPriv->y;
+
+#define HW_ENDCLIPLOOP() \
+ } \
+ } while (0)
+
+#define HW_UNLOCK() \
+ UNLOCK_HARDWARE( rmesa )
+
+
+
+/* ================================================================
+ * Color buffer
+ */
+
+/* 16 bit, RGB565 color spanline and pixel functions
+ */
+#undef INIT_MONO_PIXEL
+#define INIT_MONO_PIXEL(p, color) \
+ p = R128PACKCOLOR565( color[0], color[1], color[2] )
+
+#define WRITE_RGBA( _x, _y, r, g, b, a ) \
+ *(GLushort *)(buf + _x*2 + _y*pitch) = ((((int)r & 0xf8) << 8) | \
+ (((int)g & 0xfc) << 3) | \
+ (((int)b & 0xf8) >> 3))
+
+#define WRITE_PIXEL( _x, _y, p ) \
+ *(GLushort *)(buf + _x*2 + _y*pitch) = p
+
+#define READ_RGBA( rgba, _x, _y ) \
+ do { \
+ GLushort p = *(GLushort *)(read_buf + _x*2 + _y*pitch); \
+ rgba[0] = (p >> 8) & 0xf8; \
+ rgba[1] = (p >> 3) & 0xfc; \
+ rgba[2] = (p << 3) & 0xf8; \
+ rgba[3] = 0xff; \
+ if ( rgba[0] & 0x08 ) rgba[0] |= 0x07; \
+ if ( rgba[1] & 0x04 ) rgba[1] |= 0x03; \
+ if ( rgba[2] & 0x08 ) rgba[2] |= 0x07; \
+ } while (0)
+
+#define TAG(x) r128##x##_RGB565
+#include "spantmp.h"
+
+#define READ_DEPTH(d, _x, _y) \
+ d = *(GLushort *)(buf + _x*2 + _y*pitch)
+
+/* 32 bit, ARGB8888 color spanline and pixel functions
+ */
+#undef INIT_MONO_PIXEL
+#define INIT_MONO_PIXEL(p, color) \
+ p = R128PACKCOLOR8888( color[0], color[1], color[2], color[3] )
+
+#define WRITE_RGBA( _x, _y, r, g, b, a ) \
+ *(GLuint *)(buf + _x*4 + _y*pitch) = ((b << 0) | \
+ (g << 8) | \
+ (r << 16) | \
+ (a << 24) )
+
+#define WRITE_PIXEL( _x, _y, p ) \
+ *(GLuint *)(buf + _x*4 + _y*pitch) = p
+
+#define READ_RGBA( rgba, _x, _y ) \
+do { \
+ GLuint p = *(GLuint *)(read_buf + _x*4 + _y*pitch); \
+ rgba[0] = (p >> 16) & 0xff; \
+ rgba[1] = (p >> 8) & 0xff; \
+ rgba[2] = (p >> 0) & 0xff; \
+ rgba[3] = 0xff;/*(p >> 24) & 0xff;*/ \
+} while (0)
+
+#define TAG(x) r128##x##_ARGB8888
+#include "spantmp.h"
+
+
+/* 24 bit, RGB888 color spanline and pixel functions */
+#undef INIT_MONO_PIXEL
+#define INIT_MONO_PIXEL(p, color) \
+ p = R128PACKCOLOR888( color[0], color[1], color[2] )
+
+#define WRITE_RGBA(_x, _y, r, g, b, a) \
+ *(GLuint *)(buf + _x*3 + _y*pitch) = ((r << 16) | \
+ (g << 8) | \
+ (b << 0))
+
+#define WRITE_PIXEL(_x, _y, p) \
+ *(GLuint *)(buf + _x*3 + _y*pitch) = p
+
+#define READ_RGBA(rgba, _x, _y) \
+ do { \
+ GLuint p = *(GLuint *)(read_buf + _x*3 + _y*pitch); \
+ rgba[0] = (p >> 16) & 0xff; \
+ rgba[1] = (p >> 8) & 0xff; \
+ rgba[2] = (p >> 0) & 0xff; \
+ rgba[3] = 0xff; \
+ } while (0)
+
+/* ================================================================
+ * Depth buffer
+ */
+
+/* 16-bit depth buffer functions
+ */
+#define WRITE_DEPTH_SPAN() \
+ r128WriteDepthSpanLocked( rmesa, n, \
+ x + dPriv->x, \
+ y + dPriv->y, \
+ depth, mask );
+
+#define WRITE_DEPTH_PIXELS() \
+do { \
+ GLint ox[MAX_WIDTH]; \
+ GLint oy[MAX_WIDTH]; \
+ for ( i = 0 ; i < n ; i++ ) { \
+ ox[i] = x[i] + dPriv->x; \
+ } \
+ for ( i = 0 ; i < n ; i++ ) { \
+ oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
+ } \
+ r128WriteDepthPixelsLocked( rmesa, n, ox, oy, depth, mask ); \
+} while (0)
+
+#define READ_DEPTH_SPAN() \
+do { \
+ GLushort *buf = (GLushort *)((GLubyte *)sPriv->pFB + \
+ r128scrn->spanOffset); \
+ GLint i; \
+ \
+ r128ReadDepthSpanLocked( rmesa, n, \
+ x + dPriv->x, \
+ y + dPriv->y ); \
+ r128WaitForIdleLocked( rmesa ); \
+ \
+ for ( i = 0 ; i < n ; i++ ) { \
+ depth[i] = buf[i]; \
+ } \
+} while (0)
+
+#define READ_DEPTH_PIXELS() \
+do { \
+ GLushort *buf = (GLushort *)((GLubyte *)sPriv->pFB + \
+ r128scrn->spanOffset); \
+ GLint i, remaining = n; \
+ \
+ while ( remaining > 0 ) { \
+ GLint ox[MAX_WIDTH]; \
+ GLint oy[MAX_WIDTH]; \
+ GLint count; \
+ \
+ if ( remaining <= 128 ) { \
+ count = remaining; \
+ } else { \
+ count = 128; \
+ } \
+ for ( i = 0 ; i < count ; i++ ) { \
+ ox[i] = x[i] + dPriv->x; \
+ } \
+ for ( i = 0 ; i < count ; i++ ) { \
+ oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
+ } \
+ \
+ r128ReadDepthPixelsLocked( rmesa, count, ox, oy ); \
+ r128WaitForIdleLocked( rmesa ); \
+ \
+ for ( i = 0 ; i < count ; i++ ) { \
+ depth[i] = buf[i]; \
+ } \
+ depth += count; \
+ x += count; \
+ y += count; \
+ remaining -= count; \
+ } \
+} while (0)
+
+#define TAG(x) r128##x##_16
+#include "depthtmp.h"
+
+
+/* 24-bit depth, 8-bit stencil buffer functions
+ */
+#define WRITE_DEPTH_SPAN() \
+ r128WriteDepthSpanLocked( rmesa, n, \
+ x + dPriv->x, \
+ y + dPriv->y, \
+ depth, mask );
+
+#define WRITE_DEPTH_PIXELS() \
+do { \
+ GLint ox[MAX_WIDTH]; \
+ GLint oy[MAX_WIDTH]; \
+ for ( i = 0 ; i < n ; i++ ) { \
+ ox[i] = x[i] + dPriv->x; \
+ } \
+ for ( i = 0 ; i < n ; i++ ) { \
+ oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
+ } \
+ r128WriteDepthPixelsLocked( rmesa, n, ox, oy, depth, mask ); \
+} while (0)
+
+#define READ_DEPTH_SPAN() \
+do { \
+ GLuint *buf = (GLuint *)((GLubyte *)sPriv->pFB + \
+ r128scrn->spanOffset); \
+ GLint i; \
+ \
+ r128ReadDepthSpanLocked( rmesa, n, \
+ x + dPriv->x, \
+ y + dPriv->y ); \
+ r128WaitForIdleLocked( rmesa ); \
+ \
+ for ( i = 0 ; i < n ; i++ ) { \
+ depth[i] = buf[i] & 0x00ffffff; \
+ } \
+} while (0)
+
+#define READ_DEPTH_PIXELS() \
+do { \
+ GLuint *buf = (GLuint *)((GLubyte *)sPriv->pFB + \
+ r128scrn->spanOffset); \
+ GLint i, remaining = n; \
+ \
+ while ( remaining > 0 ) { \
+ GLint ox[MAX_WIDTH]; \
+ GLint oy[MAX_WIDTH]; \
+ GLint count; \
+ \
+ if ( remaining <= 128 ) { \
+ count = remaining; \
+ } else { \
+ count = 128; \
+ } \
+ for ( i = 0 ; i < count ; i++ ) { \
+ ox[i] = x[i] + dPriv->x; \
+ } \
+ for ( i = 0 ; i < count ; i++ ) { \
+ oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
+ } \
+ \
+ r128ReadDepthPixelsLocked( rmesa, count, ox, oy ); \
+ r128WaitForIdleLocked( rmesa ); \
+ \
+ for ( i = 0 ; i < count ; i++ ) { \
+ depth[i] = buf[i] & 0x00ffffff; \
+ } \
+ depth += count; \
+ x += count; \
+ y += count; \
+ remaining -= count; \
+ } \
+} while (0)
+
+#define TAG(x) r128##x##_24_8
+#include "depthtmp.h"
+
+
+
+/* ================================================================
+ * Stencil buffer
+ */
+
+/* FIXME: Add support for hardware stencil buffers.
+ */
+
+
+/* 32 bit depthbuffer functions */
+#define WRITE_DEPTH(_x, _y, d) \
+ *(GLuint *)(buf + _x*4 + _y*pitch) = d
+
+
+
+/*
+ * This function is called to specify which buffer to read and write
+ * for software rasterization (swrast) fallbacks. This doesn't necessarily
+ * correspond to glDrawBuffer() or glReadBuffer() calls.
+ */
+static void r128DDSetBuffer( GLcontext *ctx,
+ GLframebuffer *colorBuffer,
+ GLuint bufferBit )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+ switch ( bufferBit ) {
+ case FRONT_LEFT_BIT:
+ if ( rmesa->sarea->pfCurrentPage == 1 ) {
+ rmesa->drawOffset = rmesa->readOffset = rmesa->r128Screen->backOffset;
+ rmesa->drawPitch = rmesa->readPitch = rmesa->r128Screen->backPitch;
+ } else {
+ rmesa->drawOffset = rmesa->readOffset = rmesa->r128Screen->frontOffset;
+ rmesa->drawPitch = rmesa->readPitch = rmesa->r128Screen->frontPitch;
+ }
+ break;
+ case BACK_LEFT_BIT:
+ if ( rmesa->sarea->pfCurrentPage == 1 ) {
+ rmesa->drawOffset = rmesa->readOffset = rmesa->r128Screen->frontOffset;
+ rmesa->drawPitch = rmesa->readPitch = rmesa->r128Screen->frontPitch;
+ } else {
+ rmesa->drawOffset = rmesa->readOffset = rmesa->r128Screen->backOffset;
+ rmesa->drawPitch = rmesa->readPitch = rmesa->r128Screen->backPitch;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+
+void r128DDInitSpanFuncs( GLcontext *ctx )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+ struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx);
+
+ swdd->SetBuffer = r128DDSetBuffer;
+
+ switch ( rmesa->r128Screen->cpp ) {
+ case 2:
+ swdd->WriteRGBASpan = r128WriteRGBASpan_RGB565;
+ swdd->WriteRGBSpan = r128WriteRGBSpan_RGB565;
+ swdd->WriteMonoRGBASpan = r128WriteMonoRGBASpan_RGB565;
+ swdd->WriteRGBAPixels = r128WriteRGBAPixels_RGB565;
+ swdd->WriteMonoRGBAPixels = r128WriteMonoRGBAPixels_RGB565;
+ swdd->ReadRGBASpan = r128ReadRGBASpan_RGB565;
+ swdd->ReadRGBAPixels = r128ReadRGBAPixels_RGB565;
+ break;
+
+ case 4:
+ swdd->WriteRGBASpan = r128WriteRGBASpan_ARGB8888;
+ swdd->WriteRGBSpan = r128WriteRGBSpan_ARGB8888;
+ swdd->WriteMonoRGBASpan = r128WriteMonoRGBASpan_ARGB8888;
+ swdd->WriteRGBAPixels = r128WriteRGBAPixels_ARGB8888;
+ swdd->WriteMonoRGBAPixels = r128WriteMonoRGBAPixels_ARGB8888;
+ swdd->ReadRGBASpan = r128ReadRGBASpan_ARGB8888;
+ swdd->ReadRGBAPixels = r128ReadRGBAPixels_ARGB8888;
+ break;
+
+ default:
+ break;
+ }
+
+ switch ( rmesa->glCtx->Visual.depthBits ) {
+ case 16:
+ swdd->ReadDepthSpan = r128ReadDepthSpan_16;
+ swdd->WriteDepthSpan = r128WriteDepthSpan_16;
+ swdd->ReadDepthPixels = r128ReadDepthPixels_16;
+ swdd->WriteDepthPixels = r128WriteDepthPixels_16;
+ break;
+
+ case 24:
+ swdd->ReadDepthSpan = r128ReadDepthSpan_24_8;
+ swdd->WriteDepthSpan = r128WriteDepthSpan_24_8;
+ swdd->ReadDepthPixels = r128ReadDepthPixels_24_8;
+ swdd->WriteDepthPixels = r128WriteDepthPixels_24_8;
+ break;
+
+ default:
+ break;
+ }
+
+ swdd->WriteCI8Span = NULL;
+ swdd->WriteCI32Span = NULL;
+ swdd->WriteMonoCISpan = NULL;
+ swdd->WriteCI32Pixels = NULL;
+ swdd->WriteMonoCIPixels = NULL;
+ swdd->ReadCI32Span = NULL;
+ swdd->ReadCI32Pixels = NULL;
+}
diff --git a/src/mesa/drivers/dri/r128/r128_span.h b/src/mesa/drivers/dri/r128/r128_span.h
new file mode 100644
index 0000000000..44356c5b24
--- /dev/null
+++ b/src/mesa/drivers/dri/r128/r128_span.h
@@ -0,0 +1,44 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_span.h,v 1.3 2001/01/08 01:07:21 martin Exp $ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+ Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+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, PRECISION INSIGHT 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:
+ * Gareth Hughes <gareth@valinux.com>
+ * Kevin E. Martin <martin@valinux.com>
+ *
+ */
+
+#ifndef __R128_SPAN_H__
+#define __R128_SPAN_H__
+
+#ifdef GLX_DIRECT_RENDERING
+
+extern void r128DDInitSpanFuncs( GLcontext *ctx );
+
+#endif
+#endif
diff --git a/src/mesa/drivers/dri/r128/r128_state.c b/src/mesa/drivers/dri/r128/r128_state.c
new file mode 100644
index 0000000000..85b3b68402
--- /dev/null
+++ b/src/mesa/drivers/dri/r128/r128_state.c
@@ -0,0 +1,1239 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_state.c,v 1.11 2002/10/30 12:51:39 alanh Exp $ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+ Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+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, PRECISION INSIGHT 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:
+ * Gareth Hughes <gareth@valinux.com>
+ * Kevin E. Martin <martin@valinux.com>
+ * Keith Whitwell <keith@tungstengraphics.com>
+ *
+ */
+
+#include "r128_context.h"
+#include "r128_state.h"
+#include "r128_ioctl.h"
+#include "r128_tris.h"
+#include "r128_vb.h"
+#include "r128_tex.h"
+
+#include "context.h"
+#include "enums.h"
+#include "colormac.h"
+#include "swrast/swrast.h"
+#include "array_cache/acache.h"
+#include "tnl/tnl.h"
+#include "swrast_setup/swrast_setup.h"
+
+#include "tnl/t_pipeline.h"
+
+
+/* =============================================================
+ * Alpha blending
+ */
+
+static void r128UpdateAlphaMode( GLcontext *ctx )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+ GLuint a = rmesa->setup.misc_3d_state_cntl_reg;
+ GLuint t = rmesa->setup.tex_cntl_c;
+
+ if ( ctx->Color.AlphaEnabled ) {
+ GLubyte ref;
+
+ CLAMPED_FLOAT_TO_UBYTE(ref, ctx->Color.AlphaRef);
+
+ a &= ~(R128_ALPHA_TEST_MASK | R128_REF_ALPHA_MASK);
+
+ switch ( ctx->Color.AlphaFunc ) {
+ case GL_NEVER:
+ a |= R128_ALPHA_TEST_NEVER;
+ break;
+ case GL_LESS:
+ a |= R128_ALPHA_TEST_LESS;
+ break;
+ case GL_LEQUAL:
+ a |= R128_ALPHA_TEST_LESSEQUAL;
+ break;
+ case GL_EQUAL:
+ a |= R128_ALPHA_TEST_EQUAL;
+ break;
+ case GL_GEQUAL:
+ a |= R128_ALPHA_TEST_GREATEREQUAL;
+ break;
+ case GL_GREATER:
+ a |= R128_ALPHA_TEST_GREATER;
+ break;
+ case GL_NOTEQUAL:
+ a |= R128_ALPHA_TEST_NEQUAL;
+ break;
+ case GL_ALWAYS:
+ a |= R128_ALPHA_TEST_ALWAYS;
+ break;
+ }
+
+ a |= ref & R128_REF_ALPHA_MASK;
+ t |= R128_ALPHA_TEST_ENABLE;
+ } else {
+ t &= ~R128_ALPHA_TEST_ENABLE;
+ }
+
+ FALLBACK( rmesa, R128_FALLBACK_BLEND_FUNC, GL_FALSE );
+
+ if ( ctx->Color.BlendEnabled ) {
+ a &= ~(R128_ALPHA_BLEND_SRC_MASK | R128_ALPHA_BLEND_DST_MASK);
+
+ switch ( ctx->Color.BlendSrcRGB ) {
+ case GL_ZERO:
+ a |= R128_ALPHA_BLEND_SRC_ZERO;
+ break;
+ case GL_ONE:
+ a |= R128_ALPHA_BLEND_SRC_ONE;
+ break;
+ case GL_DST_COLOR:
+ a |= R128_ALPHA_BLEND_SRC_DESTCOLOR;
+ break;
+ case GL_ONE_MINUS_DST_COLOR:
+ a |= R128_ALPHA_BLEND_SRC_INVDESTCOLOR;
+ break;
+ case GL_SRC_ALPHA:
+ a |= R128_ALPHA_BLEND_SRC_SRCALPHA;
+ break;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ a |= R128_ALPHA_BLEND_SRC_INVSRCALPHA;
+ break;
+ case GL_DST_ALPHA:
+ a |= R128_ALPHA_BLEND_SRC_DESTALPHA;
+ break;
+ case GL_ONE_MINUS_DST_ALPHA:
+ a |= R128_ALPHA_BLEND_SRC_INVDESTALPHA;
+ break;
+ case GL_SRC_ALPHA_SATURATE:
+ a |= R128_ALPHA_BLEND_SRC_SRCALPHASAT;
+ break;
+ default:
+ FALLBACK( rmesa, R128_FALLBACK_BLEND_FUNC, GL_TRUE );
+ }
+
+ switch ( ctx->Color.BlendDstRGB ) {
+ case GL_ZERO:
+ a |= R128_ALPHA_BLEND_DST_ZERO;
+ break;
+ case GL_ONE:
+ a |= R128_ALPHA_BLEND_DST_ONE;
+ break;
+ case GL_SRC_COLOR:
+ a |= R128_ALPHA_BLEND_DST_SRCCOLOR;
+ break;
+ case GL_ONE_MINUS_SRC_COLOR:
+ a |= R128_ALPHA_BLEND_DST_INVSRCCOLOR;
+ break;
+ case GL_SRC_ALPHA:
+ a |= R128_ALPHA_BLEND_DST_SRCALPHA;
+ break;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ a |= R128_ALPHA_BLEND_DST_INVSRCALPHA;
+ break;
+ case GL_DST_ALPHA:
+ a |= R128_ALPHA_BLEND_DST_DESTALPHA;
+ break;
+ case GL_ONE_MINUS_DST_ALPHA:
+ a |= R128_ALPHA_BLEND_DST_INVDESTALPHA;
+ break;
+ default:
+ FALLBACK( rmesa, R128_FALLBACK_BLEND_FUNC, GL_TRUE );
+ }
+
+ t |= R128_ALPHA_ENABLE;
+ } else {
+ t &= ~R128_ALPHA_ENABLE;
+ }
+
+ if ( rmesa->setup.misc_3d_state_cntl_reg != a ) {
+ rmesa->setup.misc_3d_state_cntl_reg = a;
+ rmesa->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS;
+ }
+ if ( rmesa->setup.tex_cntl_c != t ) {
+ rmesa->setup.tex_cntl_c = t;
+ rmesa->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS;
+ }
+}
+
+static void r128DDAlphaFunc( GLcontext *ctx, GLenum func, GLfloat ref )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+ FLUSH_BATCH( rmesa );
+ rmesa->new_state |= R128_NEW_ALPHA;
+}
+
+static void r128DDBlendEquation( GLcontext *ctx, GLenum mode )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+ FLUSH_BATCH( rmesa );
+
+ /* BlendEquation sets ColorLogicOpEnabled in an unexpected
+ * manner.
+ */
+ FALLBACK( R128_CONTEXT(ctx), R128_FALLBACK_LOGICOP,
+ (ctx->Color.ColorLogicOpEnabled &&
+ ctx->Color.LogicOp != GL_COPY));
+
+ /* Can only do blend addition, not min, max, subtract, etc. */
+ FALLBACK( R128_CONTEXT(ctx), R128_FALLBACK_BLEND_EQ,
+ mode != GL_FUNC_ADD_EXT);
+
+ rmesa->new_state |= R128_NEW_ALPHA;
+}
+
+static void r128DDBlendFunc( GLcontext *ctx, GLenum sfactor, GLenum dfactor )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+ FLUSH_BATCH( rmesa );
+ rmesa->new_state |= R128_NEW_ALPHA;
+}
+
+static void r128DDBlendFuncSeparate( GLcontext *ctx,
+ GLenum sfactorRGB, GLenum dfactorRGB,
+ GLenum sfactorA, GLenum dfactorA )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+ FLUSH_BATCH( rmesa );
+ rmesa->new_state |= R128_NEW_ALPHA;
+}
+
+
+/* =============================================================
+ * Depth testing
+ */
+
+static void r128UpdateZMode( GLcontext *ctx )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+ GLuint z = rmesa->setup.z_sten_cntl_c;
+ GLuint t = rmesa->setup.tex_cntl_c;
+
+ if ( ctx->Depth.Test ) {
+ z &= ~R128_Z_TEST_MASK;
+
+ switch ( ctx->Depth.Func ) {
+ case GL_NEVER:
+ z |= R128_Z_TEST_NEVER;
+ break;
+ case GL_ALWAYS:
+ z |= R128_Z_TEST_ALWAYS;
+ break;
+ case GL_LESS:
+ z |= R128_Z_TEST_LESS;
+ break;
+ case GL_LEQUAL:
+ z |= R128_Z_TEST_LESSEQUAL;
+ break;
+ case GL_EQUAL:
+ z |= R128_Z_TEST_EQUAL;
+ break;
+ case GL_GEQUAL:
+ z |= R128_Z_TEST_GREATEREQUAL;
+ break;
+ case GL_GREATER:
+ z |= R128_Z_TEST_GREATER;
+ break;
+ case GL_NOTEQUAL:
+ z |= R128_Z_TEST_NEQUAL;
+ break;
+ }
+
+ t |= R128_Z_ENABLE;
+ } else {
+ t &= ~R128_Z_ENABLE;
+ }
+
+ if ( ctx->Depth.Mask ) {
+ t |= R128_Z_WRITE_ENABLE;
+ } else {
+ t &= ~R128_Z_WRITE_ENABLE;
+ }
+
+ if ( rmesa->setup.z_sten_cntl_c != z ) {
+ rmesa->setup.z_sten_cntl_c = z;
+ rmesa->dirty |= R128_UPLOAD_CONTEXT;
+ }
+ if ( rmesa->setup.tex_cntl_c != t ) {
+ rmesa->setup.tex_cntl_c = t;
+ rmesa->dirty |= R128_UPLOAD_CONTEXT;
+ }
+}
+
+static void r128DDDepthFunc( GLcontext *ctx, GLenum func )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+ FLUSH_BATCH( rmesa );
+ rmesa->new_state |= R128_NEW_DEPTH;
+}
+
+static void r128DDDepthMask( GLcontext *ctx, GLboolean flag )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+ FLUSH_BATCH( rmesa );
+ rmesa->new_state |= R128_NEW_DEPTH;
+}
+
+static void r128DDClearDepth( GLcontext *ctx, GLclampd d )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+ switch ( rmesa->setup.z_sten_cntl_c & R128_Z_PIX_WIDTH_MASK ) {
+ case R128_Z_PIX_WIDTH_16:
+ rmesa->ClearDepth = d * 0x0000ffff;
+ break;
+ case R128_Z_PIX_WIDTH_24:
+ rmesa->ClearDepth = d * 0x00ffffff;
+ break;
+ case R128_Z_PIX_WIDTH_32:
+ rmesa->ClearDepth = d * 0xffffffff;
+ break;
+ }
+}
+
+
+/* =============================================================
+ * Fog
+ */
+
+static void r128UpdateFogAttrib( GLcontext *ctx )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+ GLuint t = rmesa->setup.tex_cntl_c;
+ GLubyte c[4];
+ GLuint col;
+
+ if ( ctx->Fog.Enabled ) {
+ t |= R128_FOG_ENABLE;
+ } else {
+ t &= ~R128_FOG_ENABLE;
+ }
+
+ c[0] = FLOAT_TO_UBYTE( ctx->Fog.Color[0] );
+ c[1] = FLOAT_TO_UBYTE( ctx->Fog.Color[1] );
+ c[2] = FLOAT_TO_UBYTE( ctx->Fog.Color[2] );
+
+ col = r128PackColor( 4, c[0], c[1], c[2], 0 );
+
+ if ( rmesa->setup.fog_color_c != col ) {
+ rmesa->setup.fog_color_c = col;
+ rmesa->dirty |= R128_UPLOAD_CONTEXT;
+ }
+ if ( rmesa->setup.tex_cntl_c != t ) {
+ rmesa->setup.tex_cntl_c = t;
+ rmesa->dirty |= R128_UPLOAD_CONTEXT;
+ }
+}
+
+static void r128DDFogfv( GLcontext *ctx, GLenum pname, const GLfloat *param )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+ FLUSH_BATCH( rmesa );
+ rmesa->new_state |= R128_NEW_FOG;
+}
+
+
+/* =============================================================
+ * Clipping
+ */
+
+static void r128UpdateClipping( GLcontext *ctx )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+ if ( rmesa->driDrawable ) {
+ __DRIdrawablePrivate *drawable = rmesa->driDrawable;
+ int x1 = 0;
+ int y1 = 0;
+ int x2 = drawable->w - 1;
+ int y2 = drawable->h - 1;
+
+ if ( ctx->Scissor.Enabled ) {
+ if ( ctx->Scissor.X > x1 ) {
+ x1 = ctx->Scissor.X;
+ }
+ if ( drawable->h - ctx->Scissor.Y - ctx->Scissor.Height > y1 ) {
+ y1 = drawable->h - ctx->Scissor.Y - ctx->Scissor.Height;
+ }
+ if ( ctx->Scissor.X + ctx->Scissor.Width - 1 < x2 ) {
+ x2 = ctx->Scissor.X + ctx->Scissor.Width - 1;
+ }
+ if ( drawable->h - ctx->Scissor.Y - 1 < y2 ) {
+ y2 = drawable->h - ctx->Scissor.Y - 1;
+ }
+ }
+
+ x1 += drawable->x;
+ y1 += drawable->y;
+ x2 += drawable->x;
+ y2 += drawable->y;
+
+ rmesa->setup.sc_top_left_c = ((y1 << 16) | x1);
+ rmesa->setup.sc_bottom_right_c = ((y2 << 16) | x2);
+
+ rmesa->dirty |= R128_UPLOAD_CONTEXT;
+ }
+}
+
+static void r128DDScissor( GLcontext *ctx,
+ GLint x, GLint y, GLsizei w, GLsizei h )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+ FLUSH_BATCH( rmesa );
+ rmesa->new_state |= R128_NEW_CLIP;
+}
+
+
+/* =============================================================
+ * Culling
+ */
+
+static void r128UpdateCull( GLcontext *ctx )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+ GLuint f = rmesa->setup.pm4_vc_fpu_setup;
+
+ f &= ~R128_FRONT_DIR_MASK;
+
+ switch ( ctx->Polygon.FrontFace ) {
+ case GL_CW:
+ f |= R128_FRONT_DIR_CW;
+ break;
+ case GL_CCW:
+ f |= R128_FRONT_DIR_CCW;
+ break;
+ }
+
+ f |= R128_BACKFACE_SOLID | R128_FRONTFACE_SOLID;
+
+ if ( ctx->Polygon.CullFlag ) {
+ switch ( ctx->Polygon.CullFaceMode ) {
+ case GL_FRONT:
+ f &= ~R128_FRONTFACE_SOLID;
+ break;
+ case GL_BACK:
+ f &= ~R128_BACKFACE_SOLID;
+ break;
+ case GL_FRONT_AND_BACK:
+ f &= ~(R128_BACKFACE_SOLID |
+ R128_FRONTFACE_SOLID);
+ break;
+ }
+ }
+
+ if ( 1 || rmesa->setup.pm4_vc_fpu_setup != f ) {
+ rmesa->setup.pm4_vc_fpu_setup = f;
+ rmesa->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_SETUP;
+ }
+}
+
+static void r128DDCullFace( GLcontext *ctx, GLenum mode )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+ FLUSH_BATCH( rmesa );
+ rmesa->new_state |= R128_NEW_CULL;
+}
+
+static void r128DDFrontFace( GLcontext *ctx, GLenum mode )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+ FLUSH_BATCH( rmesa );
+ rmesa->new_state |= R128_NEW_CULL;
+}
+
+
+/* =============================================================
+ * Masks
+ */
+
+static void r128UpdateMasks( GLcontext *ctx )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+ GLuint mask = r128PackColor( rmesa->r128Screen->cpp,
+ ctx->Color.ColorMask[RCOMP],
+ ctx->Color.ColorMask[GCOMP],
+ ctx->Color.ColorMask[BCOMP],
+ ctx->Color.ColorMask[ACOMP] );
+
+ if ( rmesa->setup.plane_3d_mask_c != mask ) {
+ rmesa->setup.plane_3d_mask_c = mask;
+ rmesa->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS;
+ }
+}
+
+static void r128DDColorMask( GLcontext *ctx,
+ GLboolean r, GLboolean g,
+ GLboolean b, GLboolean a )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+ FLUSH_BATCH( rmesa );
+ rmesa->new_state |= R128_NEW_MASKS;
+}
+
+
+/* =============================================================
+ * 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 )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+ GLuint t = rmesa->setup.tex_cntl_c;
+
+ if ( ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR &&
+ ctx->Light.Enabled) {
+ /* XXX separate specular color just doesn't seem to work as it should.
+ * For now, we fall back to s/w rendering whenever separate specular
+ * is enabled.
+ */
+#if 0
+ if (ctx->Light.ShadeModel == GL_FLAT) {
+ /* R128 can't do flat-shaded separate specular */
+ t &= ~R128_SPEC_LIGHT_ENABLE;
+ FALLBACK( rmesa, R128_FALLBACK_SEP_SPECULAR, GL_TRUE );
+ /*printf("%s fallback sep spec\n", __FUNCTION__);*/
+ }
+ else {
+ t |= R128_SPEC_LIGHT_ENABLE;
+ FALLBACK( rmesa, R128_FALLBACK_SEP_SPECULAR, GL_FALSE );
+ /*printf("%s enable sep spec\n", __FUNCTION__);*/
+ }
+#else
+ t &= ~R128_SPEC_LIGHT_ENABLE;
+ FALLBACK( rmesa, R128_FALLBACK_SEP_SPECULAR, GL_TRUE );
+ /*printf("%s fallback sep spec\n", __FUNCTION__);*/
+#endif
+ }
+ else {
+ t &= ~R128_SPEC_LIGHT_ENABLE;
+ FALLBACK( rmesa, R128_FALLBACK_SEP_SPECULAR, GL_FALSE );
+ /*printf("%s disable sep spec\n", __FUNCTION__);*/
+ }
+
+ if ( rmesa->setup.tex_cntl_c != t ) {
+ rmesa->setup.tex_cntl_c = t;
+ rmesa->dirty |= R128_UPLOAD_CONTEXT;
+ rmesa->dirty |= R128_UPLOAD_SETUP;
+ rmesa->new_state |= R128_NEW_CONTEXT;
+ }
+}
+
+
+static void r128DDLightModelfv( GLcontext *ctx, GLenum pname,
+ const GLfloat *param )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+ if ( pname == GL_LIGHT_MODEL_COLOR_CONTROL ) {
+ FLUSH_BATCH( rmesa );
+ updateSpecularLighting(ctx);
+ }
+}
+
+static void r128DDShadeModel( GLcontext *ctx, GLenum mode )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+ GLuint s = rmesa->setup.pm4_vc_fpu_setup;
+
+ s &= ~R128_FPU_COLOR_MASK;
+
+ switch ( mode ) {
+ case GL_FLAT:
+ s |= R128_FPU_COLOR_FLAT;
+ break;
+ case GL_SMOOTH:
+ s |= R128_FPU_COLOR_GOURAUD;
+ break;
+ default:
+ return;
+ }
+
+ updateSpecularLighting(ctx);
+
+ if ( rmesa->setup.pm4_vc_fpu_setup != s ) {
+ FLUSH_BATCH( rmesa );
+ rmesa->setup.pm4_vc_fpu_setup = s;
+
+ rmesa->new_state |= R128_NEW_CONTEXT;
+ rmesa->dirty |= R128_UPLOAD_SETUP;
+ }
+}
+
+
+/* =============================================================
+ * Window position
+ */
+
+void r128UpdateWindow( GLcontext *ctx )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+ int x = rmesa->driDrawable->x;
+ int y = rmesa->driDrawable->y;
+
+ rmesa->setup.window_xy_offset = ((y << R128_WINDOW_Y_SHIFT) |
+ (x << R128_WINDOW_X_SHIFT));
+
+ rmesa->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_WINDOW;
+}
+
+/* =============================================================
+ * Viewport
+ */
+
+
+static void r128CalcViewport( GLcontext *ctx )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+ const GLfloat *v = ctx->Viewport._WindowMap.m;
+ GLfloat *m = rmesa->hw_viewport;
+
+ /* See also r128_translate_vertex.
+ */
+ m[MAT_SX] = v[MAT_SX];
+ m[MAT_TX] = v[MAT_TX] + SUBPIXEL_X;
+ m[MAT_SY] = - v[MAT_SY];
+ m[MAT_TY] = - v[MAT_TY] + rmesa->driDrawable->h + SUBPIXEL_Y;
+ m[MAT_SZ] = v[MAT_SZ] * rmesa->depth_scale;
+ m[MAT_TZ] = v[MAT_TZ] * rmesa->depth_scale;
+}
+
+static void r128Viewport( GLcontext *ctx,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height )
+{
+ r128CalcViewport( ctx );
+}
+
+static void r128DepthRange( GLcontext *ctx,
+ GLclampd nearval, GLclampd farval )
+{
+ r128CalcViewport( ctx );
+}
+
+
+/* =============================================================
+ * Miscellaneous
+ */
+
+static void r128DDClearColor( GLcontext *ctx,
+ const GLfloat color[4] )
+{
+ r128ContextPtr rmesa = R128_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]);
+
+ rmesa->ClearColor = r128PackColor( rmesa->r128Screen->cpp,
+ c[0], c[1], c[2], c[3] );
+}
+
+static void r128DDLogicOpCode( GLcontext *ctx, GLenum opcode )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+ if ( ctx->Color.ColorLogicOpEnabled ) {
+ FLUSH_BATCH( rmesa );
+
+ FALLBACK( rmesa, R128_FALLBACK_LOGICOP, opcode != GL_COPY );
+ }
+}
+
+static void r128DDDrawBuffer( GLcontext *ctx, GLenum mode )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+ FLUSH_BATCH( rmesa );
+
+ /*
+ * _DrawDestMask is easier to cope with than <mode>.
+ */
+ switch ( ctx->Color._DrawDestMask ) {
+ case FRONT_LEFT_BIT:
+ FALLBACK( rmesa, R128_FALLBACK_DRAW_BUFFER, GL_FALSE );
+ break;
+ case BACK_LEFT_BIT:
+ FALLBACK( rmesa, R128_FALLBACK_DRAW_BUFFER, GL_FALSE );
+ break;
+ default:
+ /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
+ FALLBACK( rmesa, R128_FALLBACK_DRAW_BUFFER, GL_TRUE );
+ break;
+ }
+
+ /* We want to update the s/w rast state too so that r200SetBuffer()
+ * gets called.
+ */
+ _swrast_DrawBuffer(ctx, mode);
+
+ rmesa->setup.dst_pitch_offset_c = (((rmesa->drawPitch/8) << 21) |
+ (rmesa->drawOffset >> 5));
+ rmesa->new_state |= R128_NEW_WINDOW;
+}
+
+static void r128DDReadBuffer( GLcontext *ctx, GLenum mode )
+{
+ /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
+}
+
+
+/* =============================================================
+ * Polygon stipple
+ */
+
+static void r128DDPolygonStipple( GLcontext *ctx, const GLubyte *mask )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+ GLuint stipple[32], i;
+ drmR128Stipple stippleRec;
+
+ for (i = 0; i < 32; i++) {
+ stipple[31 - i] = ((mask[i*4+0] << 24) |
+ (mask[i*4+1] << 16) |
+ (mask[i*4+2] << 8) |
+ (mask[i*4+3]));
+ }
+
+ FLUSH_BATCH( rmesa );
+ LOCK_HARDWARE( rmesa );
+
+ stippleRec.mask = stipple;
+ drmCommandWrite( rmesa->driFd, DRM_R128_STIPPLE,
+ &stippleRec, sizeof(drmR128Stipple) );
+
+ UNLOCK_HARDWARE( rmesa );
+
+ rmesa->new_state |= R128_NEW_CONTEXT;
+ rmesa->dirty |= R128_UPLOAD_CONTEXT;
+}
+
+
+/* =============================================================
+ * Render mode
+ */
+
+static void r128DDRenderMode( GLcontext *ctx, GLenum mode )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+ FALLBACK( rmesa, R128_FALLBACK_RENDER_MODE, (mode != GL_RENDER) );
+}
+
+
+
+/* =============================================================
+ * State enable/disable
+ */
+
+static void r128DDEnable( GLcontext *ctx, GLenum cap, GLboolean state )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+ if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
+ fprintf( stderr, "%s( %s = %s )\n",
+ __FUNCTION__, _mesa_lookup_enum_by_nr( cap ),
+ state ? "GL_TRUE" : "GL_FALSE" );
+ }
+
+ switch ( cap ) {
+ case GL_ALPHA_TEST:
+ FLUSH_BATCH( rmesa );
+ rmesa->new_state |= R128_NEW_ALPHA;
+ break;
+
+ case GL_BLEND:
+ FLUSH_BATCH( rmesa );
+ rmesa->new_state |= R128_NEW_ALPHA;
+
+ /* For some reason enable(GL_BLEND) affects ColorLogicOpEnabled.
+ */
+ FALLBACK( rmesa, R128_FALLBACK_LOGICOP,
+ (ctx->Color.ColorLogicOpEnabled &&
+ ctx->Color.LogicOp != GL_COPY));
+ break;
+
+ case GL_CULL_FACE:
+ FLUSH_BATCH( rmesa );
+ rmesa->new_state |= R128_NEW_CULL;
+ break;
+
+ case GL_DEPTH_TEST:
+ FLUSH_BATCH( rmesa );
+ rmesa->new_state |= R128_NEW_DEPTH;
+ break;
+
+ case GL_DITHER:
+ do {
+ GLuint t = rmesa->setup.tex_cntl_c;
+ FLUSH_BATCH( rmesa );
+
+ if ( ctx->Color.DitherFlag ) {
+ t |= R128_DITHER_ENABLE;
+ } else {
+ t &= ~R128_DITHER_ENABLE;
+ }
+
+ if ( rmesa->setup.tex_cntl_c != t ) {
+ rmesa->setup.tex_cntl_c = t;
+ rmesa->dirty |= R128_UPLOAD_CONTEXT;
+ }
+ } while (0);
+ break;
+
+ case GL_FOG:
+ FLUSH_BATCH( rmesa );
+ rmesa->new_state |= R128_NEW_FOG;
+ break;
+
+ case GL_COLOR_LOGIC_OP:
+ FLUSH_BATCH( rmesa );
+ FALLBACK( rmesa, R128_FALLBACK_LOGICOP,
+ state && ctx->Color.LogicOp != GL_COPY );
+ break;
+
+ case GL_LIGHTING:
+ updateSpecularLighting(ctx);
+ break;
+
+ case GL_SCISSOR_TEST:
+ FLUSH_BATCH( rmesa );
+ rmesa->scissor = state;
+ rmesa->new_state |= R128_NEW_CLIP;
+ break;
+
+ case GL_STENCIL_TEST:
+ FLUSH_BATCH( rmesa );
+ FALLBACK( rmesa, R128_FALLBACK_STENCIL, state );
+ break;
+
+ case GL_TEXTURE_1D:
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_3D:
+ FLUSH_BATCH( rmesa );
+ break;
+
+ case GL_POLYGON_STIPPLE:
+ if ( rmesa->render_primitive == GL_TRIANGLES ) {
+ FLUSH_BATCH( rmesa );
+ rmesa->setup.dp_gui_master_cntl_c &= ~R128_GMC_BRUSH_NONE;
+ if ( state ) {
+ rmesa->setup.dp_gui_master_cntl_c |=
+ R128_GMC_BRUSH_32x32_MONO_FG_LA;
+ } else {
+ rmesa->setup.dp_gui_master_cntl_c |=
+ R128_GMC_BRUSH_SOLID_COLOR;
+ }
+ rmesa->new_state |= R128_NEW_CONTEXT;
+ rmesa->dirty |= R128_UPLOAD_CONTEXT;
+ }
+ break;
+
+ default:
+ return;
+ }
+}
+
+
+/* =============================================================
+ * State initialization, management
+ */
+
+static void r128DDPrintDirty( const char *msg, GLuint state )
+{
+ fprintf( stderr,
+ "%s: (0x%x) %s%s%s%s%s%s%s%s%s\n",
+ msg,
+ state,
+ (state & R128_UPLOAD_CORE) ? "core, " : "",
+ (state & R128_UPLOAD_CONTEXT) ? "context, " : "",
+ (state & R128_UPLOAD_SETUP) ? "setup, " : "",
+ (state & R128_UPLOAD_TEX0) ? "tex0, " : "",
+ (state & R128_UPLOAD_TEX1) ? "tex1, " : "",
+ (state & R128_UPLOAD_MASKS) ? "masks, " : "",
+ (state & R128_UPLOAD_WINDOW) ? "window, " : "",
+ (state & R128_UPLOAD_CLIPRECTS) ? "cliprects, " : "",
+ (state & R128_REQUIRE_QUIESCENCE) ? "quiescence, " : "" );
+}
+
+/*
+ * Load the current context's state into the hardware.
+ *
+ * NOTE: Be VERY careful about ensuring the context state is marked for
+ * upload, the only place it shouldn't be uploaded is when the setup
+ * state has changed in ReducedPrimitiveChange as this comes right after
+ * a state update.
+ *
+ * Blits of any type should always upload the context and masks after
+ * they are done.
+ */
+void r128EmitHwStateLocked( r128ContextPtr rmesa )
+{
+ R128SAREAPrivPtr sarea = rmesa->sarea;
+ r128_context_regs_t *regs = &(rmesa->setup);
+ const r128TexObjPtr t0 = rmesa->CurrentTexObj[0];
+ const r128TexObjPtr t1 = rmesa->CurrentTexObj[1];
+
+ if ( R128_DEBUG & DEBUG_VERBOSE_MSG ) {
+ r128DDPrintDirty( "r128EmitHwStateLocked", rmesa->dirty );
+ }
+
+ if ( rmesa->dirty & (R128_UPLOAD_CONTEXT |
+ R128_UPLOAD_SETUP |
+ R128_UPLOAD_MASKS |
+ R128_UPLOAD_WINDOW |
+ R128_UPLOAD_CORE) ) {
+ memcpy( &sarea->ContextState, regs, sizeof(sarea->ContextState) );
+ }
+
+ if ( (rmesa->dirty & R128_UPLOAD_TEX0) && t0 ) {
+ r128_texture_regs_t *tex = &sarea->TexState[0];
+
+ tex->tex_cntl = t0->setup.tex_cntl;
+ tex->tex_combine_cntl = rmesa->tex_combine[0];
+ tex->tex_size_pitch = t0->setup.tex_size_pitch;
+ memcpy( &tex->tex_offset[0], &t0->setup.tex_offset[0],
+ sizeof(tex->tex_offset ) );
+ tex->tex_border_color = t0->setup.tex_border_color;
+ }
+
+ if ( (rmesa->dirty & R128_UPLOAD_TEX1) && t1 ) {
+ r128_texture_regs_t *tex = &sarea->TexState[1];
+
+ tex->tex_cntl = t1->setup.tex_cntl;
+ tex->tex_combine_cntl = rmesa->tex_combine[1];
+ tex->tex_size_pitch = t1->setup.tex_size_pitch;
+ memcpy( &tex->tex_offset[0], &t1->setup.tex_offset[0],
+ sizeof(tex->tex_offset ) );
+ tex->tex_border_color = t1->setup.tex_border_color;
+ }
+
+ sarea->vertsize = rmesa->vertex_size;
+ sarea->vc_format = rmesa->vertex_format;
+
+ /* Turn off the texture cache flushing */
+ rmesa->setup.tex_cntl_c &= ~R128_TEX_CACHE_FLUSH;
+
+ sarea->dirty |= rmesa->dirty;
+ rmesa->dirty &= R128_UPLOAD_CLIPRECTS;
+}
+
+static void r128DDPrintState( const char *msg, GLuint flags )
+{
+ fprintf( stderr,
+ "%s: (0x%x) %s%s%s%s%s%s%s%s\n",
+ msg,
+ flags,
+ (flags & R128_NEW_CONTEXT) ? "context, " : "",
+ (flags & R128_NEW_ALPHA) ? "alpha, " : "",
+ (flags & R128_NEW_DEPTH) ? "depth, " : "",
+ (flags & R128_NEW_FOG) ? "fog, " : "",
+ (flags & R128_NEW_CLIP) ? "clip, " : "",
+ (flags & R128_NEW_CULL) ? "cull, " : "",
+ (flags & R128_NEW_MASKS) ? "masks, " : "",
+ (flags & R128_NEW_WINDOW) ? "window, " : "" );
+}
+
+void r128DDUpdateHWState( GLcontext *ctx )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+ int new_state = rmesa->new_state;
+
+ if ( new_state || rmesa->NewGLState & _NEW_TEXTURE )
+ {
+ FLUSH_BATCH( rmesa );
+
+ rmesa->new_state = 0;
+
+ if ( R128_DEBUG & DEBUG_VERBOSE_MSG )
+ r128DDPrintState( "r128UpdateHwState", new_state );
+
+ /* Update the various parts of the context's state.
+ */
+ if ( new_state & R128_NEW_ALPHA )
+ r128UpdateAlphaMode( ctx );
+
+ if ( new_state & R128_NEW_DEPTH )
+ r128UpdateZMode( ctx );
+
+ if ( new_state & R128_NEW_FOG )
+ r128UpdateFogAttrib( ctx );
+
+ if ( new_state & R128_NEW_CLIP )
+ r128UpdateClipping( ctx );
+
+ if ( new_state & R128_NEW_CULL )
+ r128UpdateCull( ctx );
+
+ if ( new_state & R128_NEW_MASKS )
+ r128UpdateMasks( ctx );
+
+ if ( new_state & R128_NEW_WINDOW )
+ r128UpdateWindow( ctx );
+
+ if ( rmesa->NewGLState & _NEW_TEXTURE ) {
+ r128UpdateTextureState( ctx );
+ }
+ }
+}
+
+
+static void r128DDInvalidateState( GLcontext *ctx, GLuint new_state )
+{
+ _swrast_InvalidateState( ctx, new_state );
+ _swsetup_InvalidateState( ctx, new_state );
+ _ac_InvalidateState( ctx, new_state );
+ _tnl_InvalidateState( ctx, new_state );
+ R128_CONTEXT(ctx)->NewGLState |= new_state;
+}
+
+
+
+/* Initialize the context's hardware state.
+ */
+void r128DDInitState( r128ContextPtr rmesa )
+{
+ int dst_bpp, depth_bpp;
+
+ switch ( rmesa->r128Screen->cpp ) {
+ case 2:
+ dst_bpp = R128_GMC_DST_16BPP;
+ break;
+ case 4:
+ dst_bpp = R128_GMC_DST_32BPP;
+ break;
+ default:
+ fprintf( stderr, "Error: Unsupported pixel depth... exiting\n" );
+ exit( -1 );
+ }
+
+ rmesa->ClearColor = 0x00000000;
+
+ switch ( rmesa->glCtx->Visual.depthBits ) {
+ case 16:
+ rmesa->ClearDepth = 0x0000ffff;
+ depth_bpp = R128_Z_PIX_WIDTH_16;
+ rmesa->depth_scale = 1.0 / (GLfloat)0xffff;
+ break;
+ case 24:
+ rmesa->ClearDepth = 0x00ffffff;
+ depth_bpp = R128_Z_PIX_WIDTH_24;
+ rmesa->depth_scale = 1.0 / (GLfloat)0xffffff;
+ break;
+ default:
+ fprintf( stderr, "Error: Unsupported depth %d... exiting\n",
+ rmesa->glCtx->Visual.depthBits );
+ exit( -1 );
+ }
+
+ rmesa->Fallback = 0;
+
+ if ( rmesa->glCtx->Visual.doubleBufferMode && rmesa->sarea->pfCurrentPage == 0 ) {
+ rmesa->drawOffset = rmesa->readOffset = rmesa->r128Screen->backOffset;
+ rmesa->drawPitch = rmesa->readPitch = rmesa->r128Screen->backPitch;
+ } else {
+ rmesa->drawOffset = rmesa->readOffset = rmesa->r128Screen->frontOffset;
+ rmesa->drawPitch = rmesa->readPitch = rmesa->r128Screen->frontPitch;
+ }
+
+ /* Harware state:
+ */
+ rmesa->setup.dst_pitch_offset_c = (((rmesa->drawPitch/8) << 21) |
+ (rmesa->drawOffset >> 5));
+
+ rmesa->setup.dp_gui_master_cntl_c = (R128_GMC_DST_PITCH_OFFSET_CNTL |
+ R128_GMC_DST_CLIPPING |
+ R128_GMC_BRUSH_SOLID_COLOR |
+ dst_bpp |
+ R128_GMC_SRC_DATATYPE_COLOR |
+ R128_GMC_BYTE_MSB_TO_LSB |
+ R128_GMC_CONVERSION_TEMP_6500 |
+ R128_ROP3_S |
+ R128_DP_SRC_SOURCE_MEMORY |
+ R128_GMC_3D_FCN_EN |
+ R128_GMC_CLR_CMP_CNTL_DIS |
+ R128_GMC_AUX_CLIP_DIS |
+ R128_GMC_WR_MSK_DIS);
+
+ rmesa->setup.sc_top_left_c = 0x00000000;
+ rmesa->setup.sc_bottom_right_c = 0x1fff1fff;
+
+ rmesa->setup.z_offset_c = rmesa->r128Screen->depthOffset;
+ rmesa->setup.z_pitch_c = ((rmesa->r128Screen->depthPitch >> 3) |
+ R128_Z_TILE);
+
+ rmesa->setup.z_sten_cntl_c = (depth_bpp |
+ R128_Z_TEST_LESS |
+ R128_STENCIL_TEST_ALWAYS |
+ R128_STENCIL_S_FAIL_KEEP |
+ R128_STENCIL_ZPASS_KEEP |
+ R128_STENCIL_ZFAIL_KEEP);
+
+ rmesa->setup.tex_cntl_c = (R128_Z_WRITE_ENABLE |
+ R128_SHADE_ENABLE |
+ R128_DITHER_ENABLE |
+ R128_ALPHA_IN_TEX_COMPLETE_A |
+ R128_LIGHT_DIS |
+ R128_ALPHA_LIGHT_DIS |
+ R128_TEX_CACHE_FLUSH |
+ (0x3f << R128_LOD_BIAS_SHIFT));
+
+ rmesa->setup.misc_3d_state_cntl_reg = (R128_MISC_SCALE_3D_TEXMAP_SHADE |
+ R128_MISC_SCALE_PIX_REPLICATE |
+ R128_ALPHA_COMB_ADD_CLAMP |
+ R128_FOG_VERTEX |
+ R128_ALPHA_BLEND_SRC_ONE |
+ R128_ALPHA_BLEND_DST_ZERO |
+ R128_ALPHA_TEST_ALWAYS);
+
+ rmesa->setup.texture_clr_cmp_clr_c = 0x00000000;
+ rmesa->setup.texture_clr_cmp_msk_c = 0xffffffff;
+
+ rmesa->setup.fog_color_c = 0x00000000;
+
+ rmesa->setup.pm4_vc_fpu_setup = (R128_FRONT_DIR_CCW |
+ R128_BACKFACE_SOLID |
+ R128_FRONTFACE_SOLID |
+ R128_FPU_COLOR_GOURAUD |
+ R128_FPU_SUB_PIX_4BITS |
+ R128_FPU_MODE_3D |
+ R128_TRAP_BITS_DISABLE |
+ R128_XFACTOR_2 |
+ R128_YFACTOR_2 |
+ R128_FLAT_SHADE_VERTEX_OGL |
+ R128_FPU_ROUND_TRUNCATE |
+ R128_WM_SEL_8DW);
+
+ rmesa->setup.setup_cntl = (R128_COLOR_GOURAUD |
+ R128_PRIM_TYPE_TRI |
+ R128_TEXTURE_ST_MULT_W |
+ R128_STARTING_VERTEX_1 |
+ R128_ENDING_VERTEX_3 |
+ R128_SU_POLY_LINE_NOT_LAST |
+ R128_SUB_PIX_4BITS);
+
+ rmesa->setup.tex_size_pitch_c = 0x00000000;
+ rmesa->setup.constant_color_c = 0x00ffffff;
+
+ rmesa->setup.dp_write_mask = 0xffffffff;
+ rmesa->setup.sten_ref_mask_c = 0xffff0000;
+ rmesa->setup.plane_3d_mask_c = 0xffffffff;
+
+ rmesa->setup.window_xy_offset = 0x00000000;
+
+ rmesa->setup.scale_3d_cntl = (R128_SCALE_DITHER_TABLE |
+ R128_TEX_CACHE_SIZE_FULL |
+ R128_DITHER_INIT_RESET |
+ R128_SCALE_3D_TEXMAP_SHADE |
+ R128_SCALE_PIX_REPLICATE |
+ R128_ALPHA_COMB_ADD_CLAMP |
+ R128_FOG_VERTEX |
+ R128_ALPHA_BLEND_SRC_ONE |
+ R128_ALPHA_BLEND_DST_ZERO |
+ R128_ALPHA_TEST_ALWAYS |
+ R128_COMPOSITE_SHADOW_CMP_EQUAL |
+ R128_TEX_MAP_ALPHA_IN_TEXTURE |
+ R128_TEX_CACHE_LINE_SIZE_4QW);
+
+ rmesa->new_state = R128_NEW_ALL;
+}
+
+/* Initialize the driver's state functions.
+ */
+void r128DDInitStateFuncs( GLcontext *ctx )
+{
+ ctx->Driver.UpdateState = r128DDInvalidateState;
+
+ ctx->Driver.ClearIndex = NULL;
+ ctx->Driver.ClearColor = r128DDClearColor;
+ ctx->Driver.DrawBuffer = r128DDDrawBuffer;
+ ctx->Driver.ReadBuffer = r128DDReadBuffer;
+
+ ctx->Driver.IndexMask = NULL;
+ ctx->Driver.ColorMask = r128DDColorMask;
+ ctx->Driver.AlphaFunc = r128DDAlphaFunc;
+ ctx->Driver.BlendEquation = r128DDBlendEquation;
+ ctx->Driver.BlendFunc = r128DDBlendFunc;
+ ctx->Driver.BlendFuncSeparate = r128DDBlendFuncSeparate;
+ ctx->Driver.ClearDepth = r128DDClearDepth;
+ ctx->Driver.CullFace = r128DDCullFace;
+ ctx->Driver.FrontFace = r128DDFrontFace;
+ ctx->Driver.DepthFunc = r128DDDepthFunc;
+ ctx->Driver.DepthMask = r128DDDepthMask;
+ ctx->Driver.Enable = r128DDEnable;
+ ctx->Driver.Fogfv = r128DDFogfv;
+ ctx->Driver.Hint = NULL;
+ ctx->Driver.Lightfv = NULL;
+ ctx->Driver.LightModelfv = r128DDLightModelfv;
+ ctx->Driver.LogicOpcode = r128DDLogicOpCode;
+ ctx->Driver.PolygonMode = NULL;
+ ctx->Driver.PolygonStipple = r128DDPolygonStipple;
+ ctx->Driver.RenderMode = r128DDRenderMode;
+ ctx->Driver.Scissor = r128DDScissor;
+ ctx->Driver.ShadeModel = r128DDShadeModel;
+ ctx->Driver.ClearStencil = NULL;
+ ctx->Driver.StencilFunc = NULL;
+ ctx->Driver.StencilMask = NULL;
+ ctx->Driver.StencilOp = NULL;
+
+ ctx->Driver.DepthRange = r128DepthRange;
+ ctx->Driver.Viewport = r128Viewport;
+
+ /* Pixel path fallbacks.
+ */
+ ctx->Driver.Accum = _swrast_Accum;
+ ctx->Driver.Bitmap = _swrast_Bitmap;
+ ctx->Driver.CopyPixels = _swrast_CopyPixels;
+ ctx->Driver.DrawPixels = _swrast_DrawPixels;
+ ctx->Driver.ReadPixels = _swrast_ReadPixels;
+
+ /* Swrast hooks for imaging extensions:
+ */
+ ctx->Driver.CopyColorTable = _swrast_CopyColorTable;
+ ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable;
+ ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
+ ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
+}
diff --git a/src/mesa/drivers/dri/r128/r128_state.h b/src/mesa/drivers/dri/r128/r128_state.h
new file mode 100644
index 0000000000..c51ac23942
--- /dev/null
+++ b/src/mesa/drivers/dri/r128/r128_state.h
@@ -0,0 +1,54 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_state.h,v 1.3 2001/01/08 01:07:21 martin Exp $ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+ Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+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, PRECISION INSIGHT 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:
+ * Gareth Hughes <gareth@valinux.com>
+ * Kevin E. Martin <martin@valinux.com>
+ *
+ */
+
+#ifndef __R128_STATE_H__
+#define __R128_STATE_H__
+
+#ifdef GLX_DIRECT_RENDERING
+
+#include "r128_context.h"
+
+extern void r128DDInitState( r128ContextPtr rmesa );
+extern void r128DDInitStateFuncs( GLcontext *ctx );
+
+extern void r128DDUpdateState( GLcontext *ctx );
+extern void r128DDUpdateHWState( GLcontext *ctx );
+
+extern void r128UpdateWindow( GLcontext *ctx );
+
+extern void r128EmitHwStateLocked( r128ContextPtr rmesa );
+
+#endif
+#endif
diff --git a/src/mesa/drivers/dri/r128/r128_tex.c b/src/mesa/drivers/dri/r128/r128_tex.c
new file mode 100644
index 0000000000..2793a793a0
--- /dev/null
+++ b/src/mesa/drivers/dri/r128/r128_tex.c
@@ -0,0 +1,598 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_tex.c,v 1.14 2002/11/05 17:46:08 tsi Exp $ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+ Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+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, PRECISION INSIGHT 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:
+ * Gareth Hughes <gareth@valinux.com>
+ * Kevin E. Martin <martin@valinux.com>
+ * Brian Paul <brianp@valinux.com>
+ */
+
+#include "r128_context.h"
+#include "r128_state.h"
+#include "r128_ioctl.h"
+#include "r128_vb.h"
+#include "r128_tris.h"
+#include "r128_tex.h"
+#include "r128_texobj.h"
+
+#include "context.h"
+#include "macros.h"
+#include "simple_list.h"
+#include "enums.h"
+#include "texstore.h"
+#include "texformat.h"
+#include "teximage.h"
+#include "imports.h"
+#include "colormac.h"
+
+#define TEX_0 1
+#define TEX_1 2
+
+
+static void r128SetTexWrap( r128TexObjPtr t, GLenum swrap, GLenum twrap )
+{
+ t->setup.tex_cntl &= ~(R128_TEX_CLAMP_S_MASK | R128_TEX_CLAMP_T_MASK);
+
+ switch ( swrap ) {
+ case GL_CLAMP:
+ t->setup.tex_cntl |= R128_TEX_CLAMP_S_BORDER_COLOR;
+ break;
+ case GL_CLAMP_TO_EDGE:
+ t->setup.tex_cntl |= R128_TEX_CLAMP_S_CLAMP;
+ break;
+ case GL_REPEAT:
+ t->setup.tex_cntl |= R128_TEX_CLAMP_S_WRAP;
+ break;
+ case GL_CLAMP_TO_BORDER:
+ t->setup.tex_cntl |= R128_TEX_CLAMP_S_BORDER_COLOR;
+ break;
+ case GL_MIRRORED_REPEAT:
+ t->setup.tex_cntl |= R128_TEX_CLAMP_S_MIRROR;
+ break;
+ }
+
+ switch ( twrap ) {
+ case GL_CLAMP:
+ t->setup.tex_cntl |= R128_TEX_CLAMP_T_BORDER_COLOR;
+ break;
+ case GL_CLAMP_TO_EDGE:
+ t->setup.tex_cntl |= R128_TEX_CLAMP_T_CLAMP;
+ break;
+ case GL_REPEAT:
+ t->setup.tex_cntl |= R128_TEX_CLAMP_T_WRAP;
+ break;
+ case GL_CLAMP_TO_BORDER:
+ t->setup.tex_cntl |= R128_TEX_CLAMP_T_BORDER_COLOR;
+ break;
+ case GL_MIRRORED_REPEAT:
+ t->setup.tex_cntl |= R128_TEX_CLAMP_T_MIRROR;
+ break;
+ }
+}
+
+static void r128SetTexFilter( r128TexObjPtr t, GLenum minf, GLenum magf )
+{
+ t->setup.tex_cntl &= ~(R128_MIN_BLEND_MASK | R128_MAG_BLEND_MASK);
+
+ switch ( minf ) {
+ case GL_NEAREST:
+ t->setup.tex_cntl |= R128_MIN_BLEND_NEAREST;
+ break;
+ case GL_LINEAR:
+ t->setup.tex_cntl |= R128_MIN_BLEND_LINEAR;
+ break;
+ case GL_NEAREST_MIPMAP_NEAREST:
+ t->setup.tex_cntl |= R128_MIN_BLEND_MIPNEAREST;
+ break;
+ case GL_LINEAR_MIPMAP_NEAREST:
+ t->setup.tex_cntl |= R128_MIN_BLEND_MIPLINEAR;
+ break;
+ case GL_NEAREST_MIPMAP_LINEAR:
+ t->setup.tex_cntl |= R128_MIN_BLEND_LINEARMIPNEAREST;
+ break;
+ case GL_LINEAR_MIPMAP_LINEAR:
+ t->setup.tex_cntl |= R128_MIN_BLEND_LINEARMIPLINEAR;
+ break;
+ }
+
+ switch ( magf ) {
+ case GL_NEAREST:
+ t->setup.tex_cntl |= R128_MAG_BLEND_NEAREST;
+ break;
+ case GL_LINEAR:
+ t->setup.tex_cntl |= R128_MAG_BLEND_LINEAR;
+ break;
+ }
+}
+
+static void r128SetTexBorderColor( r128TexObjPtr t, GLubyte c[4] )
+{
+ t->setup.tex_border_color = r128PackColor( 4, c[0], c[1], c[2], c[3] );
+}
+
+
+static r128TexObjPtr r128AllocTexObj( struct gl_texture_object *texObj )
+{
+ r128TexObjPtr t;
+
+ if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
+ fprintf( stderr, "%s( %p )\n", __FUNCTION__, texObj );
+ }
+
+ t = (r128TexObjPtr) CALLOC_STRUCT( r128_tex_obj );
+ texObj->DriverData = t;
+ if ( t != NULL ) {
+
+ /* Initialize non-image-dependent parts of the state:
+ */
+ t->base.tObj = texObj;
+
+ /* FIXME Something here to set initial values for other parts of
+ * FIXME t->setup?
+ */
+
+ make_empty_list( (driTextureObject *) t );
+
+ r128SetTexWrap( t, texObj->WrapS, texObj->WrapT );
+ r128SetTexFilter( t, texObj->MinFilter, texObj->MagFilter );
+ r128SetTexBorderColor( t, texObj->_BorderChan );
+ }
+
+ return t;
+}
+
+
+/* Called by the _mesa_store_teximage[123]d() functions. */
+static const struct gl_texture_format *
+r128ChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
+ GLenum format, GLenum type )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+ (void) format;
+ (void) type;
+
+ switch ( internalFormat ) {
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ case GL_COMPRESSED_ALPHA:
+ 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:
+ case 4:
+ case GL_RGBA:
+ case GL_COMPRESSED_RGBA:
+ case GL_RGBA2:
+ case GL_RGB5_A1:
+ case GL_RGBA8:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ if (rmesa->r128Screen->cpp == 4)
+ return &_mesa_texformat_argb8888;
+ else
+ return &_mesa_texformat_argb4444;
+ case GL_RGBA4:
+ return &_mesa_texformat_argb4444;
+
+ case 3:
+ case GL_RGB:
+ case GL_COMPRESSED_RGB:
+ case GL_R3_G3_B2:
+ case GL_RGB4:
+ case GL_RGB5:
+ case GL_RGB8:
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ if (rmesa->r128Screen->cpp == 4)
+ return &_mesa_texformat_argb8888;
+ else
+ return &_mesa_texformat_rgb565;
+
+ case 1:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ case GL_COMPRESSED_LUMINANCE:
+ if (rmesa->r128Screen->cpp == 4)
+ return &_mesa_texformat_argb8888; /* inefficient but accurate */
+ else
+ return &_mesa_texformat_rgb565;
+
+ case GL_INTENSITY4:
+ return &_mesa_texformat_argb4444;
+ case GL_INTENSITY:
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ case GL_COMPRESSED_INTENSITY:
+ if (rmesa->r128Screen->cpp == 4)
+ return &_mesa_texformat_argb8888; /* inefficient but accurate */
+ else
+ return &_mesa_texformat_argb4444;
+
+ case GL_COLOR_INDEX:
+ case GL_COLOR_INDEX1_EXT:
+ case GL_COLOR_INDEX2_EXT:
+ case GL_COLOR_INDEX4_EXT:
+ case GL_COLOR_INDEX8_EXT:
+ case GL_COLOR_INDEX12_EXT:
+ case GL_COLOR_INDEX16_EXT:
+ return &_mesa_texformat_ci8;
+
+ case GL_YCBCR_MESA:
+ if (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
+ type == GL_UNSIGNED_BYTE)
+ return &_mesa_texformat_ycbcr;
+ else
+ return &_mesa_texformat_ycbcr_rev;
+
+ default:
+ _mesa_problem( ctx, "unexpected format in %s", __FUNCTION__ );
+ return NULL;
+ }
+}
+
+
+static void r128TexImage1D( GLcontext *ctx, GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint border,
+ GLenum format, GLenum type, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage )
+{
+ driTextureObject * t = (driTextureObject *) texObj->DriverData;
+
+ if ( t ) {
+ driSwapOutTextureObject( t );
+ }
+ else {
+ t = (driTextureObject *) r128AllocTexObj(texObj);
+ if (!t) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
+ return;
+ }
+ }
+
+ /* Note, this will call r128ChooseTextureFormat */
+ _mesa_store_teximage1d( ctx, target, level, internalFormat,
+ width, border, format, type,
+ pixels, packing, texObj, texImage );
+
+ t->dirty_images[0] |= (1 << level);
+}
+
+
+static void r128TexSubImage1D( GLcontext *ctx,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLsizei width,
+ GLenum format, GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage )
+{
+ driTextureObject * t = (driTextureObject *) texObj->DriverData;
+
+ assert( t ); /* this _should_ be true */
+ if ( t ) {
+ driSwapOutTextureObject( t );
+ }
+ else {
+ t = (driTextureObject *) r128AllocTexObj(texObj);
+ if (!t) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
+ return;
+ }
+ }
+
+ _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
+ format, type, pixels, packing, texObj,
+ texImage);
+
+ t->dirty_images[0] |= (1 << level);
+}
+
+
+static void r128TexImage2D( 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 ) {
+ driSwapOutTextureObject( (driTextureObject *) t );
+ }
+ else {
+ t = (driTextureObject *) r128AllocTexObj(texObj);
+ if (!t) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
+ return;
+ }
+ }
+
+ /* Note, this will call r128ChooseTextureFormat */
+ _mesa_store_teximage2d(ctx, target, level, internalFormat,
+ width, height, border, format, type, pixels,
+ &ctx->Unpack, texObj, texImage);
+
+ t->dirty_images[0] |= (1 << level);
+}
+
+
+static void r128TexSubImage2D( 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 ) {
+ driSwapOutTextureObject( t );
+ }
+ else {
+ t = (driTextureObject *) r128AllocTexObj(texObj);
+ if (!t) {
+ _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);
+ t->dirty_images[0] |= (1 << level);
+}
+
+
+static void r128DDTexEnv( GLcontext *ctx, GLenum target,
+ GLenum pname, const GLfloat *param )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+ struct gl_texture_unit *texUnit;
+ GLubyte c[4];
+
+ if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
+ fprintf( stderr, "%s( %s )\n",
+ __FUNCTION__, _mesa_lookup_enum_by_nr( pname ) );
+ }
+
+ switch ( pname ) {
+ case GL_TEXTURE_ENV_MODE:
+ FLUSH_BATCH( rmesa );
+ rmesa->new_state |= R128_NEW_ALPHA;
+ break;
+
+ case GL_TEXTURE_ENV_COLOR:
+ texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ CLAMPED_FLOAT_TO_UBYTE( c[0], texUnit->EnvColor[0] );
+ CLAMPED_FLOAT_TO_UBYTE( c[1], texUnit->EnvColor[1] );
+ CLAMPED_FLOAT_TO_UBYTE( c[2], texUnit->EnvColor[2] );
+ CLAMPED_FLOAT_TO_UBYTE( c[3], texUnit->EnvColor[3] );
+ rmesa->env_color = r128PackColor( 4, c[0], c[1], c[2], c[3] );
+ if ( rmesa->setup.constant_color_c != rmesa->env_color ) {
+ FLUSH_BATCH( rmesa );
+ rmesa->setup.constant_color_c = rmesa->env_color;
+
+ /* More complex multitexture/multipass fallbacks for GL_BLEND
+ * can be done later, but this allows a single pass GL_BLEND
+ * in some cases (ie. Performer town demo). This is only
+ * applicable to the regular Rage 128, as the Pro and M3 can
+ * handle true single-pass GL_BLEND texturing.
+ */
+ rmesa->blend_flags &= ~R128_BLEND_ENV_COLOR;
+ if ( R128_IS_PLAIN( rmesa ) &&
+ rmesa->env_color != 0x00000000 &&
+ rmesa->env_color != 0xff000000 &&
+ rmesa->env_color != 0x00ffffff &&
+ rmesa->env_color != 0xffffffff ) {
+ rmesa->blend_flags |= R128_BLEND_ENV_COLOR;
+ }
+ }
+ break;
+
+ case GL_TEXTURE_LOD_BIAS_EXT:
+ do {
+ CARD32 t = rmesa->setup.tex_cntl_c;
+ GLint bias;
+ CARD32 b;
+
+ /* GTH: This isn't exactly correct, but gives good results up to a
+ * certain point. It is better than completely ignoring the LOD
+ * bias. Unfortunately there isn't much range in the bias, the
+ * spec mentions strides that vary between 0.5 and 2.0 but these
+ * numbers don't seem to relate the the GL LOD bias value at all.
+ */
+ if ( param[0] >= 1.0 ) {
+ bias = -128;
+ } else if ( param[0] >= 0.5 ) {
+ bias = -64;
+ } else if ( param[0] >= 0.25 ) {
+ bias = 0;
+ } else if ( param[0] >= 0.0 ) {
+ bias = 63;
+ } else {
+ bias = 127;
+ }
+
+ b = (CARD32)bias & 0xff;
+ t &= ~R128_LOD_BIAS_MASK;
+ t |= (b << R128_LOD_BIAS_SHIFT);
+
+ if ( rmesa->setup.tex_cntl_c != t ) {
+ FLUSH_BATCH( rmesa );
+ rmesa->setup.tex_cntl_c = t;
+ rmesa->dirty |= R128_UPLOAD_CONTEXT;
+ }
+ } while (0);
+ break;
+
+ default:
+ return;
+ }
+}
+
+
+static void r128DDTexParameter( GLcontext *ctx, GLenum target,
+ struct gl_texture_object *tObj,
+ GLenum pname, const GLfloat *params )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+ r128TexObjPtr t = (r128TexObjPtr)tObj->DriverData;
+
+ if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
+ fprintf( stderr, "%s( %s )\n",
+ __FUNCTION__, _mesa_lookup_enum_by_nr( pname ) );
+ }
+
+ if ( ( target != GL_TEXTURE_2D ) && ( target != GL_TEXTURE_1D ) )
+ return;
+
+ switch ( pname ) {
+ case GL_TEXTURE_MIN_FILTER:
+ case GL_TEXTURE_MAG_FILTER:
+ if ( t->base.bound ) FLUSH_BATCH( rmesa );
+ r128SetTexFilter( t, tObj->MinFilter, tObj->MagFilter );
+ break;
+
+ case GL_TEXTURE_WRAP_S:
+ case GL_TEXTURE_WRAP_T:
+ if ( t->base.bound ) FLUSH_BATCH( rmesa );
+ r128SetTexWrap( t, tObj->WrapS, tObj->WrapT );
+ break;
+
+ case GL_TEXTURE_BORDER_COLOR:
+ if ( t->base.bound ) FLUSH_BATCH( rmesa );
+ r128SetTexBorderColor( 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 for R128. Since there's no LOD clamping,
+ * we just have to rely on loading the right subset of mipmap levels
+ * to simulate a clamped LOD.
+ */
+ if ( t->base.bound ) FLUSH_BATCH( rmesa );
+ driSwapOutTextureObject( (driTextureObject *) t );
+ break;
+
+ default:
+ return;
+ }
+}
+
+static void r128DDBindTexture( GLcontext *ctx, GLenum target,
+ struct gl_texture_object *tObj )
+{
+ if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
+ fprintf( stderr, "%s( %p ) unit=%d\n", __FUNCTION__, tObj,
+ ctx->Texture.CurrentUnit );
+ }
+
+ if ( target == GL_TEXTURE_2D || target == GL_TEXTURE_1D ) {
+ if ( tObj->DriverData == NULL ) {
+ r128AllocTexObj( tObj );
+ }
+ }
+}
+
+static void r128DDDeleteTexture( GLcontext *ctx,
+ struct gl_texture_object *tObj )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+ driTextureObject * t = (driTextureObject *) tObj->DriverData;
+
+ if ( t ) {
+ if ( t->bound && rmesa ) {
+ FLUSH_BATCH( rmesa );
+ }
+
+ driDestroyTextureObject( t );
+ }
+}
+
+void r128DDInitTextureFuncs( GLcontext *ctx )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+
+ ctx->Driver.TexEnv = r128DDTexEnv;
+ ctx->Driver.ChooseTextureFormat = r128ChooseTextureFormat;
+ ctx->Driver.TexImage1D = r128TexImage1D;
+ ctx->Driver.TexSubImage1D = r128TexSubImage1D;
+ ctx->Driver.TexImage2D = r128TexImage2D;
+ ctx->Driver.TexSubImage2D = r128TexSubImage2D;
+ ctx->Driver.TexImage3D = _mesa_store_teximage3d;
+ ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
+ ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d;
+ ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d;
+ ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d;
+ ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d;
+ ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d;
+ ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage;
+ ctx->Driver.TexParameter = r128DDTexParameter;
+ ctx->Driver.BindTexture = r128DDBindTexture;
+ ctx->Driver.DeleteTexture = r128DDDeleteTexture;
+ ctx->Driver.UpdateTexturePalette = NULL;
+ ctx->Driver.ActiveTexture = NULL;
+ ctx->Driver.IsTextureResident = driIsTextureResident;
+ ctx->Driver.PrioritizeTexture = NULL;
+
+ driInitTextureObjects( ctx, & rmesa->swapped,
+ DRI_TEXMGR_DO_TEXTURE_1D
+ | DRI_TEXMGR_DO_TEXTURE_2D );
+}
diff --git a/src/mesa/drivers/dri/r128/r128_tex.h b/src/mesa/drivers/dri/r128/r128_tex.h
new file mode 100644
index 0000000000..2e3d954fbb
--- /dev/null
+++ b/src/mesa/drivers/dri/r128/r128_tex.h
@@ -0,0 +1,88 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_tex.h,v 1.7 2002/02/22 21:44:58 dawes Exp $ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+ Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+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, PRECISION INSIGHT 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:
+ * Gareth Hughes <gareth@valinux.com>
+ * Kevin E. Martin <martin@valinux.com>
+ *
+ */
+
+#ifndef __R128_TEX_H__
+#define __R128_TEX_H__
+
+#ifdef GLX_DIRECT_RENDERING
+
+extern void r128UpdateTextureState( GLcontext *ctx );
+
+extern void r128UploadTexImages( r128ContextPtr rmesa, r128TexObjPtr t );
+
+extern void r128DestroyTexObj( r128ContextPtr rmesa, r128TexObjPtr t );
+
+extern void r128DDInitTextureFuncs( GLcontext *ctx );
+
+
+/* ================================================================
+ * Color conversion macros:
+ */
+
+#define R128PACKCOLOR332( r, g, b ) \
+ (((r) & 0xe0) | (((g) & 0xe0) >> 3) | (((b) & 0xc0) >> 6))
+
+#define R128PACKCOLOR1555( r, g, b, a ) \
+ ((((r) & 0xf8) << 7) | (((g) & 0xf8) << 2) | (((b) & 0xf8) >> 3) | \
+ ((a) ? 0x8000 : 0))
+
+#define R128PACKCOLOR565( r, g, b ) \
+ ((((r) & 0xf8) << 8) | (((g) & 0xfc) << 3) | (((b) & 0xf8) >> 3))
+
+#define R128PACKCOLOR888( r, g, b ) \
+ (((r) << 16) | ((g) << 8) | (b))
+
+#define R128PACKCOLOR8888( r, g, b, a ) \
+ (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
+
+#define R128PACKCOLOR4444( r, g, b, a ) \
+ ((((a) & 0xf0) << 8) | (((r) & 0xf0) << 4) | ((g) & 0xf0) | ((b) >> 4))
+
+static __inline__ CARD32 r128PackColor( GLuint cpp,
+ GLubyte r, GLubyte g,
+ GLubyte b, GLubyte a )
+{
+ switch ( cpp ) {
+ case 2:
+ return R128PACKCOLOR565( r, g, b );
+ case 4:
+ return R128PACKCOLOR8888( r, g, b, a );
+ default:
+ return 0;
+ }
+}
+
+#endif
+#endif /* __R128_TEX_H__ */
diff --git a/src/mesa/drivers/dri/r128/r128_texmem.c b/src/mesa/drivers/dri/r128/r128_texmem.c
new file mode 100644
index 0000000000..f6a5dfbbcf
--- /dev/null
+++ b/src/mesa/drivers/dri/r128/r128_texmem.c
@@ -0,0 +1,302 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_tex.c,v 1.7 2001/01/08 01:07:21 martin Exp $ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+ Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+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, PRECISION INSIGHT 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:
+ * Gareth Hughes <gareth@valinux.com>
+ * Kevin E. Martin <martin@valinux.com>
+ * Brian Paul <brianp@valinux.com>
+ */
+
+#include "r128_context.h"
+#include "r128_state.h"
+#include "r128_ioctl.h"
+#include "r128_vb.h"
+#include "r128_tris.h"
+#include "r128_tex.h"
+
+#include "context.h"
+#include "macros.h"
+#include "simple_list.h"
+#include "texformat.h"
+#include "imports.h"
+
+#define TEX_0 1
+#define TEX_1 2
+
+
+/* Destroy hardware state associated with texture `t'.
+ */
+void r128DestroyTexObj( r128ContextPtr rmesa, r128TexObjPtr t )
+{
+ unsigned i;
+
+
+ /* See if it was the driver's current object.
+ */
+
+ if ( rmesa != NULL )
+ {
+ for ( i = 0 ; i < rmesa->glCtx->Const.MaxTextureUnits ; i++ )
+ {
+ if ( t == rmesa->CurrentTexObj[ i ] ) {
+ assert( t->base.bound & (1 << i) );
+ rmesa->CurrentTexObj[ i ] = NULL;
+ }
+ }
+ }
+}
+
+
+/**
+ * Upload the texture image associated with texture \a t at the specified
+ * level at the address relative to \a start.
+ */
+static void uploadSubImage( r128ContextPtr rmesa, r128TexObjPtr t,
+ GLint level,
+ GLint x, GLint y, GLint width, GLint height )
+{
+ struct gl_texture_image *image;
+ int texelsPerDword = 0;
+ int imageWidth, imageHeight;
+ int remaining, rows;
+ int format, dwords;
+ CARD32 pitch, offset;
+ int i;
+
+ /* Ensure we have a valid texture to upload */
+ if ( ( level < 0 ) || ( level > R128_MAX_TEXTURE_LEVELS ) )
+ return;
+
+ image = t->base.tObj->Image[level];
+ if ( !image )
+ return;
+
+ switch ( image->TexFormat->TexelBytes ) {
+ case 1: texelsPerDword = 4; break;
+ case 2: texelsPerDword = 2; break;
+ case 4: texelsPerDword = 1; break;
+ }
+
+#if 1
+ /* FIXME: The subimage index calcs are wrong... */
+ x = 0;
+ y = 0;
+ width = image->Width;
+ height = image->Height;
+#endif
+
+ imageWidth = image->Width;
+ imageHeight = image->Height;
+
+ format = t->textureFormat >> 16;
+
+ /* The texel upload routines have a minimum width, so force the size
+ * if needed.
+ */
+ if ( imageWidth < texelsPerDword ) {
+ int factor;
+
+ factor = texelsPerDword / imageWidth;
+ imageWidth = texelsPerDword;
+ imageHeight /= factor;
+ if ( imageHeight == 0 ) {
+ /* In this case, the texel converter will actually walk a
+ * texel or two off the end of the image, but normal malloc
+ * alignment should prevent it from ever causing a fault.
+ */
+ imageHeight = 1;
+ }
+ }
+
+ /* We can't upload to a pitch less than 8 texels so we will need to
+ * linearly upload all modified rows for textures smaller than this.
+ * This makes the x/y/width/height different for the blitter and the
+ * texture walker.
+ */
+ if ( imageWidth >= 8 ) {
+ /* The texture walker and the blitter look identical */
+ pitch = imageWidth >> 3;
+ } else {
+ int factor;
+ int y2;
+ int start, end;
+
+ start = (y * imageWidth) & ~7;
+ end = (y + height) * imageWidth;
+
+ if ( end - start < 8 ) {
+ /* Handle the case where the total number of texels
+ * uploaded is < 8.
+ */
+ x = 0;
+ y = start / 8;
+ width = end - start;
+ height = 1;
+ } else {
+ /* Upload some number of full 8 texel blit rows */
+ factor = 8 / imageWidth;
+
+ y2 = y + height - 1;
+ y /= factor;
+ y2 /= factor;
+
+ x = 0;
+ width = 8;
+ height = y2 - y + 1;
+ }
+
+ /* Fixed pitch of 8 */
+ pitch = 1;
+ }
+
+ dwords = width * height / texelsPerDword;
+ offset = t->bufAddr + t->image[level - t->base.firstLevel].offset;
+
+#if ENABLE_PERF_BOXES
+ /* Bump the performace counter */
+ rmesa->c_textureBytes += (dwords << 2);
+#endif
+
+ if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
+ fprintf( stderr, "r128UploadSubImage: %d,%d of %d,%d at %d,%d\n",
+ width, height, image->Width, image->Height, x, y );
+ fprintf( stderr, " blit ofs: 0x%07x pitch: 0x%x dwords: %d "
+ "level: %d format: %x\n",
+ (GLuint)offset, (GLuint)pitch, dwords, level, format );
+ }
+
+ /* Subdivide the texture if required */
+ if ( dwords <= R128_BUFFER_MAX_DWORDS / 2 ) {
+ rows = height;
+ } else {
+ rows = (R128_BUFFER_MAX_DWORDS * texelsPerDword) / (2 * width);
+ }
+
+ for ( i = 0, remaining = height ;
+ remaining > 0 ;
+ remaining -= rows, y += rows, i++ )
+ {
+ CARD32 *dst;
+ drmBufPtr buffer;
+
+ assert(image->Data);
+
+ height = MIN2(remaining, rows);
+
+ /* Grab the indirect buffer for the texture blit */
+ LOCK_HARDWARE( rmesa );
+ buffer = r128GetBufferLocked( rmesa );
+
+ dst = (CARD32 *)((char *)buffer->address + R128_HOSTDATA_BLIT_OFFSET);
+
+ /* Copy the next chunck of the texture image into the blit buffer */
+ {
+ const GLubyte *src = (const GLubyte *) image->Data +
+ (y * image->Width + x) * image->TexFormat->TexelBytes;
+ const GLuint bytes = width * height * image->TexFormat->TexelBytes;
+ memcpy(dst, src, bytes);
+ }
+
+ r128FireBlitLocked( rmesa, buffer,
+ offset, pitch, format,
+ x, y, width, height );
+ UNLOCK_HARDWARE( rmesa );
+ }
+
+ rmesa->new_state |= R128_NEW_CONTEXT;
+ rmesa->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS;
+}
+
+
+/* Upload the texture images associated with texture `t'. This might
+ * require removing our own and/or other client's texture objects to
+ * make room for these images.
+ */
+void r128UploadTexImages( r128ContextPtr rmesa, r128TexObjPtr t )
+{
+ const GLint numLevels = t->base.lastLevel - t->base.firstLevel + 1;
+ GLint i;
+
+ if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
+ fprintf( stderr, "%s( %p, %p )\n",
+ __FUNCTION__, rmesa->glCtx, t );
+ }
+
+ assert(t);
+
+ LOCK_HARDWARE( rmesa );
+
+ if ( !t->base.memBlock ) {
+ int heap;
+
+
+ heap = driAllocateTexture( rmesa->texture_heaps, rmesa->nr_heaps,
+ (driTextureObject *) t );
+ if ( heap == -1 ) {
+ UNLOCK_HARDWARE( rmesa );
+ return;
+ }
+
+ /* Set the base offset of the texture image */
+ t->bufAddr = rmesa->r128Screen->texOffset[heap]
+ + t->base.memBlock->ofs;
+
+ /* Set texture offsets for each mipmap level */
+ if ( t->setup.tex_cntl & R128_MIP_MAP_DISABLE ) {
+ for ( i = 0 ; i < R128_MAX_TEXTURE_LEVELS ; i++ ) {
+ t->setup.tex_offset[i] = t->bufAddr;
+ }
+ } else {
+ for ( i = 0; i < numLevels; i++ ) {
+ const int j = numLevels - i - 1;
+ t->setup.tex_offset[j] = t->bufAddr + t->image[i].offset;
+ }
+ }
+ }
+
+ /* Let the world know we've used this memory recently.
+ */
+ driUpdateTextureLRU( (driTextureObject *) t );
+ UNLOCK_HARDWARE( rmesa );
+
+ /* Upload any images that are new */
+ if ( t->base.dirty_images[0] ) {
+ for ( i = 0 ; i < numLevels; i++ ) {
+ const GLint j = t->base.firstLevel + i; /* the texObj's level */
+ if ( t->base.dirty_images[0] & (1 << j) ) {
+ uploadSubImage( rmesa, t, j, 0, 0,
+ t->image[i].width, t->image[i].height );
+ }
+ }
+
+ rmesa->setup.tex_cntl_c |= R128_TEX_CACHE_FLUSH;
+ rmesa->dirty |= R128_UPLOAD_CONTEXT;
+ t->base.dirty_images[0] = 0;
+ }
+}
diff --git a/src/mesa/drivers/dri/r128/r128_texobj.h b/src/mesa/drivers/dri/r128/r128_texobj.h
new file mode 100644
index 0000000000..e2ff1ac24d
--- /dev/null
+++ b/src/mesa/drivers/dri/r128/r128_texobj.h
@@ -0,0 +1,69 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_texobj.h,v 1.5 2002/02/22 21:44:58 dawes Exp $ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+ Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+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, PRECISION INSIGHT 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:
+ * Kevin E. Martin <martin@valinux.com>
+ * Gareth Hughes <gareth@valinux.com>
+ *
+ */
+
+#ifndef _R128_TEXOBJ_H_
+#define _R128_TEXOBJ_H_
+
+#include "r128_sarea.h"
+#include "mm.h"
+
+/* Individual texture image information.
+ */
+typedef struct {
+ GLuint offset; /* Relative to local texture space */
+ GLuint width;
+ GLuint height;
+} r128TexImage;
+
+typedef struct r128_tex_obj r128TexObj, *r128TexObjPtr;
+
+/* Texture object in locally shared texture space.
+ */
+struct r128_tex_obj {
+ driTextureObject base;
+
+ CARD32 bufAddr; /* Offset to start of locally
+ shared texture block */
+
+ GLuint age;
+ r128TexImage image[R128_MAX_TEXTURE_LEVELS]; /* Image data for all
+ mipmap levels */
+
+ CARD32 textureFormat; /* Actual hardware format */
+
+ r128_texture_regs_t setup; /* Setup regs for texture */
+};
+
+#endif /* _R128_TEXOBJ_H_ */
diff --git a/src/mesa/drivers/dri/r128/r128_texstate.c b/src/mesa/drivers/dri/r128/r128_texstate.c
new file mode 100644
index 0000000000..3f4347b02e
--- /dev/null
+++ b/src/mesa/drivers/dri/r128/r128_texstate.c
@@ -0,0 +1,652 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_tex.c,v 1.7 2001/01/08 01:07:21 martin Exp $ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+ Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+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, PRECISION INSIGHT 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:
+ * Gareth Hughes <gareth@valinux.com>
+ * Kevin E. Martin <martin@valinux.com>
+ * Brian Paul <brianp@valinux.com>
+ */
+
+#include "glheader.h"
+#include "imports.h"
+#include "context.h"
+#include "macros.h"
+#include "texformat.h"
+
+#include "r128_context.h"
+#include "r128_state.h"
+#include "r128_ioctl.h"
+#include "r128_vb.h"
+#include "r128_tris.h"
+#include "r128_tex.h"
+
+
+static void r128SetTexImages( r128ContextPtr rmesa,
+ const struct gl_texture_object *tObj )
+{
+ r128TexObjPtr t = (r128TexObjPtr) tObj->DriverData;
+ struct gl_texture_image *baseImage = tObj->Image[tObj->BaseLevel];
+ int log2Pitch, log2Height, log2Size, log2MinSize;
+ int totalSize;
+ int i;
+ GLint firstLevel, lastLevel;
+
+ assert(t);
+ assert(baseImage);
+
+ if ( R128_DEBUG & DEBUG_VERBOSE_API )
+ fprintf( stderr, "%s( %p )\n", __FUNCTION__, tObj );
+
+ switch (baseImage->TexFormat->MesaFormat) {
+ case MESA_FORMAT_ARGB8888:
+ t->textureFormat = R128_DATATYPE_ARGB8888;
+ break;
+ case MESA_FORMAT_ARGB4444:
+ t->textureFormat = R128_DATATYPE_ARGB4444;
+ break;
+ case MESA_FORMAT_RGB565:
+ t->textureFormat = R128_DATATYPE_RGB565;
+ break;
+ case MESA_FORMAT_RGB332:
+ t->textureFormat = R128_DATATYPE_RGB8;
+ break;
+ case MESA_FORMAT_CI8:
+ t->textureFormat = R128_DATATYPE_CI8;
+ break;
+ case MESA_FORMAT_YCBCR:
+ t->textureFormat = R128_DATATYPE_YVYU422;
+ break;
+ case MESA_FORMAT_YCBCR_REV:
+ t->textureFormat = R128_DATATYPE_VYUY422;
+ break;
+ default:
+ _mesa_problem(rmesa->glCtx, "Bad texture format in %s", __FUNCTION__);
+ };
+
+ /* Compute which mipmap levels we really want to send to the hardware.
+ * This depends on the base image size, GL_TEXTURE_MIN_LOD,
+ * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
+ * Yes, this looks overly complicated, but it's all needed.
+ */
+ firstLevel = tObj->BaseLevel + (GLint) (tObj->MinLod + 0.5);
+ firstLevel = MAX2(firstLevel, tObj->BaseLevel);
+ lastLevel = tObj->BaseLevel + (GLint) (tObj->MaxLod + 0.5);
+ lastLevel = MAX2(lastLevel, tObj->BaseLevel);
+ lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2);
+ lastLevel = MIN2(lastLevel, tObj->MaxLevel);
+ lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */
+
+ log2Pitch = tObj->Image[firstLevel]->WidthLog2;
+ log2Height = tObj->Image[firstLevel]->HeightLog2;
+ log2Size = MAX2(log2Pitch, log2Height);
+ log2MinSize = log2Size;
+
+ t->base.dirty_images[0] = 0;
+ totalSize = 0;
+ for ( i = firstLevel; i <= lastLevel; i++ ) {
+ const struct gl_texture_image *texImage;
+
+ texImage = tObj->Image[i];
+ if ( !texImage || !texImage->Data ) {
+ lastLevel = i - 1;
+ break;
+ }
+
+ log2MinSize = texImage->MaxLog2;
+
+ t->image[i - firstLevel].offset = totalSize;
+ t->image[i - firstLevel].width = tObj->Image[i]->Width;
+ t->image[i - firstLevel].height = tObj->Image[i]->Height;
+
+ t->base.dirty_images[0] |= (1 << i);
+
+ totalSize += (tObj->Image[i]->Height *
+ tObj->Image[i]->Width *
+ tObj->Image[i]->TexFormat->TexelBytes);
+
+ /* Offsets must be 32-byte aligned for host data blits and tiling */
+ totalSize = (totalSize + 31) & ~31;
+ }
+
+ t->base.totalSize = totalSize;
+ t->base.firstLevel = firstLevel;
+ t->base.lastLevel = lastLevel;
+
+ /* Set the texture format */
+ t->setup.tex_cntl &= ~(0xf << 16);
+ t->setup.tex_cntl |= t->textureFormat;
+
+ t->setup.tex_combine_cntl = 0x00000000; /* XXX is this right? */
+
+ t->setup.tex_size_pitch = ((log2Pitch << R128_TEX_PITCH_SHIFT) |
+ (log2Size << R128_TEX_SIZE_SHIFT) |
+ (log2Height << R128_TEX_HEIGHT_SHIFT) |
+ (log2MinSize << R128_TEX_MIN_SIZE_SHIFT));
+
+ for ( i = 0 ; i < R128_MAX_TEXTURE_LEVELS ; i++ ) {
+ t->setup.tex_offset[i] = 0x00000000;
+ }
+
+ if (firstLevel == lastLevel)
+ t->setup.tex_cntl |= R128_MIP_MAP_DISABLE;
+ else
+ t->setup.tex_cntl &= ~R128_MIP_MAP_DISABLE;
+
+ /* FYI: r128UploadTexImages( rmesa, t ); used to be called here */
+}
+
+
+/* ================================================================
+ * Texture combine functions
+ */
+
+#define COLOR_COMB_DISABLE (R128_COMB_DIS | \
+ R128_COLOR_FACTOR_TEX)
+#define COLOR_COMB_COPY_INPUT (R128_COMB_COPY_INP | \
+ R128_COLOR_FACTOR_TEX)
+#define COLOR_COMB_MODULATE (R128_COMB_MODULATE | \
+ R128_COLOR_FACTOR_TEX)
+#define COLOR_COMB_MODULATE_NTEX (R128_COMB_MODULATE | \
+ R128_COLOR_FACTOR_NTEX)
+#define COLOR_COMB_ADD (R128_COMB_ADD | \
+ R128_COLOR_FACTOR_TEX)
+#define COLOR_COMB_BLEND_TEX (R128_COMB_BLEND_TEXTURE | \
+ R128_COLOR_FACTOR_TEX)
+/* Rage 128 Pro/M3 only! */
+#define COLOR_COMB_BLEND_COLOR (R128_COMB_MODULATE2X | \
+ R128_COMB_FCN_MSB | \
+ R128_COLOR_FACTOR_CONST_COLOR)
+
+#define ALPHA_COMB_DISABLE (R128_COMB_ALPHA_DIS | \
+ R128_ALPHA_FACTOR_TEX_ALPHA)
+#define ALPHA_COMB_COPY_INPUT (R128_COMB_ALPHA_COPY_INP | \
+ R128_ALPHA_FACTOR_TEX_ALPHA)
+#define ALPHA_COMB_MODULATE (R128_COMB_ALPHA_MODULATE | \
+ R128_ALPHA_FACTOR_TEX_ALPHA)
+#define ALPHA_COMB_MODULATE_NTEX (R128_COMB_ALPHA_MODULATE | \
+ R128_ALPHA_FACTOR_NTEX_ALPHA)
+#define ALPHA_COMB_ADD (R128_COMB_ALPHA_ADD | \
+ R128_ALPHA_FACTOR_TEX_ALPHA)
+
+#define INPUT_INTERP (R128_INPUT_FACTOR_INT_COLOR | \
+ R128_INP_FACTOR_A_INT_ALPHA)
+#define INPUT_PREVIOUS (R128_INPUT_FACTOR_PREV_COLOR | \
+ R128_INP_FACTOR_A_PREV_ALPHA)
+
+static GLboolean r128UpdateTextureEnv( GLcontext *ctx, int unit )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+ GLint source = rmesa->tmu_source[unit];
+ const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
+ const struct gl_texture_object *tObj = texUnit->_Current;
+ const GLenum format = tObj->Image[tObj->BaseLevel]->Format;
+ GLuint combine;
+
+ if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
+ fprintf( stderr, "%s( %p, %d )\n",
+ __FUNCTION__, ctx, unit );
+ }
+
+ if ( unit == 0 ) {
+ combine = INPUT_INTERP;
+ } else {
+ combine = INPUT_PREVIOUS;
+ }
+
+ /* Set the texture environment state */
+ switch ( texUnit->EnvMode ) {
+ case GL_REPLACE:
+ switch ( format ) {
+ case GL_RGBA:
+ case GL_LUMINANCE_ALPHA:
+ case GL_INTENSITY:
+ combine |= (COLOR_COMB_DISABLE | /* C = Ct */
+ ALPHA_COMB_DISABLE); /* A = At */
+ break;
+ case GL_RGB:
+ case GL_LUMINANCE:
+ combine |= (COLOR_COMB_DISABLE | /* C = Ct */
+ ALPHA_COMB_COPY_INPUT); /* A = Af */
+ break;
+ case GL_ALPHA:
+ combine |= (COLOR_COMB_COPY_INPUT | /* C = Cf */
+ ALPHA_COMB_DISABLE); /* A = At */
+ break;
+ case GL_COLOR_INDEX:
+ default:
+ return GL_FALSE;
+ }
+ break;
+
+ case GL_MODULATE:
+ switch ( format ) {
+ case GL_RGBA:
+ case GL_LUMINANCE_ALPHA:
+ case GL_INTENSITY:
+ combine |= (COLOR_COMB_MODULATE | /* C = CfCt */
+ ALPHA_COMB_MODULATE); /* A = AfAt */
+ break;
+ case GL_RGB:
+ case GL_LUMINANCE:
+ combine |= (COLOR_COMB_MODULATE | /* C = CfCt */
+ ALPHA_COMB_COPY_INPUT); /* A = Af */
+ break;
+ case GL_ALPHA:
+ combine |= (COLOR_COMB_COPY_INPUT | /* C = Cf */
+ ALPHA_COMB_MODULATE); /* A = AfAt */
+ break;
+ case GL_COLOR_INDEX:
+ default:
+ return GL_FALSE;
+ }
+ break;
+
+ case GL_DECAL:
+ switch ( format ) {
+ case GL_RGBA:
+ combine |= (COLOR_COMB_BLEND_TEX | /* C = Cf(1-At)+CtAt */
+ ALPHA_COMB_COPY_INPUT); /* A = Af */
+ break;
+ case GL_RGB:
+ combine |= (COLOR_COMB_DISABLE | /* C = Ct */
+ ALPHA_COMB_COPY_INPUT); /* A = Af */
+ break;
+ case GL_ALPHA:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ case GL_INTENSITY:
+ /* Undefined behaviour - just copy the incoming fragment */
+ combine |= (COLOR_COMB_COPY_INPUT | /* C = undefined */
+ ALPHA_COMB_COPY_INPUT); /* A = undefined */
+ break;
+ case GL_COLOR_INDEX:
+ default:
+ return GL_FALSE;
+ }
+ break;
+
+ case GL_BLEND:
+ /* Rage 128 Pro and M3 can handle GL_BLEND texturing.
+ */
+ if ( !R128_IS_PLAIN( rmesa ) ) {
+ /* XXX this hasn't been fully tested, I don't have a Pro card. -BP */
+ switch ( format ) {
+ case GL_RGBA:
+ case GL_LUMINANCE_ALPHA:
+ combine |= (COLOR_COMB_BLEND_COLOR | /* C = Cf(1-Ct)+CcCt */
+ ALPHA_COMB_MODULATE); /* A = AfAt */
+ break;
+
+ case GL_RGB:
+ case GL_LUMINANCE:
+ combine |= (COLOR_COMB_BLEND_COLOR | /* C = Cf(1-Ct)+CcCt */
+ ALPHA_COMB_COPY_INPUT); /* A = Af */
+ break;
+
+ case GL_ALPHA:
+ combine |= (COLOR_COMB_COPY_INPUT | /* C = Cf */
+ ALPHA_COMB_MODULATE); /* A = AfAt */
+ break;
+
+ case GL_INTENSITY:
+ /* GH: We could be smarter about this... */
+ switch ( rmesa->env_color & 0xff000000 ) {
+ case 0x00000000:
+ combine |= (COLOR_COMB_BLEND_COLOR | /* C = Cf(1-It)+CcIt */
+ ALPHA_COMB_MODULATE_NTEX); /* A = Af(1-It) */
+ default:
+ combine |= (COLOR_COMB_MODULATE | /* C = fallback */
+ ALPHA_COMB_MODULATE); /* A = fallback */
+ return GL_FALSE;
+ }
+ break;
+
+ case GL_COLOR_INDEX:
+ default:
+ return GL_FALSE;
+ }
+ break;
+ }
+
+ /* Rage 128 has to fake some cases of GL_BLEND, otherwise fallback
+ * to software rendering.
+ */
+ if ( rmesa->blend_flags ) {
+ return GL_FALSE;
+ }
+ switch ( format ) {
+ case GL_RGBA:
+ case GL_LUMINANCE_ALPHA:
+ switch ( rmesa->env_color & 0x00ffffff ) {
+ case 0x00000000:
+ combine |= (COLOR_COMB_MODULATE_NTEX | /* C = Cf(1-Ct) */
+ ALPHA_COMB_MODULATE); /* A = AfAt */
+ break;
+#if 0
+ /* This isn't right - BP */
+ case 0x00ffffff:
+ if ( unit == 0 ) {
+ combine |= (COLOR_COMB_MODULATE_NTEX | /* C = Cf(1-Ct) */
+ ALPHA_COMB_MODULATE); /* A = AfAt */
+ } else {
+ combine |= (COLOR_COMB_ADD | /* C = Cf+Ct */
+ ALPHA_COMB_COPY_INPUT); /* A = Af */
+ }
+ break;
+#endif
+ default:
+ combine |= (COLOR_COMB_MODULATE | /* C = fallback */
+ ALPHA_COMB_MODULATE); /* A = fallback */
+ return GL_FALSE;
+ }
+ break;
+ case GL_RGB:
+ case GL_LUMINANCE:
+ switch ( rmesa->env_color & 0x00ffffff ) {
+ case 0x00000000:
+ combine |= (COLOR_COMB_MODULATE_NTEX | /* C = Cf(1-Ct) */
+ ALPHA_COMB_COPY_INPUT); /* A = Af */
+ break;
+#if 0
+ /* This isn't right - BP */
+ case 0x00ffffff:
+ if ( unit == 0 ) {
+ combine |= (COLOR_COMB_MODULATE_NTEX | /* C = Cf(1-Ct) */
+ ALPHA_COMB_COPY_INPUT); /* A = Af */
+ } else {
+ combine |= (COLOR_COMB_ADD | /* C = Cf+Ct */
+ ALPHA_COMB_COPY_INPUT); /* A = Af */
+ }
+ break;
+#endif
+ default:
+ combine |= (COLOR_COMB_MODULATE | /* C = fallback */
+ ALPHA_COMB_COPY_INPUT); /* A = fallback */
+ return GL_FALSE;
+ }
+ break;
+ case GL_ALPHA:
+ if ( unit == 0 ) {
+ combine |= (COLOR_COMB_COPY_INPUT | /* C = Cf */
+ ALPHA_COMB_MODULATE); /* A = AfAt */
+ } else {
+ combine |= (COLOR_COMB_COPY_INPUT | /* C = Cf */
+ ALPHA_COMB_COPY_INPUT); /* A = Af */
+ }
+ break;
+ case GL_INTENSITY:
+ switch ( rmesa->env_color & 0x00ffffff ) {
+ case 0x00000000:
+ combine |= COLOR_COMB_MODULATE_NTEX; /* C = Cf(1-It) */
+ break;
+#if 0
+ /* This isn't right - BP */
+ case 0x00ffffff:
+ if ( unit == 0 ) {
+ combine |= COLOR_COMB_MODULATE_NTEX; /* C = Cf(1-It) */
+ } else {
+ combine |= COLOR_COMB_ADD; /* C = Cf+It */
+ }
+ break;
+#endif
+ default:
+ combine |= (COLOR_COMB_MODULATE | /* C = fallback */
+ ALPHA_COMB_MODULATE); /* A = fallback */
+ return GL_FALSE;
+ }
+ switch ( rmesa->env_color & 0xff000000 ) {
+ case 0x00000000:
+ combine |= ALPHA_COMB_MODULATE_NTEX; /* A = Af(1-It) */
+ break;
+#if 0
+ /* This isn't right - BP */
+ case 0xff000000:
+ if ( unit == 0 ) {
+ combine |= ALPHA_COMB_MODULATE_NTEX; /* A = Af(1-It) */
+ } else {
+ combine |= ALPHA_COMB_ADD; /* A = Af+It */
+ }
+ break;
+#endif
+ default:
+ combine |= (COLOR_COMB_MODULATE | /* C = fallback */
+ ALPHA_COMB_MODULATE); /* A = fallback */
+ return GL_FALSE;
+ }
+ break;
+ case GL_COLOR_INDEX:
+ default:
+ return GL_FALSE;
+ }
+ break;
+
+ case GL_ADD:
+ switch ( format ) {
+ case GL_RGBA:
+ case GL_LUMINANCE_ALPHA:
+ combine |= (COLOR_COMB_ADD | /* C = Cf+Ct */
+ ALPHA_COMB_MODULATE); /* A = AfAt */
+ break;
+ case GL_RGB:
+ case GL_LUMINANCE:
+ combine |= (COLOR_COMB_ADD | /* C = Cf+Ct */
+ ALPHA_COMB_COPY_INPUT); /* A = Af */
+ break;
+ case GL_ALPHA:
+ combine |= (COLOR_COMB_COPY_INPUT | /* C = Cf */
+ ALPHA_COMB_MODULATE); /* A = AfAt */
+ break;
+ case GL_INTENSITY:
+ combine |= (COLOR_COMB_ADD | /* C = Cf+Ct */
+ ALPHA_COMB_ADD); /* A = Af+At */
+ break;
+ case GL_COLOR_INDEX:
+ default:
+ return GL_FALSE;
+ }
+ break;
+
+ default:
+ return GL_FALSE;
+ }
+
+ if ( rmesa->tex_combine[unit] != combine ) {
+ rmesa->tex_combine[unit] = combine;
+ rmesa->dirty |= R128_UPLOAD_TEX0 << unit;
+ }
+ return GL_TRUE;
+}
+
+static void disable_tex( GLcontext *ctx, int unit )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+ FLUSH_BATCH( rmesa );
+
+ if ( rmesa->CurrentTexObj[unit] ) {
+ rmesa->CurrentTexObj[unit]->base.bound &= ~(1 << unit);
+ rmesa->CurrentTexObj[unit] = NULL;
+ }
+
+ rmesa->setup.tex_cntl_c &= ~(R128_TEXMAP_ENABLE << unit);
+ rmesa->setup.tex_size_pitch_c &= ~(R128_TEX_SIZE_PITCH_MASK <<
+ (R128_SEC_TEX_SIZE_PITCH_SHIFT * unit));
+ rmesa->dirty |= R128_UPLOAD_CONTEXT;
+
+ /* If either texture unit is disabled, then multitexturing is not
+ * happening.
+ */
+
+ rmesa->blend_flags &= ~R128_BLEND_MULTITEX;
+}
+
+static GLboolean enable_tex_2d( GLcontext *ctx, int unit )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+ const int source = rmesa->tmu_source[unit];
+ const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
+ const struct gl_texture_object *tObj = texUnit->_Current;
+ r128TexObjPtr t = (r128TexObjPtr) tObj->DriverData;
+
+ /* Need to load the 2d images associated with this unit.
+ */
+ if ( t->base.dirty_images[0] ) {
+ /* FIXME: For Radeon, RADEON_FIREVERTICES is called here. Should
+ * FIXME: something similar be done for R128?
+ */
+ /* FLUSH_BATCH( rmesa ); */
+
+ r128SetTexImages( rmesa, tObj );
+ r128UploadTexImages( rmesa, t );
+ if ( !t->base.memBlock )
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+static GLboolean update_tex_common( GLcontext *ctx, int unit )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+ const int source = rmesa->tmu_source[unit];
+ const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
+ const struct gl_texture_object *tObj = texUnit->_Current;
+ r128TexObjPtr t = (r128TexObjPtr) tObj->DriverData;
+
+
+ /* Fallback if there's a texture border */
+ if ( tObj->Image[tObj->BaseLevel]->Border > 0 ) {
+ return GL_FALSE;
+ }
+
+
+ /* Update state if this is a different texture object to last
+ * time.
+ */
+ if ( rmesa->CurrentTexObj[unit] != t ) {
+ if ( rmesa->CurrentTexObj[unit] != NULL ) {
+ /* The old texture is no longer bound to this texture unit.
+ * Mark it as such.
+ */
+
+ rmesa->CurrentTexObj[unit]->base.bound &=
+ ~(1UL << unit);
+ }
+
+ rmesa->CurrentTexObj[unit] = t;
+ t->base.bound |= (1UL << unit);
+ rmesa->dirty |= R128_UPLOAD_TEX0 << unit;
+
+ driUpdateTextureLRU( (driTextureObject *) t ); /* XXX: should be locked! */
+ }
+
+ /* FIXME: We need to update the texture unit if any texture parameters have
+ * changed, but this texture was already bound. This could be changed to
+ * work like the Radeon driver where the texture object has it's own
+ * dirty state flags
+ */
+ rmesa->dirty |= R128_UPLOAD_TEX0 << unit;
+
+ /* register setup */
+ rmesa->setup.tex_size_pitch_c &= ~(R128_TEX_SIZE_PITCH_MASK <<
+ (R128_SEC_TEX_SIZE_PITCH_SHIFT * unit));
+
+ if ( unit == 0 ) {
+ rmesa->setup.tex_cntl_c |= R128_TEXMAP_ENABLE;
+ rmesa->setup.tex_size_pitch_c |= t->setup.tex_size_pitch << 0;
+ rmesa->setup.scale_3d_cntl &= ~R128_TEX_CACHE_SPLIT;
+ t->setup.tex_cntl &= ~R128_SEC_SELECT_SEC_ST;
+ }
+ else {
+ rmesa->setup.tex_cntl_c |= R128_SEC_TEXMAP_ENABLE;
+ rmesa->setup.tex_size_pitch_c |= t->setup.tex_size_pitch << 16;
+ rmesa->setup.scale_3d_cntl |= R128_TEX_CACHE_SPLIT;
+ t->setup.tex_cntl |= R128_SEC_SELECT_SEC_ST;
+
+ /* If the second TMU is enabled, then multitexturing is happening.
+ */
+ if ( R128_IS_PLAIN( rmesa ) )
+ rmesa->blend_flags |= R128_BLEND_MULTITEX;
+ }
+
+ rmesa->dirty |= R128_UPLOAD_CONTEXT;
+
+
+ /* FIXME: The Radeon has some cached state so that it can avoid calling
+ * FIXME: UpdateTextureEnv in some cases. Is that possible here?
+ */
+ return r128UpdateTextureEnv( ctx, unit );
+}
+
+static GLboolean updateTextureUnit( GLcontext *ctx, int unit )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+ const int source = rmesa->tmu_source[unit];
+ const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
+
+
+ if (texUnit->_ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT)) {
+ return (enable_tex_2d( ctx, unit ) &&
+ update_tex_common( ctx, unit ));
+ }
+ else if ( texUnit->_ReallyEnabled ) {
+ return GL_FALSE;
+ }
+ else {
+ disable_tex( ctx, unit );
+ return GL_TRUE;
+ }
+}
+
+
+void r128UpdateTextureState( GLcontext *ctx )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+ GLboolean ok;
+
+
+ /* This works around a quirk with the R128 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.
+ */
+
+ rmesa->tmu_source[0] = 0;
+ rmesa->tmu_source[1] = 1;
+
+ if ((ctx->Texture._EnabledUnits & 0x03) == 0x02) {
+ /* only texture 1 enabled */
+ rmesa->tmu_source[0] = 1;
+ rmesa->tmu_source[1] = 0;
+ }
+
+ ok = (updateTextureUnit( ctx, 0 ) &&
+ updateTextureUnit( ctx, 1 ));
+
+ FALLBACK( rmesa, R128_FALLBACK_TEXTURE, !ok );
+}
diff --git a/src/mesa/drivers/dri/r128/r128_tris.c b/src/mesa/drivers/dri/r128/r128_tris.c
new file mode 100644
index 0000000000..4e2860288e
--- /dev/null
+++ b/src/mesa/drivers/dri/r128/r128_tris.c
@@ -0,0 +1,721 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_tris.c,v 1.8 2002/10/30 12:51:43 alanh Exp $ */ /* -*- c-basic-offset: 3 -*- */
+/**************************************************************************
+
+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>
+ *
+ */
+
+#include "glheader.h"
+#include "mtypes.h"
+#include "colormac.h"
+#include "macros.h"
+
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+#include "r128_tris.h"
+#include "r128_state.h"
+#include "r128_tex.h"
+#include "r128_vb.h"
+#include "r128_ioctl.h"
+
+static const GLuint hw_prim[GL_POLYGON+1] = {
+ R128_CCE_VC_CNTL_PRIM_TYPE_POINT,
+ R128_CCE_VC_CNTL_PRIM_TYPE_LINE,
+ R128_CCE_VC_CNTL_PRIM_TYPE_LINE,
+ R128_CCE_VC_CNTL_PRIM_TYPE_LINE,
+ R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST,
+ R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST,
+ R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST,
+ R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST,
+ R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST,
+ R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST,
+};
+
+static void r128RasterPrimitive( GLcontext *ctx, GLuint hwprim );
+static void r128RenderPrimitive( GLcontext *ctx, GLenum prim );
+
+
+/***********************************************************************
+ * Emit primitives as inline vertices *
+ ***********************************************************************/
+
+#if defined(USE_X86_ASM)
+#define COPY_DWORDS( j, vb, vertsize, v ) \
+do { \
+ int __tmp; \
+ __asm__ __volatile__( "rep ; movsl" \
+ : "=%c" (j), "=D" (vb), "=S" (__tmp) \
+ : "0" (vertsize), \
+ "D" ((long)vb), \
+ "S" ((long)v) ); \
+} while (0)
+#else
+#define COPY_DWORDS( j, vb, vertsize, v ) \
+do { \
+ for ( j = 0 ; j < vertsize ; j++ ) \
+ vb[j] = CPU_TO_LE32(((GLuint *)v)[j]); \
+ vb += vertsize; \
+} while (0)
+#endif
+
+static __inline void r128_draw_quad( r128ContextPtr rmesa,
+ r128VertexPtr v0,
+ r128VertexPtr v1,
+ r128VertexPtr v2,
+ r128VertexPtr v3 )
+{
+ GLuint vertsize = rmesa->vertex_size;
+ GLuint *vb = (GLuint *)r128AllocDmaLow( rmesa, 6 * vertsize * 4 );
+ GLuint j;
+
+ rmesa->num_verts += 6;
+ COPY_DWORDS( j, vb, vertsize, v0 );
+ COPY_DWORDS( j, vb, vertsize, v1 );
+ COPY_DWORDS( j, vb, vertsize, v3 );
+ COPY_DWORDS( j, vb, vertsize, v1 );
+ COPY_DWORDS( j, vb, vertsize, v2 );
+ COPY_DWORDS( j, vb, vertsize, v3 );
+}
+
+
+static __inline void r128_draw_triangle( r128ContextPtr rmesa,
+ r128VertexPtr v0,
+ r128VertexPtr v1,
+ r128VertexPtr v2 )
+{
+ GLuint vertsize = rmesa->vertex_size;
+ GLuint *vb = (GLuint *)r128AllocDmaLow( rmesa, 3 * vertsize * 4 );
+ GLuint j;
+
+ rmesa->num_verts += 3;
+ COPY_DWORDS( j, vb, vertsize, v0 );
+ COPY_DWORDS( j, vb, vertsize, v1 );
+ COPY_DWORDS( j, vb, vertsize, v2 );
+}
+
+static __inline void r128_draw_line( r128ContextPtr rmesa,
+ r128VertexPtr v0,
+ r128VertexPtr v1 )
+{
+ GLuint vertsize = rmesa->vertex_size;
+ GLuint *vb = (GLuint *)r128AllocDmaLow( rmesa, 2 * vertsize * 4 );
+ GLuint j;
+
+ rmesa->num_verts += 2;
+ COPY_DWORDS( j, vb, vertsize, v0 );
+ COPY_DWORDS( j, vb, vertsize, v1 );
+}
+
+static __inline void r128_draw_point( r128ContextPtr rmesa,
+ r128VertexPtr v0 )
+{
+ int vertsize = rmesa->vertex_size;
+ GLuint *vb = (GLuint *)r128AllocDmaLow( rmesa, vertsize * 4 );
+ int j;
+
+ rmesa->num_verts += 1;
+ COPY_DWORDS( j, vb, vertsize, v0 );
+}
+
+/***********************************************************************
+ * Macros for t_dd_tritmp.h to draw basic primitives *
+ ***********************************************************************/
+
+#define TRI( a, b, c ) \
+do { \
+ if (DO_FALLBACK) \
+ rmesa->draw_tri( rmesa, a, b, c ); \
+ else \
+ r128_draw_triangle( rmesa, a, b, c ); \
+} while (0)
+
+#define QUAD( a, b, c, d ) \
+do { \
+ if (DO_FALLBACK) { \
+ rmesa->draw_tri( rmesa, a, b, d ); \
+ rmesa->draw_tri( rmesa, b, c, d ); \
+ } else \
+ r128_draw_quad( rmesa, a, b, c, d ); \
+} while (0)
+
+#define LINE( v0, v1 ) \
+do { \
+ if (DO_FALLBACK) \
+ rmesa->draw_line( rmesa, v0, v1 ); \
+ else \
+ r128_draw_line( rmesa, v0, v1 ); \
+} while (0)
+
+#define POINT( v0 ) \
+do { \
+ if (DO_FALLBACK) \
+ rmesa->draw_point( rmesa, v0 ); \
+ else \
+ r128_draw_point( rmesa, v0 ); \
+} while (0)
+
+
+/***********************************************************************
+ * Build render functions from dd templates *
+ ***********************************************************************/
+
+#define R128_OFFSET_BIT 0x01
+#define R128_TWOSIDE_BIT 0x02
+#define R128_UNFILLED_BIT 0x04
+#define R128_FALLBACK_BIT 0x08
+#define R128_MAX_TRIFUNC 0x10
+
+
+static struct {
+ points_func points;
+ line_func line;
+ triangle_func triangle;
+ quad_func quad;
+} rast_tab[R128_MAX_TRIFUNC];
+
+
+#define DO_FALLBACK (IND & R128_FALLBACK_BIT)
+#define DO_OFFSET (IND & R128_OFFSET_BIT)
+#define DO_UNFILLED (IND & R128_UNFILLED_BIT)
+#define DO_TWOSIDE (IND & R128_TWOSIDE_BIT)
+#define DO_FLAT 0
+#define DO_TRI 1
+#define DO_QUAD 1
+#define DO_LINE 1
+#define DO_POINTS 1
+#define DO_FULL_QUAD 1
+
+#define HAVE_RGBA 1
+#define HAVE_SPEC 1
+#define HAVE_BACK_COLORS 0
+#define HAVE_HW_FLATSHADE 1
+#define VERTEX r128Vertex
+#define TAB rast_tab
+
+#define DEPTH_SCALE 1.0
+#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) (rmesa->verts + (e<<rmesa->vertex_stride_shift))
+
+#define VERT_SET_RGBA( v, c ) do { \
+ r128_color_t *vc = (r128_color_t *)&(v)->ui[coloroffset]; \
+ vc->blue = (c)[2]; \
+ vc->green = (c)[1]; \
+ vc->red = (c)[0]; \
+ vc->alpha = (c)[3]; \
+ } while (0)
+#define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
+#define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset]
+#define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
+
+#define VERT_SET_SPEC( v0, c ) if (havespec) { \
+ (v0)->v.specular.red = (c)[0];\
+ (v0)->v.specular.green = (c)[1];\
+ (v0)->v.specular.blue = (c)[2]; }
+#define VERT_COPY_SPEC( v0, v1 ) if (havespec) { \
+ (v0)->v.specular.red = v1->v.specular.red; \
+ (v0)->v.specular.green = v1->v.specular.green; \
+ (v0)->v.specular.blue = v1->v.specular.blue; }
+
+#define VERT_SAVE_SPEC( idx ) if (havespec) spec[idx] = v[idx]->ui[5]
+#define VERT_RESTORE_SPEC( idx ) if (havespec) v[idx]->ui[5] = spec[idx]
+
+#define LOCAL_VARS(n) \
+ r128ContextPtr rmesa = R128_CONTEXT(ctx); \
+ GLuint color[n], spec[n]; \
+ GLuint coloroffset = (rmesa->vertex_size == 4 ? 3 : 4); \
+ GLboolean havespec = (rmesa->vertex_size == 4 ? 0 : 1); \
+ (void) color; (void) spec; (void) coloroffset; (void) havespec;
+
+/***********************************************************************
+ * Helpers for rendering unfilled primitives *
+ ***********************************************************************/
+
+#define RASTERIZE(x) if (rmesa->hw_primitive != hw_prim[x]) \
+ r128RasterPrimitive( ctx, hw_prim[x] )
+#define RENDER_PRIMITIVE rmesa->render_primitive
+#define IND R128_FALLBACK_BIT
+#define TAG(x) x
+#include "tnl_dd/t_dd_unfilled.h"
+#undef IND
+
+
+/***********************************************************************
+ * Generate GL render functions *
+ ***********************************************************************/
+
+
+#define IND (0)
+#define TAG(x) x
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (R128_OFFSET_BIT)
+#define TAG(x) x##_offset
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (R128_TWOSIDE_BIT)
+#define TAG(x) x##_twoside
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (R128_TWOSIDE_BIT|R128_OFFSET_BIT)
+#define TAG(x) x##_twoside_offset
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (R128_UNFILLED_BIT)
+#define TAG(x) x##_unfilled
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (R128_OFFSET_BIT|R128_UNFILLED_BIT)
+#define TAG(x) x##_offset_unfilled
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (R128_TWOSIDE_BIT|R128_UNFILLED_BIT)
+#define TAG(x) x##_twoside_unfilled
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (R128_TWOSIDE_BIT|R128_OFFSET_BIT|R128_UNFILLED_BIT)
+#define TAG(x) x##_twoside_offset_unfilled
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (R128_FALLBACK_BIT)
+#define TAG(x) x##_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (R128_OFFSET_BIT|R128_FALLBACK_BIT)
+#define TAG(x) x##_offset_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (R128_TWOSIDE_BIT|R128_FALLBACK_BIT)
+#define TAG(x) x##_twoside_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (R128_TWOSIDE_BIT|R128_OFFSET_BIT|R128_FALLBACK_BIT)
+#define TAG(x) x##_twoside_offset_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (R128_UNFILLED_BIT|R128_FALLBACK_BIT)
+#define TAG(x) x##_unfilled_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (R128_OFFSET_BIT|R128_UNFILLED_BIT|R128_FALLBACK_BIT)
+#define TAG(x) x##_offset_unfilled_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (R128_TWOSIDE_BIT|R128_UNFILLED_BIT|R128_FALLBACK_BIT)
+#define TAG(x) x##_twoside_unfilled_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (R128_TWOSIDE_BIT|R128_OFFSET_BIT|R128_UNFILLED_BIT| \
+ R128_FALLBACK_BIT)
+#define TAG(x) x##_twoside_offset_unfilled_fallback
+#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();
+}
+
+
+
+/***********************************************************************
+ * Rasterization fallback helpers *
+ ***********************************************************************/
+
+
+/* This code is hit only when a mix of accelerated and unaccelerated
+ * primitives are being drawn, and only for the unaccelerated
+ * primitives.
+ */
+static void
+r128_fallback_tri( r128ContextPtr rmesa,
+ r128Vertex *v0,
+ r128Vertex *v1,
+ r128Vertex *v2 )
+{
+ GLcontext *ctx = rmesa->glCtx;
+ SWvertex v[3];
+ r128_translate_vertex( ctx, v0, &v[0] );
+ r128_translate_vertex( ctx, v1, &v[1] );
+ r128_translate_vertex( ctx, v2, &v[2] );
+ _swrast_Triangle( ctx, &v[0], &v[1], &v[2] );
+}
+
+
+static void
+r128_fallback_line( r128ContextPtr rmesa,
+ r128Vertex *v0,
+ r128Vertex *v1 )
+{
+ GLcontext *ctx = rmesa->glCtx;
+ SWvertex v[2];
+ r128_translate_vertex( ctx, v0, &v[0] );
+ r128_translate_vertex( ctx, v1, &v[1] );
+ _swrast_Line( ctx, &v[0], &v[1] );
+}
+
+
+static void
+r128_fallback_point( r128ContextPtr rmesa,
+ r128Vertex *v0 )
+{
+ GLcontext *ctx = rmesa->glCtx;
+ SWvertex v[1];
+ r128_translate_vertex( ctx, v0, &v[0] );
+ _swrast_Point( ctx, &v[0] );
+}
+
+
+
+/**********************************************************************/
+/* Render unclipped begin/end objects */
+/**********************************************************************/
+
+#define VERT(x) (r128Vertex *)(r128verts + (x << shift))
+#define RENDER_POINTS( start, count ) \
+ for ( ; start < count ; start++) \
+ r128_draw_point( rmesa, VERT(start) )
+#define RENDER_LINE( v0, v1 ) \
+ r128_draw_line( rmesa, VERT(v0), VERT(v1) )
+#define RENDER_TRI( v0, v1, v2 ) \
+ r128_draw_triangle( rmesa, VERT(v0), VERT(v1), VERT(v2) )
+#define RENDER_QUAD( v0, v1, v2, v3 ) \
+ r128_draw_quad( rmesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
+#define INIT(x) do { \
+ if (0) fprintf(stderr, "%s\n", __FUNCTION__); \
+ r128RenderPrimitive( ctx, x ); \
+} while (0)
+#undef LOCAL_VARS
+#define LOCAL_VARS \
+ r128ContextPtr rmesa = R128_CONTEXT(ctx); \
+ const GLuint shift = rmesa->vertex_stride_shift; \
+ const char *r128verts = (char *)rmesa->verts; \
+ 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) r128_##x##_verts
+#include "tnl/t_vb_rendertmp.h"
+#undef ELT
+#undef TAG
+#define TAG(x) r128_##x##_elts
+#define ELT(x) elt[x]
+#include "tnl/t_vb_rendertmp.h"
+
+
+/**********************************************************************/
+/* Render clipped primitives */
+/**********************************************************************/
+
+static void r128RenderClippedPoly( GLcontext *ctx, const GLuint *elts,
+ GLuint n )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+
+ /* 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;
+ }
+}
+
+static void r128RenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ tnl->Driver.Render.Line( ctx, ii, jj );
+}
+
+static void r128FastRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
+ GLuint n )
+{
+ r128ContextPtr rmesa = R128_CONTEXT( ctx );
+ GLuint vertsize = rmesa->vertex_size;
+ GLuint *vb = r128AllocDmaLow( rmesa, (n-2) * 3 * 4 * vertsize );
+ GLubyte *r128verts = (GLubyte *)rmesa->verts;
+ const GLuint shift = rmesa->vertex_stride_shift;
+ const GLuint *start = (const GLuint *)VERT(elts[0]);
+ int i,j;
+
+ rmesa->num_verts += (n-2) * 3;
+
+ for (i = 2 ; i < n ; i++) {
+ COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) VERT(elts[i-1]) );
+ COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) VERT(elts[i]) );
+ COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) start );
+ }
+}
+
+
+
+
+/**********************************************************************/
+/* Choose render functions */
+/**********************************************************************/
+
+#define _R128_NEW_RENDER_STATE (_DD_NEW_LINE_STIPPLE | \
+ _DD_NEW_LINE_SMOOTH | \
+ _DD_NEW_POINT_SMOOTH | \
+ _DD_NEW_TRI_SMOOTH | \
+ _DD_NEW_TRI_UNFILLED | \
+ _DD_NEW_TRI_LIGHT_TWOSIDE | \
+ _DD_NEW_TRI_OFFSET) \
+
+
+#define POINT_FALLBACK (DD_POINT_SMOOTH)
+#define LINE_FALLBACK (DD_LINE_STIPPLE|DD_LINE_SMOOTH)
+#define TRI_FALLBACK (DD_TRI_SMOOTH)
+#define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)
+#define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
+
+
+static void r128ChooseRenderState(GLcontext *ctx)
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+ GLuint flags = ctx->_TriangleCaps;
+ GLuint index = 0;
+
+ if (flags & (ANY_RASTER_FLAGS|ANY_FALLBACK_FLAGS)) {
+ rmesa->draw_point = r128_draw_point;
+ rmesa->draw_line = r128_draw_line;
+ rmesa->draw_tri = r128_draw_triangle;
+
+ if (flags & ANY_RASTER_FLAGS) {
+ if (flags & DD_TRI_LIGHT_TWOSIDE) index |= R128_TWOSIDE_BIT;
+ if (flags & DD_TRI_OFFSET) index |= R128_OFFSET_BIT;
+ if (flags & DD_TRI_UNFILLED) index |= R128_UNFILLED_BIT;
+ }
+
+ /* Hook in fallbacks for specific primitives.
+ */
+ if (flags & (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)) {
+ if (flags & POINT_FALLBACK) rmesa->draw_point = r128_fallback_point;
+ if (flags & LINE_FALLBACK) rmesa->draw_line = r128_fallback_line;
+ if (flags & TRI_FALLBACK) rmesa->draw_tri = r128_fallback_tri;
+ index |= R128_FALLBACK_BIT;
+ }
+ }
+
+ if (index != rmesa->RenderIndex) {
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ 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 = r128_render_tab_verts;
+ tnl->Driver.Render.PrimTabElts = r128_render_tab_elts;
+ tnl->Driver.Render.ClippedLine = rast_tab[index].line;
+ tnl->Driver.Render.ClippedPolygon = r128FastRenderClippedPoly;
+ } else {
+ tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
+ tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
+ tnl->Driver.Render.ClippedLine = r128RenderClippedLine;
+ tnl->Driver.Render.ClippedPolygon = r128RenderClippedPoly;
+ }
+
+ rmesa->RenderIndex = index;
+ }
+}
+
+/**********************************************************************/
+/* Validate state at pipeline start */
+/**********************************************************************/
+
+static void r128RunPipeline( GLcontext *ctx )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+ if (rmesa->new_state || rmesa->NewGLState & _NEW_TEXTURE)
+ r128DDUpdateHWState( ctx );
+
+ if (!rmesa->Fallback && rmesa->NewGLState) {
+ if (rmesa->NewGLState & _R128_NEW_VERTEX_STATE)
+ r128ChooseVertexState( ctx );
+
+ if (rmesa->NewGLState & _R128_NEW_RENDER_STATE)
+ r128ChooseRenderState( ctx );
+
+ rmesa->NewGLState = 0;
+ }
+
+ _tnl_run_pipeline( ctx );
+}
+
+/**********************************************************************/
+/* High level hooks for t_vb_render.c */
+/**********************************************************************/
+
+/* This is called when Mesa switches between rendering triangle
+ * primitives (such as GL_POLYGON, GL_QUADS, GL_TRIANGLE_STRIP, etc),
+ * and lines, points and bitmaps.
+ *
+ * As the r128 uses triangles to render lines and points, it is
+ * necessary to turn off hardware culling when rendering these
+ * primitives.
+ */
+
+static void r128RasterPrimitive( GLcontext *ctx, GLuint hwprim )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+ rmesa->setup.dp_gui_master_cntl_c &= ~R128_GMC_BRUSH_NONE;
+
+ if ( ctx->Polygon.StippleFlag && hwprim == GL_TRIANGLES ) {
+ rmesa->setup.dp_gui_master_cntl_c |= R128_GMC_BRUSH_32x32_MONO_FG_LA;
+ }
+ else {
+ rmesa->setup.dp_gui_master_cntl_c |= R128_GMC_BRUSH_SOLID_COLOR;
+ }
+
+ rmesa->new_state |= R128_NEW_CONTEXT;
+ rmesa->dirty |= R128_UPLOAD_CONTEXT;
+
+ if (rmesa->hw_primitive != hwprim) {
+ FLUSH_BATCH( rmesa );
+ rmesa->hw_primitive = hwprim;
+ }
+}
+
+static void r128RenderPrimitive( GLcontext *ctx, GLenum prim )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+ GLuint hw = hw_prim[prim];
+ rmesa->render_primitive = prim;
+ if (prim >= GL_TRIANGLES && (ctx->_TriangleCaps & DD_TRI_UNFILLED))
+ return;
+ r128RasterPrimitive( ctx, hw );
+}
+
+
+static void r128RenderStart( GLcontext *ctx )
+{
+ /* Check for projective texturing. Make sure all texcoord
+ * pointers point to something. (fix in mesa?)
+ */
+ r128CheckTexSizes( ctx );
+}
+
+static void r128RenderFinish( GLcontext *ctx )
+{
+ if (R128_CONTEXT(ctx)->RenderIndex & R128_FALLBACK_BIT)
+ _swrast_flush( ctx );
+}
+
+
+/**********************************************************************/
+/* Transition to/from hardware rasterization. */
+/**********************************************************************/
+
+void r128Fallback( GLcontext *ctx, GLuint bit, GLboolean mode )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+ GLuint oldfallback = rmesa->Fallback;
+
+ if (mode) {
+ rmesa->Fallback |= bit;
+ if (oldfallback == 0) {
+ FLUSH_BATCH( rmesa );
+ _swsetup_Wakeup( ctx );
+ rmesa->RenderIndex = ~0;
+ }
+ }
+ else {
+ rmesa->Fallback &= ~bit;
+ if (oldfallback == bit) {
+ _swrast_flush( ctx );
+ tnl->Driver.Render.Start = r128RenderStart;
+ tnl->Driver.Render.PrimitiveNotify = r128RenderPrimitive;
+ tnl->Driver.Render.Finish = r128RenderFinish;
+ tnl->Driver.Render.BuildVertices = r128BuildVertices;
+ rmesa->NewGLState |= (_R128_NEW_RENDER_STATE|
+ _R128_NEW_VERTEX_STATE);
+ }
+ }
+}
+
+
+/**********************************************************************/
+/* Initialization. */
+/**********************************************************************/
+
+void r128InitTriFuncs( GLcontext *ctx )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ static int firsttime = 1;
+
+ if (firsttime) {
+ init_rast_tab();
+ firsttime = 0;
+ }
+
+ tnl->Driver.RunPipeline = r128RunPipeline;
+ tnl->Driver.Render.Start = r128RenderStart;
+ tnl->Driver.Render.Finish = r128RenderFinish;
+ tnl->Driver.Render.PrimitiveNotify = r128RenderPrimitive;
+ tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple;
+ tnl->Driver.Render.BuildVertices = r128BuildVertices;
+ rmesa->NewGLState |= (_R128_NEW_RENDER_STATE|
+ _R128_NEW_VERTEX_STATE);
+
+/* r128Fallback( ctx, 0x100000, 1 ); */
+}
diff --git a/src/mesa/drivers/dri/r128/r128_tris.h b/src/mesa/drivers/dri/r128/r128_tris.h
new file mode 100644
index 0000000000..755d3320b0
--- /dev/null
+++ b/src/mesa/drivers/dri/r128/r128_tris.h
@@ -0,0 +1,48 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_tris.h,v 1.8 2002/10/30 12:51:43 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>
+ *
+ */
+
+#ifndef __R128_TRIS_H__
+#define __R128_TRIS_H__
+
+#include "mtypes.h"
+
+extern void r128InitTriFuncs( GLcontext *ctx );
+
+
+extern void r128Fallback( GLcontext *ctx, GLuint bit, GLboolean mode );
+#define FALLBACK( rmesa, bit, mode ) r128Fallback( rmesa->glCtx, bit, mode )
+
+
+#endif /* __R128_TRIS_H__ */
diff --git a/src/mesa/drivers/dri/r128/r128_vb.c b/src/mesa/drivers/dri/r128/r128_vb.c
new file mode 100644
index 0000000000..7738901648
--- /dev/null
+++ b/src/mesa/drivers/dri/r128/r128_vb.c
@@ -0,0 +1,522 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_vb.c,v 1.15 2002/10/30 12:51:43 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>
+ *
+ */
+
+#include "glheader.h"
+#include "mtypes.h"
+#include "imports.h"
+#include "macros.h"
+#include "colormac.h"
+
+#include "swrast_setup/swrast_setup.h"
+#include "tnl/t_context.h"
+
+#include "r128_context.h"
+#include "r128_vb.h"
+#include "r128_ioctl.h"
+#include "r128_tris.h"
+#include "r128_state.h"
+
+
+#define R128_TEX1_BIT 0x1
+#define R128_TEX0_BIT 0x2
+#define R128_RGBA_BIT 0x4
+#define R128_SPEC_BIT 0x8
+#define R128_FOG_BIT 0x10
+#define R128_XYZW_BIT 0x20
+#define R128_PTEX_BIT 0x40
+#define R128_MAX_SETUP 0x80
+
+static struct {
+ void (*emit)( GLcontext *, GLuint, GLuint, void *, GLuint );
+ interp_func interp;
+ copy_pv_func copy_pv;
+ GLboolean (*check_tex_sizes)( GLcontext *ctx );
+ GLuint vertex_size;
+ GLuint vertex_stride_shift;
+ GLuint vertex_format;
+} setup_tab[R128_MAX_SETUP];
+
+#define TINY_VERTEX_FORMAT (R128_CCE_VC_FRMT_DIFFUSE_ARGB)
+
+#define NOTEX_VERTEX_FORMAT (R128_CCE_VC_FRMT_RHW | \
+ R128_CCE_VC_FRMT_DIFFUSE_ARGB |\
+ R128_CCE_VC_FRMT_SPEC_FRGB)
+
+#define TEX0_VERTEX_FORMAT (R128_CCE_VC_FRMT_RHW | \
+ R128_CCE_VC_FRMT_DIFFUSE_ARGB |\
+ R128_CCE_VC_FRMT_SPEC_FRGB | \
+ R128_CCE_VC_FRMT_S_T)
+
+#define TEX1_VERTEX_FORMAT (R128_CCE_VC_FRMT_RHW | \
+ R128_CCE_VC_FRMT_DIFFUSE_ARGB |\
+ R128_CCE_VC_FRMT_SPEC_FRGB | \
+ R128_CCE_VC_FRMT_S_T | \
+ R128_CCE_VC_FRMT_S2_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 & R128_XYZW_BIT)
+#define DO_RGBA (IND & R128_RGBA_BIT)
+#define DO_SPEC (IND & R128_SPEC_BIT)
+#define DO_FOG (IND & R128_FOG_BIT)
+#define DO_TEX0 (IND & R128_TEX0_BIT)
+#define DO_TEX1 (IND & R128_TEX1_BIT)
+#define DO_TEX2 0
+#define DO_TEX3 0
+#define DO_PTEX (IND & R128_PTEX_BIT)
+
+#define VERTEX r128Vertex
+#define VERTEX_COLOR r128_color_t
+#define LOCALVARS r128ContextPtr rmesa = R128_CONTEXT(ctx);
+#define GET_VIEWPORT_MAT() rmesa->hw_viewport
+#define GET_TEXSOURCE(n) rmesa->tmu_source[n]
+#define GET_VERTEX_FORMAT() rmesa->vertex_format
+#define GET_VERTEX_STORE() rmesa->verts
+#define GET_VERTEX_STRIDE_SHIFT() rmesa->vertex_stride_shift
+#define INVALIDATE_STORED_VERTICES()
+#define GET_UBYTE_COLOR_STORE() &rmesa->UbyteColor
+#define GET_UBYTE_SPEC_COLOR_STORE() &rmesa->UbyteSecondaryColor
+
+#define HAVE_HW_VIEWPORT 0
+#define HAVE_HW_DIVIDE 0
+#define HAVE_RGBA_COLOR 0
+#define HAVE_TINY_VERTICES 1
+#define HAVE_NOTEX_VERTICES 1
+#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 /* r128 rhw2 not supported by template */
+
+#define UNVIEWPORT_VARS GLfloat h = R128_CONTEXT(ctx)->driDrawable->h
+#define UNVIEWPORT_X(x) x - SUBPIXEL_X
+#define UNVIEWPORT_Y(y) - y + h + SUBPIXEL_Y
+#define UNVIEWPORT_Z(z) z / rmesa->depth_scale
+
+#define PTEX_FALLBACK() FALLBACK(R128_CONTEXT(ctx), R128_FALLBACK_TEXTURE, 1)
+
+#define IMPORT_FLOAT_COLORS r128_import_float_colors
+#define IMPORT_FLOAT_SPEC_COLORS r128_import_float_spec_colors
+
+#define INTERP_VERTEX setup_tab[rmesa->SetupIndex].interp
+#define COPY_PV_VERTEX setup_tab[rmesa->SetupIndex].copy_pv
+
+/***********************************************************************
+ * Generate pv-copying and translation functions *
+ ***********************************************************************/
+
+#define TAG(x) r128_##x
+#include "tnl_dd/t_dd_vb.c"
+
+/***********************************************************************
+ * Generate vertex emit and interp functions *
+ ***********************************************************************/
+
+
+#define IND (R128_XYZW_BIT|R128_RGBA_BIT)
+#define TAG(x) x##_wg
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_SPEC_BIT)
+#define TAG(x) x##_wgs
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_TEX0_BIT)
+#define TAG(x) x##_wgt0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_TEX0_BIT|R128_TEX1_BIT)
+#define TAG(x) x##_wgt0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_TEX0_BIT|R128_PTEX_BIT)
+#define TAG(x) x##_wgpt0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_SPEC_BIT|R128_TEX0_BIT)
+#define TAG(x) x##_wgst0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_SPEC_BIT|R128_TEX0_BIT|\
+ R128_TEX1_BIT)
+#define TAG(x) x##_wgst0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_SPEC_BIT|R128_TEX0_BIT|\
+ R128_PTEX_BIT)
+#define TAG(x) x##_wgspt0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_FOG_BIT)
+#define TAG(x) x##_wgf
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT)
+#define TAG(x) x##_wgfs
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_TEX0_BIT)
+#define TAG(x) x##_wgft0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_TEX0_BIT|\
+ R128_TEX1_BIT)
+#define TAG(x) x##_wgft0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_TEX0_BIT|\
+ R128_PTEX_BIT)
+#define TAG(x) x##_wgfpt0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT|\
+ R128_TEX0_BIT)
+#define TAG(x) x##_wgfst0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT|\
+ R128_TEX0_BIT|R128_TEX1_BIT)
+#define TAG(x) x##_wgfst0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT|\
+ R128_TEX0_BIT|R128_PTEX_BIT)
+#define TAG(x) x##_wgfspt0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_TEX0_BIT)
+#define TAG(x) x##_t0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_TEX0_BIT|R128_TEX1_BIT)
+#define TAG(x) x##_t0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_FOG_BIT)
+#define TAG(x) x##_f
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_FOG_BIT|R128_TEX0_BIT)
+#define TAG(x) x##_ft0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_FOG_BIT|R128_TEX0_BIT|R128_TEX1_BIT)
+#define TAG(x) x##_ft0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_RGBA_BIT)
+#define TAG(x) x##_g
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_RGBA_BIT|R128_SPEC_BIT)
+#define TAG(x) x##_gs
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_RGBA_BIT|R128_TEX0_BIT)
+#define TAG(x) x##_gt0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_RGBA_BIT|R128_TEX0_BIT|R128_TEX1_BIT)
+#define TAG(x) x##_gt0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_RGBA_BIT|R128_SPEC_BIT|R128_TEX0_BIT)
+#define TAG(x) x##_gst0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_RGBA_BIT|R128_SPEC_BIT|R128_TEX0_BIT|R128_TEX1_BIT)
+#define TAG(x) x##_gst0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_RGBA_BIT|R128_FOG_BIT)
+#define TAG(x) x##_gf
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT)
+#define TAG(x) x##_gfs
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_RGBA_BIT|R128_FOG_BIT|R128_TEX0_BIT)
+#define TAG(x) x##_gft0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_RGBA_BIT|R128_FOG_BIT|R128_TEX0_BIT|R128_TEX1_BIT)
+#define TAG(x) x##_gft0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT|R128_TEX0_BIT)
+#define TAG(x) x##_gfst0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT|R128_TEX0_BIT|\
+ R128_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 r128PrintSetupFlags(char *msg, GLuint flags )
+{
+ fprintf(stderr, "%s(%x): %s%s%s%s%s%s\n",
+ msg,
+ (int)flags,
+ (flags & R128_XYZW_BIT) ? " xyzw," : "",
+ (flags & R128_RGBA_BIT) ? " rgba," : "",
+ (flags & R128_SPEC_BIT) ? " spec," : "",
+ (flags & R128_FOG_BIT) ? " fog," : "",
+ (flags & R128_TEX0_BIT) ? " tex-0," : "",
+ (flags & R128_TEX1_BIT) ? " tex-1," : "");
+}
+
+
+
+void r128CheckTexSizes( GLcontext *ctx )
+{
+ r128ContextPtr rmesa = R128_CONTEXT( ctx );
+
+ if (!setup_tab[rmesa->SetupIndex].check_tex_sizes(ctx)) {
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+ /* Invalidate stored verts
+ */
+ rmesa->SetupNewInputs = ~0;
+ rmesa->SetupIndex |= R128_PTEX_BIT;
+
+ if (!rmesa->Fallback &&
+ !(ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
+ tnl->Driver.Render.Interp = setup_tab[rmesa->SetupIndex].interp;
+ tnl->Driver.Render.CopyPV = setup_tab[rmesa->SetupIndex].copy_pv;
+ }
+ }
+}
+
+void r128BuildVertices( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint newinputs )
+{
+ r128ContextPtr rmesa = R128_CONTEXT( ctx );
+ GLubyte *v = ((GLubyte *)rmesa->verts + (start<<rmesa->vertex_stride_shift));
+ GLuint stride = 1<<rmesa->vertex_stride_shift;
+
+ newinputs |= rmesa->SetupNewInputs;
+ rmesa->SetupNewInputs = 0;
+
+ if (!newinputs)
+ return;
+
+ if (newinputs & VERT_BIT_CLIP) {
+ setup_tab[rmesa->SetupIndex].emit( ctx, start, count, v, stride );
+ } else {
+ GLuint ind = 0;
+
+ if (newinputs & VERT_BIT_COLOR0)
+ ind |= R128_RGBA_BIT;
+
+ if (newinputs & VERT_BIT_COLOR1)
+ ind |= R128_SPEC_BIT;
+
+ if (newinputs & VERT_BIT_TEX0)
+ ind |= R128_TEX0_BIT;
+
+ if (newinputs & VERT_BIT_TEX1)
+ ind |= R128_TEX1_BIT;
+
+ if (newinputs & VERT_BIT_FOG)
+ ind |= R128_FOG_BIT;
+
+ if (rmesa->SetupIndex & R128_PTEX_BIT)
+ ind = ~0;
+
+ ind &= rmesa->SetupIndex;
+
+ if (ind) {
+ setup_tab[ind].emit( ctx, start, count, v, stride );
+ }
+ }
+}
+
+void r128ChooseVertexState( GLcontext *ctx )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ r128ContextPtr rmesa = R128_CONTEXT( ctx );
+ GLuint ind = R128_XYZW_BIT|R128_RGBA_BIT;
+
+ if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)
+ ind |= R128_SPEC_BIT;
+
+ if (ctx->Fog.Enabled)
+ ind |= R128_FOG_BIT;
+
+ if (ctx->Texture._EnabledUnits) {
+ ind |= R128_TEX0_BIT;
+ if (ctx->Texture.Unit[0]._ReallyEnabled &&
+ ctx->Texture.Unit[1]._ReallyEnabled)
+ ind |= R128_TEX1_BIT;
+ }
+
+ rmesa->SetupIndex = ind;
+
+ if (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED)) {
+ tnl->Driver.Render.Interp = r128_interp_extras;
+ tnl->Driver.Render.CopyPV = r128_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 != rmesa->vertex_format) {
+ FLUSH_BATCH(rmesa);
+ rmesa->vertex_format = setup_tab[ind].vertex_format;
+ rmesa->vertex_size = setup_tab[ind].vertex_size;
+ rmesa->vertex_stride_shift = setup_tab[ind].vertex_stride_shift;
+ }
+}
+
+
+
+void r128_emit_contiguous_verts( GLcontext *ctx,
+ GLuint start,
+ GLuint count )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+ GLuint vertex_size = rmesa->vertex_size * 4;
+ GLuint *dest = r128AllocDmaLow( rmesa, (count-start) * vertex_size);
+ setup_tab[rmesa->SetupIndex].emit( ctx, start, count, dest, vertex_size );
+}
+
+
+#if 0
+void r128_emit_indexed_verts( GLcontext *ctx, GLuint start, GLuint count )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+ GLuint vertex_size = rmesa->vertex_size * 4;
+ GLuint bufsz = (count-start) * vertex_size;
+ CARD32 *dest;
+
+ rmesa->vertex_low = (rmesa->vertex_low + 63) & ~63; /* alignment */
+ rmesa->vertex_last_prim = rmesa->vertex_low;
+
+ dest = r128AllocDmaLow( rmesa, bufsz, __FUNCTION__);
+ setup_tab[rmesa->SetupIndex].emit( ctx, start, count, dest, vertex_size );
+
+ rmesa->retained_buffer = rmesa->vertex_buffer;
+ rmesa->vb_offset = (rmesa->vertex_buffer->idx * R128_BUFFER_SIZE +
+ rmesa->vertex_low - bufsz);
+
+ rmesa->vertex_low = (rmesa->vertex_low + 0x7) & ~0x7; /* alignment */
+ rmesa->vertex_last_prim = rmesa->vertex_low;
+}
+#endif
+
+
+void r128InitVB( GLcontext *ctx )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+ GLuint size = TNL_CONTEXT(ctx)->vb.Size;
+
+ rmesa->verts = ALIGN_MALLOC(size * 4 * 16, 32);
+
+ {
+ static int firsttime = 1;
+ if (firsttime) {
+ init_setup_tab();
+ firsttime = 0;
+ }
+ }
+}
+
+
+void r128FreeVB( GLcontext *ctx )
+{
+ r128ContextPtr rmesa = R128_CONTEXT(ctx);
+ if (rmesa->verts) {
+ ALIGN_FREE(rmesa->verts);
+ rmesa->verts = 0;
+ }
+
+
+ if (rmesa->UbyteSecondaryColor.Ptr) {
+ ALIGN_FREE(rmesa->UbyteSecondaryColor.Ptr);
+ rmesa->UbyteSecondaryColor.Ptr = 0;
+ }
+
+ if (rmesa->UbyteColor.Ptr) {
+ ALIGN_FREE(rmesa->UbyteColor.Ptr);
+ rmesa->UbyteColor.Ptr = 0;
+ }
+}
diff --git a/src/mesa/drivers/dri/r128/r128_vb.h b/src/mesa/drivers/dri/r128/r128_vb.h
new file mode 100644
index 0000000000..31afa74f1c
--- /dev/null
+++ b/src/mesa/drivers/dri/r128/r128_vb.h
@@ -0,0 +1,74 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_vb.h,v 1.8 2002/10/30 12:51:46 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>
+ *
+ */
+
+#ifndef R128VB_INC
+#define R128VB_INC
+
+#include "mtypes.h"
+#include "swrast/swrast.h"
+#include "r128_context.h"
+
+#define _R128_NEW_VERTEX_STATE (_DD_NEW_SEPARATE_SPECULAR | \
+ _DD_NEW_TRI_LIGHT_TWOSIDE | \
+ _DD_NEW_TRI_UNFILLED | \
+ _NEW_TEXTURE | \
+ _NEW_FOG)
+
+extern void r128CheckTexSizes( GLcontext *ctx );
+extern void r128ChooseVertexState( GLcontext *ctx );
+
+extern void r128BuildVertices( GLcontext *ctx, GLuint start, GLuint count,
+ GLuint newinputs );
+
+extern void r128PrintSetupFlags(char *msg, GLuint flags );
+
+extern void r128InitVB( GLcontext *ctx );
+extern void r128FreeVB( GLcontext *ctx );
+
+extern void r128_emit_contiguous_verts( GLcontext *ctx,
+ GLuint start,
+ GLuint count );
+
+extern void r128_emit_indexed_verts( GLcontext *ctx,
+ GLuint start,
+ GLuint count );
+
+extern void r128_translate_vertex( GLcontext *ctx,
+ const r128Vertex *src,
+ SWvertex *dst );
+
+extern void r128_print_vertex( GLcontext *ctx, const r128Vertex *v );
+
+#endif
diff --git a/src/mesa/drivers/dri/r128/server/r128.h b/src/mesa/drivers/dri/r128/server/r128.h
new file mode 100644
index 0000000000..fba01d6d60
--- /dev/null
+++ b/src/mesa/drivers/dri/r128/server/r128.h
@@ -0,0 +1,566 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128.h,v 1.24 2002/12/16 16:19:10 dawes Exp $ */
+/*
+ * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario,
+ * Precision Insight, Inc., Cedar Park, Texas, 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, 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
+ * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, PRECISION INSIGHT, 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:
+ * Rickard E. Faith <faith@valinux.com>
+ * Kevin E. Martin <martin@valinux.com>
+ *
+ */
+
+#ifndef _R128_H_
+#define _R128_H_
+
+#include "dri_util.h"
+#ifndef _SOLO
+#include "xf86str.h"
+
+ /* PCI support */
+#include "xf86Pci.h"
+
+ /* XAA and Cursor Support */
+#include "xaa.h"
+#include "xf86Cursor.h"
+
+ /* DDC support */
+#include "xf86DDC.h"
+
+ /* Xv support */
+#include "xf86xv.h"
+
+ /* DRI support */
+#ifdef XF86DRI
+#define _XF86DRI_SERVER_
+#include "r128_dripriv.h"
+#include "dri.h"
+#include "GL/glxint.h"
+#endif
+#endif
+#ifdef _SOLO
+#define XF86DRI
+#endif
+
+#define R128_DEBUG 0 /* Turn off debugging output */
+#define R128_IDLE_RETRY 32 /* Fall out of idle loops after this count */
+#define R128_TIMEOUT 2000000 /* Fall out of wait loops after this count */
+#define R128_MMIOSIZE 0x4000
+
+#define R128_VBIOS_SIZE 0x00010000
+
+#if R128_DEBUG
+#define R128TRACE(x) \
+ do { \
+ ErrorF("(**) %s(%d): ", R128_NAME, pScrn->scrnIndex); \
+ ErrorF x; \
+ } while (0);
+#else
+#define R128TRACE(x)
+#endif
+
+
+/* Other macros */
+#define R128_ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
+#define R128_ALIGN(x,bytes) (((x) + ((bytes) - 1)) & ~((bytes) - 1))
+#define R128PTR(pScrn) ((R128InfoPtr)(pScrn)->driverPrivate)
+
+/**
+ * \brief Chip families.
+ */
+typedef enum {
+ CHIP_FAMILY_UNKNOWN,
+ CHIP_FAMILY_R128_PCI,
+ CHIP_FAMILY_R128_AGP,
+} R128ChipFamily;
+
+typedef struct { /* All values in XCLKS */
+ int ML; /* Memory Read Latency */
+ int MB; /* Memory Burst Length */
+ int Trcd; /* RAS to CAS delay */
+ int Trp; /* RAS percentage */
+ int Twr; /* Write Recovery */
+ int CL; /* CAS Latency */
+ int Tr2w; /* Read to Write Delay */
+ int Rloop; /* Loop Latency */
+ int Rloop_fudge; /* Add to ML to get Rloop */
+ char *name;
+} R128RAMRec, *R128RAMPtr;
+
+typedef struct {
+ /* Common registers */
+ CARD32 ovr_clr;
+ CARD32 ovr_wid_left_right;
+ CARD32 ovr_wid_top_bottom;
+ CARD32 ov0_scale_cntl;
+ CARD32 mpp_tb_config;
+ CARD32 mpp_gp_config;
+ CARD32 subpic_cntl;
+ CARD32 viph_control;
+ CARD32 i2c_cntl_1;
+ CARD32 gen_int_cntl;
+ CARD32 cap0_trig_cntl;
+ CARD32 cap1_trig_cntl;
+ CARD32 bus_cntl;
+ CARD32 config_cntl;
+
+ /* Other registers to save for VT switches */
+ CARD32 dp_datatype;
+ CARD32 gen_reset_cntl;
+ CARD32 clock_cntl_index;
+ CARD32 amcgpio_en_reg;
+ CARD32 amcgpio_mask;
+
+ /* CRTC registers */
+ CARD32 crtc_gen_cntl;
+ CARD32 crtc_ext_cntl;
+ CARD32 dac_cntl;
+ CARD32 crtc_h_total_disp;
+ CARD32 crtc_h_sync_strt_wid;
+ CARD32 crtc_v_total_disp;
+ CARD32 crtc_v_sync_strt_wid;
+ CARD32 crtc_offset;
+ CARD32 crtc_offset_cntl;
+ CARD32 crtc_pitch;
+
+ /* CRTC2 registers */
+ CARD32 crtc2_gen_cntl;
+
+ /* Flat panel registers */
+ CARD32 fp_crtc_h_total_disp;
+ CARD32 fp_crtc_v_total_disp;
+ CARD32 fp_gen_cntl;
+ CARD32 fp_h_sync_strt_wid;
+ CARD32 fp_horz_stretch;
+ CARD32 fp_panel_cntl;
+ CARD32 fp_v_sync_strt_wid;
+ CARD32 fp_vert_stretch;
+ CARD32 lvds_gen_cntl;
+ CARD32 tmds_crc;
+ CARD32 tmds_transmitter_cntl;
+
+ /* Computed values for PLL */
+ CARD32 dot_clock_freq;
+ CARD32 pll_output_freq;
+ int feedback_div;
+ int post_div;
+
+ /* PLL registers */
+ CARD32 ppll_ref_div;
+ CARD32 ppll_div_3;
+ CARD32 htotal_cntl;
+
+ /* DDA register */
+ CARD32 dda_config;
+ CARD32 dda_on_off;
+
+ /* Pallet */
+ GLboolean palette_valid;
+ CARD32 palette[256];
+} R128SaveRec, *R128SavePtr;
+
+#ifndef _SOLO
+typedef struct {
+ CARD16 reference_freq;
+ CARD16 reference_div;
+ CARD32 min_pll_freq;
+ CARD32 max_pll_freq;
+ CARD16 xclk;
+} R128PLLRec, *R128PLLPtr;
+
+typedef struct {
+ int bitsPerPixel;
+ int depth;
+ int displayWidth;
+ int pixel_code;
+ int pixel_bytes;
+ DisplayModePtr mode;
+} R128FBLayout;
+#endif
+
+typedef struct {
+#ifndef _SOLO
+ EntityInfoPtr pEnt;
+ pciVideoPtr PciInfo;
+ PCITAG PciTag;
+#endif
+ int Chipset;
+ GLboolean Primary;
+
+ GLboolean FBDev;
+
+ unsigned long LinearAddr; /* Frame buffer physical address */
+ unsigned long BIOSAddr; /* BIOS physical address */
+
+ unsigned char *MMIO; /* Map of MMIO region */
+ unsigned char *FB; /* Map of frame buffer */
+
+ CARD32 MemCntl;
+ CARD32 BusCntl;
+ unsigned long FbMapSize; /* Size of frame buffer, in bytes */
+ int Flags; /* Saved copy of mode flags */
+
+#ifndef _SOLO
+ CARD8 BIOSDisplay; /* Device the BIOS is set to display to */
+
+ GLboolean HasPanelRegs; /* Current chip can connect to a FP */
+ CARD8 *VBIOS; /* Video BIOS for mode validation on FPs */
+ int FPBIOSstart; /* Start of the flat panel info */
+#endif
+ /* Computed values for FPs */
+ int PanelXRes;
+ int PanelYRes;
+ int HOverPlus;
+ int HSyncWidth;
+ int HBlank;
+ int VOverPlus;
+ int VSyncWidth;
+ int VBlank;
+ int PanelPwrDly;
+#ifndef _SOLO
+ R128PLLRec pll;
+ R128RAMPtr ram;
+
+ R128SaveRec SavedReg; /* Original (text) mode */
+ R128SaveRec ModeReg; /* Current mode */
+ GLboolean (*CloseScreen)(int, ScreenPtr);
+ void (*BlockHandler)(int, pointer, pointer, pointer);
+
+ GLboolean PaletteSavedOnVT; /* Palette saved on last VT switch */
+
+ XAAInfoRecPtr accel;
+ GLboolean accelOn;
+ xf86CursorInfoPtr cursor;
+#endif
+ unsigned long cursor_start;
+ unsigned long cursor_end;
+
+ /*
+ * XAAForceTransBlit is used to change the behavior of the XAA
+ * SetupForScreenToScreenCopy function, to make it DGA-friendly.
+ */
+ GLboolean XAAForceTransBlit;
+
+ int fifo_slots; /* Free slots in the FIFO (64 max) */
+ int pix24bpp; /* Depth of pixmap for 24bpp framebuffer */
+ GLboolean dac6bits; /* Use 6 bit DAC? */
+
+ /* Computed values for Rage 128 */
+ int pitch;
+ int datatype;
+ CARD32 dp_gui_master_cntl;
+
+ /* Saved values for ScreenToScreenCopy */
+ int xdir;
+ int ydir;
+
+ /* ScanlineScreenToScreenColorExpand support */
+ unsigned char *scratch_buffer[1];
+ unsigned char *scratch_save;
+ int scanline_x;
+ int scanline_y;
+ int scanline_w;
+ int scanline_h;
+#ifdef XF86DRI
+ int scanline_hpass;
+ int scanline_x1clip;
+ int scanline_x2clip;
+ int scanline_rop;
+ int scanline_fg;
+ int scanline_bg;
+#endif /* XF86DRI */
+ int scanline_words;
+ int scanline_direct;
+ int scanline_bpp; /* Only used for ImageWrite */
+
+#ifndef _SOLO
+ DGAModePtr DGAModes;
+ int numDGAModes;
+ GLboolean DGAactive;
+ int DGAViewportStatus;
+ DGAFunctionRec DGAFuncs;
+
+ R128FBLayout CurrentLayout;
+#endif
+#ifdef XF86DRI
+ drmContext drmCtx;
+#ifndef _SOLO
+ DRIInfoPtr pDRIInfo;
+ int numVisualConfigs;
+ __GLXvisualConfig *pVisualConfigs;
+ R128ConfigPrivPtr pVisualConfigsPriv;
+#endif
+
+ drmSize registerSize;
+ drmHandle registerHandle;
+
+ GLboolean IsPCI; /* Current card is a PCI card */
+ drmSize pciSize;
+ drmHandle pciMemHandle;
+ unsigned char *PCI; /* Map */
+
+ GLboolean allowPageFlip; /* Enable 3d page flipping */
+ GLboolean have3DWindows; /* Are there any 3d clients? */
+ int drmMinor;
+
+ drmSize agpSize;
+ drmHandle agpMemHandle; /* Handle from drmAgpAlloc */
+ unsigned long agpOffset;
+ unsigned char *AGP; /* Map */
+ int agpMode;
+
+ GLboolean CCEInUse; /* CCE is currently active */
+ int CCEMode; /* CCE mode that server/clients use */
+ int CCEFifoSize; /* Size of the CCE command FIFO */
+ GLboolean CCESecure; /* CCE security enabled */
+ int CCEusecTimeout; /* CCE timeout in usecs */
+
+ /* CCE ring buffer data */
+ unsigned long ringStart; /* Offset into AGP space */
+ drmHandle ringHandle; /* Handle from drmAddMap */
+ drmSize ringMapSize; /* Size of map */
+ int ringSize; /* Size of ring (in MB) */
+ unsigned char *ring; /* Map */
+ int ringSizeLog2QW;
+
+ unsigned long ringReadOffset; /* Offset into AGP space */
+ drmHandle ringReadPtrHandle; /* Handle from drmAddMap */
+ drmSize ringReadMapSize; /* Size of map */
+ unsigned char *ringReadPtr; /* Map */
+
+ /* CCE vertex/indirect buffer data */
+ unsigned long bufStart; /* Offset into AGP space */
+ drmHandle bufHandle; /* Handle from drmAddMap */
+ drmSize bufMapSize; /* Size of map */
+ int bufSize; /* Size of buffers (in MB) */
+ unsigned char *buf; /* Map */
+ int bufNumBufs; /* Number of buffers */
+ drmBufMapPtr buffers; /* Buffer map */
+
+ /* CCE AGP Texture data */
+ unsigned long agpTexStart; /* Offset into AGP space */
+ drmHandle agpTexHandle; /* Handle from drmAddMap */
+ drmSize agpTexMapSize; /* Size of map */
+ int agpTexSize; /* Size of AGP tex space (in MB) */
+ unsigned char *agpTex; /* Map */
+ int log2AGPTexGran;
+
+ /* CCE 2D accleration */
+ drmBufPtr indirectBuffer;
+ int indirectStart;
+
+ /* DRI screen private data */
+ int fbX;
+ int fbY;
+ int backX;
+ int backY;
+ int depthX;
+ int depthY;
+
+ int frontOffset;
+ int frontPitch;
+ int backOffset;
+ int backPitch;
+ int depthOffset;
+ int depthPitch;
+ int spanOffset;
+ int textureOffset;
+ int textureSize;
+ int log2TexGran;
+
+ /* Saved scissor values */
+ CARD32 sc_left;
+ CARD32 sc_right;
+ CARD32 sc_top;
+ CARD32 sc_bottom;
+
+ CARD32 re_top_left;
+ CARD32 re_width_height;
+
+ CARD32 aux_sc_cntl;
+
+ int irq;
+ CARD32 gen_int_cntl;
+
+ GLboolean DMAForXv;
+#endif
+
+#ifndef _SOLO
+ XF86VideoAdaptorPtr adaptor;
+ void (*VideoTimerCallback)(ScrnInfoPtr, Time);
+ int videoKey;
+ GLboolean showCache;
+ OptionInfoPtr Options;
+
+ GLboolean isDFP;
+ GLboolean isPro2;
+ I2CBusPtr pI2CBus;
+ CARD32 DDCReg;
+#endif
+} R128InfoRec, *R128InfoPtr;
+
+#define R128WaitForFifo(pScrn, entries) \
+do { \
+ if (info->fifo_slots < entries) R128WaitForFifoFunction(pScrn, entries); \
+ info->fifo_slots -= entries; \
+} while (0)
+
+extern void r128WaitForFifoFunction(const DRIDriverContext *ctx, int entries);
+extern void r128WaitForIdle(const DRIDriverContext *ctx);
+
+extern void r128WaitForVerticalSync(const DRIDriverContext *ctx);
+
+extern GLboolean r128AccelInit(const DRIDriverContext *ctx);
+extern void r128EngineInit(const DRIDriverContext *ctx);
+extern GLboolean r128CursorInit(const DRIDriverContext *ctx);
+extern GLboolean r128DGAInit(const DRIDriverContext *ctx);
+
+extern void r128InitVideo(const DRIDriverContext *ctx);
+
+extern GLboolean r128DRIScreenInit(const DRIDriverContext *ctx);
+extern void r128DRICloseScreen(const DRIDriverContext *ctx);
+extern GLboolean r128DRIFinishScreenInit(const DRIDriverContext *ctx);
+
+#define R128CCE_START(ctx, info) \
+do { \
+ int _ret = drmCommandNone(ctx->drmFD, DRM_R128_CCE_START); \
+ if (_ret) { \
+ fprintf(stderr, \
+ "%s: CCE start %d\n", __FUNCTION__, _ret); \
+ } \
+} while (0)
+
+#define R128CCE_STOP(ctx, info) \
+do { \
+ int _ret = R128CCEStop(ctx); \
+ if (_ret) { \
+ fprintf(stderr, \
+ "%s: CCE stop %d\n", __FUNCTION__, _ret); \
+ } \
+} while (0)
+
+#define R128CCE_RESET(ctx, info) \
+do { \
+ if (info->directRenderingEnabled \
+ && R128CCE_USE_RING_BUFFER(info->CCEMode)) { \
+ int _ret = drmCommandNone(info->drmFD, DRM_R128_CCE_RESET); \
+ if (_ret) { \
+ fprintf(stderr, \
+ "%s: CCE reset %d\n", __FUNCTION__, _ret); \
+ } \
+ } \
+} while (0)
+
+
+#define CCE_PACKET0( reg, n ) \
+ (R128_CCE_PACKET0 | ((n) << 16) | ((reg) >> 2))
+#define CCE_PACKET1( reg0, reg1 ) \
+ (R128_CCE_PACKET1 | (((reg1) >> 2) << 11) | ((reg0) >> 2))
+#define CCE_PACKET2() \
+ (R128_CCE_PACKET2)
+#define CCE_PACKET3( pkt, n ) \
+ (R128_CCE_PACKET3 | (pkt) | ((n) << 16))
+
+
+#define R128_VERBOSE 0
+
+#define RING_LOCALS CARD32 *__head; int __count;
+
+#define R128CCE_REFRESH(pScrn, info) \
+do { \
+ if ( R128_VERBOSE ) { \
+ fprintf(stderr, "REFRESH( %d ) in %s\n", \
+ !info->CCEInUse , __FUNCTION__ ); \
+ } \
+ if ( !info->CCEInUse ) { \
+ R128CCEWaitForIdle(pScrn); \
+ BEGIN_RING( 6 ); \
+ OUT_RING_REG( R128_RE_TOP_LEFT, info->re_top_left ); \
+ OUT_RING_REG( R128_RE_WIDTH_HEIGHT, info->re_width_height ); \
+ OUT_RING_REG( R128_AUX_SC_CNTL, info->aux_sc_cntl ); \
+ ADVANCE_RING(); \
+ info->CCEInUse = TRUE; \
+ } \
+} while (0)
+
+#define BEGIN_RING( n ) do { \
+ if ( R128_VERBOSE ) { \
+ fprintf(stderr, \
+ "BEGIN_RING( %d ) in %s\n", n, __FUNCTION__ ); \
+ } \
+ if ( !info->indirectBuffer ) { \
+ info->indirectBuffer = R128CCEGetBuffer( pScrn ); \
+ info->indirectStart = 0; \
+ } else if ( (info->indirectBuffer->used + 4*(n)) > \
+ info->indirectBuffer->total ) { \
+ R128CCEFlushIndirect( pScrn, 1 ); \
+ } \
+ __head = (pointer)((char *)info->indirectBuffer->address + \
+ info->indirectBuffer->used); \
+ __count = 0; \
+} while (0)
+
+#define ADVANCE_RING() do { \
+ if ( R128_VERBOSE ) { \
+ fprintf(stderr, \
+ "ADVANCE_RING() used: %d+%d=%d/%d\n", \
+ info->indirectBuffer->used - info->indirectStart, \
+ __count * sizeof(CARD32), \
+ info->indirectBuffer->used - info->indirectStart + \
+ __count * sizeof(CARD32), \
+ info->indirectBuffer->total - info->indirectStart ); \
+ } \
+ info->indirectBuffer->used += __count * (int)sizeof(CARD32); \
+} while (0)
+
+#define OUT_RING( x ) do { \
+ if ( R128_VERBOSE ) { \
+ fprintf(stderr, \
+ " OUT_RING( 0x%08x )\n", (unsigned int)(x) ); \
+ } \
+ MMIO_OUT32(&__head[__count++], 0, (x)); \
+} while (0)
+
+#define OUT_RING_REG( reg, val ) \
+do { \
+ OUT_RING( CCE_PACKET0( reg, 0 ) ); \
+ OUT_RING( val ); \
+} while (0)
+
+#define FLUSH_RING() \
+do { \
+ if ( R128_VERBOSE ) \
+ fprintf(stderr, \
+ "FLUSH_RING in %s\n", __FUNCTION__ ); \
+ if ( info->indirectBuffer ) { \
+ R128CCEFlushIndirect( pScrn, 0 ); \
+ } \
+} while (0)
+
+
+#endif
diff --git a/src/mesa/drivers/dri/r128/server/r128_common.h b/src/mesa/drivers/dri/r128/server/r128_common.h
new file mode 100644
index 0000000000..fa81360ea5
--- /dev/null
+++ b/src/mesa/drivers/dri/r128/server/r128_common.h
@@ -0,0 +1,169 @@
+/* r128_common.h -- common header definitions for R128 2D/3D/DRM suite
+ * Created: Sun Apr 9 18:16:28 2000 by kevin@precisioninsight.com
+ *
+ * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Author:
+ * Gareth Hughes <gareth@valinux.com>
+ * Kevin E. Martin <martin@valinux.com>
+ *
+ * Converted to common header format:
+ * Jens Owen <jens@tungstengraphics.com>
+ *
+ * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/xf86drmR128.h,v 3.11 2001/04/16 15:02:13 tsi Exp $
+ *
+ */
+
+#ifndef _R128_COMMON_H_
+#define _R128_COMMON_H_
+
+/*
+ * WARNING: If you change any of these defines, make sure to change
+ * the kernel include file as well (r128_drm.h)
+ */
+
+/* Driver specific DRM command indices
+ * NOTE: these are not OS specific, but they are driver specific
+ */
+#define DRM_R128_INIT 0x00
+#define DRM_R128_CCE_START 0x01
+#define DRM_R128_CCE_STOP 0x02
+#define DRM_R128_CCE_RESET 0x03
+#define DRM_R128_CCE_IDLE 0x04
+#define DRM_R128_UNDEFINED1 0x05
+#define DRM_R128_RESET 0x06
+#define DRM_R128_SWAP 0x07
+#define DRM_R128_CLEAR 0x08
+#define DRM_R128_VERTEX 0x09
+#define DRM_R128_INDICES 0x0a
+#define DRM_R128_BLIT 0x0b
+#define DRM_R128_DEPTH 0x0c
+#define DRM_R128_STIPPLE 0x0d
+#define DRM_R128_UNDEFINED2 0x0e
+#define DRM_R128_INDIRECT 0x0f
+#define DRM_R128_FULLSCREEN 0x10
+#define DRM_R128_CLEAR2 0x11
+#define DRM_R128_GETPARAM 0x12
+#define DRM_R128_FLIP 0x13
+
+#define DRM_R128_FRONT_BUFFER 0x1
+#define DRM_R128_BACK_BUFFER 0x2
+#define DRM_R128_DEPTH_BUFFER 0x4
+
+typedef struct {
+ enum {
+ DRM_R128_INIT_CCE = 0x01,
+ DRM_R128_CLEANUP_CCE = 0x02
+ } func;
+ unsigned long sarea_priv_offset;
+ int is_pci;
+ int cce_mode;
+ int cce_secure; /* FIXME: Deprecated, we should remove this */
+ int ring_size;
+ int usec_timeout;
+
+ unsigned int fb_bpp;
+ unsigned int front_offset, front_pitch;
+ unsigned int back_offset, back_pitch;
+ unsigned int depth_bpp;
+ unsigned int depth_offset, depth_pitch;
+ unsigned int span_offset;
+
+ unsigned long fb_offset;
+ unsigned long mmio_offset;
+ unsigned long ring_offset;
+ unsigned long ring_rptr_offset;
+ unsigned long buffers_offset;
+ unsigned long agp_textures_offset;
+} drmR128Init;
+
+typedef struct {
+ int flush;
+ int idle;
+} drmR128CCEStop;
+
+typedef struct {
+ int idx;
+ int start;
+ int end;
+ int discard;
+} drmR128Indirect;
+
+typedef struct {
+ int idx;
+ int pitch;
+ int offset;
+ int format;
+ unsigned short x, y;
+ unsigned short width, height;
+} drmR128Blit;
+
+typedef struct {
+ enum {
+ DRM_R128_WRITE_SPAN = 0x01,
+ DRM_R128_WRITE_PIXELS = 0x02,
+ DRM_R128_READ_SPAN = 0x03,
+ DRM_R128_READ_PIXELS = 0x04
+ } func;
+ int n;
+ int *x;
+ int *y;
+ unsigned int *buffer;
+ unsigned char *mask;
+} drmR128Depth;
+
+typedef struct {
+ int prim;
+ int idx; /* Index of vertex buffer */
+ int count; /* Number of vertices in buffer */
+ int discard; /* Client finished with buffer? */
+} drmR128Vertex;
+
+typedef struct {
+ unsigned int *mask;
+} drmR128Stipple;
+
+typedef struct {
+ unsigned int flags;
+ unsigned int clear_color;
+ unsigned int clear_depth;
+ unsigned int color_mask;
+ unsigned int depth_mask;
+} drmR128Clear;
+
+typedef struct {
+ enum {
+ DRM_R128_INIT_FULLSCREEN = 0x01,
+ DRM_R128_CLEANUP_FULLSCREEN = 0x02
+ } func;
+} drmR128Fullscreen;
+
+typedef struct drm_r128_getparam {
+ int param;
+ void *value;
+} drmR128GetParam;
+
+#define R128_PARAM_IRQ_NR 1
+
+#endif
diff --git a/src/mesa/drivers/dri/r128/server/r128_dri.c b/src/mesa/drivers/dri/r128/server/r128_dri.c
new file mode 100644
index 0000000000..aa8f49f9c7
--- /dev/null
+++ b/src/mesa/drivers/dri/r128/server/r128_dri.c
@@ -0,0 +1,1165 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_dri.c,v 1.28 2003/02/07 20:41:14 martin Exp $ */
+/*
+ * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario,
+ * Precision Insight, Inc., Cedar Park, Texas, 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, 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
+ * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, PRECISION INSIGHT, 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:
+ * Kevin E. Martin <martin@valinux.com>
+ * Rickard E. Faith <faith@valinux.com>
+ * Daryll Strauss <daryll@valinux.com>
+ * Gareth Hughes <gareth@valinux.com>
+ *
+ */
+
+#include "sarea.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <linux/pci_ids.h>
+
+#include "driver.h"
+#include "drm.h"
+
+#include "sarea.h"
+#include "r128.h"
+#include "r128_dri.h"
+#include "r128_macros.h"
+#include "r128_reg.h"
+#include "r128_sarea.h"
+#include "r128_version.h"
+
+
+/* ?? HACK - for now, put this here... */
+/* ?? Alpha - this may need to be a variable to handle UP1x00 vs TITAN */
+#if defined(__alpha__)
+# define DRM_PAGE_SIZE 8192
+#elif defined(__ia64__)
+# define DRM_PAGE_SIZE getpagesize()
+#else
+# define DRM_PAGE_SIZE 4096
+#endif
+
+/**
+ * \brief Establish the set of modes available for the display.
+ *
+ * \param ctx display handle.
+ * \param numModes will receive the number of supported modes.
+ * \param modes will point to the list of supported modes.
+ *
+ * \return one on success, or zero on failure.
+ *
+ * Allocates a single visual and fills it with information according to the
+ * display bit depth. Supports only 16 and 32 bpp bit depths, aborting
+ * otherwise.
+ */
+const __GLcontextModes __glModes[] = {
+
+ /* 32 bit, RGBA Depth=24 Stencil=8 */
+ {.rgbMode = GL_TRUE, .colorIndexMode = GL_FALSE, .doubleBufferMode = GL_TRUE, .stereoMode = GL_FALSE,
+ .haveAccumBuffer = GL_FALSE, .haveDepthBuffer = GL_TRUE, .haveStencilBuffer = GL_TRUE,
+ .redBits = 8, .greenBits = 8, .blueBits = 8, .alphaBits = 8,
+ .redMask = 0xff0000, .greenMask = 0xff00, .blueMask = 0xff, .alphaMask = 0xff000000,
+ .rgbBits = 32, .indexBits = 0,
+ .accumRedBits = 0, .accumGreenBits = 0, .accumBlueBits = 0, .accumAlphaBits = 0,
+ .depthBits = 24, .stencilBits = 8,
+ .numAuxBuffers= 0, .level = 0, .pixmapMode = GL_FALSE, },
+
+ /* 16 bit, RGB Depth=16 */
+ {.rgbMode = GL_TRUE, .colorIndexMode = GL_FALSE, .doubleBufferMode = GL_TRUE, .stereoMode = GL_FALSE,
+ .haveAccumBuffer = GL_FALSE, .haveDepthBuffer = GL_TRUE, .haveStencilBuffer = GL_FALSE,
+ .redBits = 5, .greenBits = 6, .blueBits = 5, .alphaBits = 0,
+ .redMask = 0xf800, .greenMask = 0x07e0, .blueMask = 0x001f, .alphaMask = 0x0,
+ .rgbBits = 16, .indexBits = 0,
+ .accumRedBits = 0, .accumGreenBits = 0, .accumBlueBits = 0, .accumAlphaBits = 0,
+ .depthBits = 16, .stencilBits = 0,
+ .numAuxBuffers= 0, .level = 0, .pixmapMode = GL_FALSE, },
+};
+static int R128InitContextModes( const DRIDriverContext *ctx,
+ int *numModes, const __GLcontextModes **modes)
+{
+ *numModes = sizeof(__glModes)/sizeof(__GLcontextModes *);
+ *modes = &__glModes[0];
+ return 1;
+}
+
+/* Compute log base 2 of val. */
+static int R128MinBits(int val)
+{
+ int bits;
+
+ if (!val) return 1;
+ for (bits = 0; val; val >>= 1, ++bits);
+ return bits;
+}
+
+/* Initialize the AGP state. Request memory for use in AGP space, and
+ initialize the Rage 128 registers to point to that memory. */
+static GLboolean R128DRIAgpInit(const DRIDriverContext *ctx)
+{
+ unsigned char *R128MMIO = ctx->MMIOAddress;
+ R128InfoPtr info = ctx->driverPrivate;
+ unsigned long mode;
+ unsigned int vendor, device;
+ int ret;
+ unsigned long cntl, chunk;
+ int s, l;
+ int flags;
+ unsigned long agpBase;
+
+ if (drmAgpAcquire(ctx->drmFD) < 0) {
+ fprintf(stderr, "[agp] AGP not available\n");
+ return GL_FALSE;
+ }
+
+ /* Modify the mode if the default mode is
+ not appropriate for this particular
+ combination of graphics card and AGP
+ chipset. */
+
+ mode = drmAgpGetMode(ctx->drmFD); /* Default mode */
+ vendor = drmAgpVendorId(ctx->drmFD);
+ device = drmAgpDeviceId(ctx->drmFD);
+
+ mode &= ~R128_AGP_MODE_MASK;
+ switch (info->agpMode) {
+ case 4: mode |= R128_AGP_4X_MODE;
+ case 2: mode |= R128_AGP_2X_MODE;
+ case 1: default: mode |= R128_AGP_1X_MODE;
+ }
+
+ fprintf(stderr,
+ "[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n",
+ mode, vendor, device,
+ 0x1002,
+ info->Chipset);
+
+ if (drmAgpEnable(ctx->drmFD, mode) < 0) {
+ fprintf(stderr, "[agp] AGP not enabled\n");
+ drmAgpRelease(ctx->drmFD);
+ return GL_FALSE;
+ }
+
+ info->agpOffset = 0;
+
+ if ((ret = drmAgpAlloc(ctx->drmFD, info->agpSize*1024*1024, 0, NULL,
+ &info->agpMemHandle)) < 0) {
+ fprintf(stderr, "[agp] Out of memory (%d)\n", ret);
+ drmAgpRelease(ctx->drmFD);
+ return GL_FALSE;
+ }
+ fprintf(stderr,
+ "[agp] %d kB allocated with handle 0x%08x\n",
+ info->agpSize*1024, info->agpMemHandle);
+
+ if (drmAgpBind(ctx->drmFD, info->agpMemHandle, info->agpOffset) < 0) {
+ fprintf(stderr, "[agp] Could not bind\n");
+ drmAgpFree(ctx->drmFD, info->agpMemHandle);
+ drmAgpRelease(ctx->drmFD);
+ return GL_FALSE;
+ }
+
+ /* Initialize the CCE ring buffer data */
+ info->ringStart = info->agpOffset;
+ info->ringMapSize = info->ringSize*1024*1024 + DRM_PAGE_SIZE;
+ info->ringSizeLog2QW = R128MinBits(info->ringSize*1024*1024/8) - 1;
+
+ info->ringReadOffset = info->ringStart + info->ringMapSize;
+ info->ringReadMapSize = DRM_PAGE_SIZE;
+
+ /* Reserve space for vertex/indirect buffers */
+ info->bufStart = info->ringReadOffset + info->ringReadMapSize;
+ info->bufMapSize = info->bufSize*1024*1024;
+
+ /* Reserve the rest for AGP textures */
+ info->agpTexStart = info->bufStart + info->bufMapSize;
+ s = (info->agpSize*1024*1024 - info->agpTexStart);
+ l = R128MinBits((s-1) / R128_NR_TEX_REGIONS);
+ if (l < R128_LOG_TEX_GRANULARITY) l = R128_LOG_TEX_GRANULARITY;
+ info->agpTexMapSize = (s >> l) << l;
+ info->log2AGPTexGran = l;
+
+ if (info->CCESecure) flags = DRM_READ_ONLY;
+ else flags = 0;
+
+ if (drmAddMap(ctx->drmFD, info->ringStart, info->ringMapSize,
+ DRM_AGP, flags, &info->ringHandle) < 0) {
+ fprintf(stderr,
+ "[agp] Could not add ring mapping\n");
+ return GL_FALSE;
+ }
+ fprintf(stderr,
+ "[agp] ring handle = 0x%08lx\n", info->ringHandle);
+
+ if (drmMap(ctx->drmFD, info->ringHandle, info->ringMapSize,
+ (drmAddressPtr)&info->ring) < 0) {
+ fprintf(stderr, "[agp] Could not map ring\n");
+ return GL_FALSE;
+ }
+ fprintf(stderr,
+ "[agp] Ring mapped at 0x%08lx\n",
+ (unsigned long)info->ring);
+
+ if (drmAddMap(ctx->drmFD, info->ringReadOffset, info->ringReadMapSize,
+ DRM_AGP, flags, &info->ringReadPtrHandle) < 0) {
+ fprintf(stderr,
+ "[agp] Could not add ring read ptr mapping\n");
+ return GL_FALSE;
+ }
+ fprintf(stderr,
+ "[agp] ring read ptr handle = 0x%08lx\n",
+ info->ringReadPtrHandle);
+
+ if (drmMap(ctx->drmFD, info->ringReadPtrHandle, info->ringReadMapSize,
+ (drmAddressPtr)&info->ringReadPtr) < 0) {
+ fprintf(stderr,
+ "[agp] Could not map ring read ptr\n");
+ return GL_FALSE;
+ }
+ fprintf(stderr,
+ "[agp] Ring read ptr mapped at 0x%08lx\n",
+ (unsigned long)info->ringReadPtr);
+
+ if (drmAddMap(ctx->drmFD, info->bufStart, info->bufMapSize,
+ DRM_AGP, 0, &info->bufHandle) < 0) {
+ fprintf(stderr,
+ "[agp] Could not add vertex/indirect buffers mapping\n");
+ return GL_FALSE;
+ }
+ fprintf(stderr,
+ "[agp] vertex/indirect buffers handle = 0x%08lx\n",
+ info->bufHandle);
+
+ if (drmMap(ctx->drmFD, info->bufHandle, info->bufMapSize,
+ (drmAddressPtr)&info->buf) < 0) {
+ fprintf(stderr,
+ "[agp] Could not map vertex/indirect buffers\n");
+ return GL_FALSE;
+ }
+ fprintf(stderr,
+ "[agp] Vertex/indirect buffers mapped at 0x%08lx\n",
+ (unsigned long)info->buf);
+
+ if (drmAddMap(ctx->drmFD, info->agpTexStart, info->agpTexMapSize,
+ DRM_AGP, 0, &info->agpTexHandle) < 0) {
+ fprintf(stderr,
+ "[agp] Could not add AGP texture map mapping\n");
+ return GL_FALSE;
+ }
+ fprintf(stderr,
+ "[agp] AGP texture map handle = 0x%08lx\n",
+ info->agpTexHandle);
+
+ if (drmMap(ctx->drmFD, info->agpTexHandle, info->agpTexMapSize,
+ (drmAddressPtr)&info->agpTex) < 0) {
+ fprintf(stderr,
+ "[agp] Could not map AGP texture map\n");
+ return GL_FALSE;
+ }
+ fprintf(stderr,
+ "[agp] AGP Texture map mapped at 0x%08lx\n",
+ (unsigned long)info->agpTex);
+
+ /* Initialize Rage 128's AGP registers */
+ cntl = INREG(R128_AGP_CNTL);
+ cntl &= ~R128_AGP_APER_SIZE_MASK;
+ switch (info->agpSize) {
+ case 256: cntl |= R128_AGP_APER_SIZE_256MB; break;
+ case 128: cntl |= R128_AGP_APER_SIZE_128MB; break;
+ case 64: cntl |= R128_AGP_APER_SIZE_64MB; break;
+ case 32: cntl |= R128_AGP_APER_SIZE_32MB; break;
+ case 16: cntl |= R128_AGP_APER_SIZE_16MB; break;
+ case 8: cntl |= R128_AGP_APER_SIZE_8MB; break;
+ case 4: cntl |= R128_AGP_APER_SIZE_4MB; break;
+ default:
+ fprintf(stderr,
+ "[agp] Illegal aperture size %d kB\n",
+ info->agpSize*1024);
+ return GL_FALSE;
+ }
+ agpBase = drmAgpBase(ctx->drmFD);
+ OUTREG(R128_AGP_BASE, agpBase);
+ OUTREG(R128_AGP_CNTL, cntl);
+
+ /* Disable Rage 128's PCIGART registers */
+ chunk = INREG(R128_BM_CHUNK_0_VAL);
+ chunk &= ~(R128_BM_PTR_FORCE_TO_PCI |
+ R128_BM_PM4_RD_FORCE_TO_PCI |
+ R128_BM_GLOBAL_FORCE_TO_PCI);
+ OUTREG(R128_BM_CHUNK_0_VAL, chunk);
+
+ OUTREG(R128_PCI_GART_PAGE, 1); /* Ensure AGP GART is used (for now) */
+
+ return GL_TRUE;
+}
+
+static GLboolean R128DRIPciInit(const DRIDriverContext *ctx)
+{
+ R128InfoPtr info = ctx->driverPrivate;
+ unsigned char *R128MMIO = ctx->MMIOAddress;
+ CARD32 chunk;
+ int ret;
+ int flags;
+
+ info->agpOffset = 0;
+
+ ret = drmScatterGatherAlloc(ctx->drmFD, info->agpSize*1024*1024,
+ &info->pciMemHandle);
+ if (ret < 0) {
+ fprintf(stderr, "[pci] Out of memory (%d)\n", ret);
+ return GL_FALSE;
+ }
+ fprintf(stderr,
+ "[pci] %d kB allocated with handle 0x%08x\n",
+ info->agpSize*1024, info->pciMemHandle);
+
+ /* Initialize the CCE ring buffer data */
+ info->ringStart = info->agpOffset;
+ info->ringMapSize = info->ringSize*1024*1024 + DRM_PAGE_SIZE;
+ info->ringSizeLog2QW = R128MinBits(info->ringSize*1024*1024/8) - 1;
+
+ info->ringReadOffset = info->ringStart + info->ringMapSize;
+ info->ringReadMapSize = DRM_PAGE_SIZE;
+
+ /* Reserve space for vertex/indirect buffers */
+ info->bufStart = info->ringReadOffset + info->ringReadMapSize;
+ info->bufMapSize = info->bufSize*1024*1024;
+
+ flags = DRM_READ_ONLY | DRM_LOCKED | DRM_KERNEL;
+
+ if (drmAddMap(ctx->drmFD, info->ringStart, info->ringMapSize,
+ DRM_SCATTER_GATHER, flags, &info->ringHandle) < 0) {
+ fprintf(stderr,
+ "[pci] Could not add ring mapping\n");
+ return GL_FALSE;
+ }
+ fprintf(stderr,
+ "[pci] ring handle = 0x%08lx\n", info->ringHandle);
+
+ if (drmMap(ctx->drmFD, info->ringHandle, info->ringMapSize,
+ (drmAddressPtr)&info->ring) < 0) {
+ fprintf(stderr, "[pci] Could not map ring\n");
+ return GL_FALSE;
+ }
+ fprintf(stderr,
+ "[pci] Ring mapped at 0x%08lx\n",
+ (unsigned long)info->ring);
+ fprintf(stderr,
+ "[pci] Ring contents 0x%08lx\n",
+ *(unsigned long *)info->ring);
+
+ if (drmAddMap(ctx->drmFD, info->ringReadOffset, info->ringReadMapSize,
+ DRM_SCATTER_GATHER, flags, &info->ringReadPtrHandle) < 0) {
+ fprintf(stderr,
+ "[pci] Could not add ring read ptr mapping\n");
+ return GL_FALSE;
+ }
+ fprintf(stderr,
+ "[pci] ring read ptr handle = 0x%08lx\n",
+ info->ringReadPtrHandle);
+
+ if (drmMap(ctx->drmFD, info->ringReadPtrHandle, info->ringReadMapSize,
+ (drmAddressPtr)&info->ringReadPtr) < 0) {
+ fprintf(stderr,
+ "[pci] Could not map ring read ptr\n");
+ return GL_FALSE;
+ }
+ fprintf(stderr,
+ "[pci] Ring read ptr mapped at 0x%08lx\n",
+ (unsigned long)info->ringReadPtr);
+ fprintf(stderr,
+ "[pci] Ring read ptr contents 0x%08lx\n",
+ *(unsigned long *)info->ringReadPtr);
+
+ if (drmAddMap(ctx->drmFD, info->bufStart, info->bufMapSize,
+ DRM_SCATTER_GATHER, 0, &info->bufHandle) < 0) {
+ fprintf(stderr,
+ "[pci] Could not add vertex/indirect buffers mapping\n");
+ return GL_FALSE;
+ }
+ fprintf(stderr,
+ "[pci] vertex/indirect buffers handle = 0x%08lx\n",
+ info->bufHandle);
+
+ if (drmMap(ctx->drmFD, info->bufHandle, info->bufMapSize,
+ (drmAddressPtr)&info->buf) < 0) {
+ fprintf(stderr,
+ "[pci] Could not map vertex/indirect buffers\n");
+ return GL_FALSE;
+ }
+ fprintf(stderr,
+ "[pci] Vertex/indirect buffers mapped at 0x%08lx\n",
+ (unsigned long)info->buf);
+ fprintf(stderr,
+ "[pci] Vertex/indirect buffers contents 0x%08lx\n",
+ *(unsigned long *)info->buf);
+
+ if (!info->IsPCI) {
+ /* This is really an AGP card, force PCI GART mode */
+ chunk = INREG(R128_BM_CHUNK_0_VAL);
+ chunk |= (R128_BM_PTR_FORCE_TO_PCI |
+ R128_BM_PM4_RD_FORCE_TO_PCI |
+ R128_BM_GLOBAL_FORCE_TO_PCI);
+ OUTREG(R128_BM_CHUNK_0_VAL, chunk);
+ OUTREG(R128_PCI_GART_PAGE, 0); /* Ensure PCI GART is used */
+ }
+
+ return GL_TRUE;
+}
+
+/* Add a map for the MMIO registers that will be accessed by any
+ DRI-based clients. */
+static GLboolean R128DRIMapInit(const DRIDriverContext *ctx)
+{
+ R128InfoPtr info = ctx->driverPrivate;
+ int flags;
+
+ if (info->CCESecure) flags = DRM_READ_ONLY;
+ else flags = 0;
+
+ /* Map registers */
+ if (drmAddMap(ctx->drmFD, ctx->MMIOStart, ctx->MMIOSize,
+ DRM_REGISTERS, flags, &info->registerHandle) < 0) {
+ return GL_FALSE;
+ }
+ fprintf(stderr,
+ "[drm] register handle = 0x%08lx\n", info->registerHandle);
+
+ return GL_TRUE;
+}
+
+/* Initialize the kernel data structures. */
+static int R128DRIKernelInit(const DRIDriverContext *ctx)
+{
+ R128InfoPtr info = ctx->driverPrivate;
+ drmR128Init drmInfo;
+
+ memset( &drmInfo, 0, sizeof(drmR128Init) );
+
+ drmInfo.func = DRM_R128_INIT_CCE;
+ drmInfo.sarea_priv_offset = sizeof(XF86DRISAREARec);
+ drmInfo.is_pci = info->IsPCI;
+ drmInfo.cce_mode = info->CCEMode;
+ drmInfo.cce_secure = info->CCESecure;
+ drmInfo.ring_size = info->ringSize*1024*1024;
+ drmInfo.usec_timeout = info->CCEusecTimeout;
+
+ drmInfo.fb_bpp = ctx->bpp;
+ drmInfo.depth_bpp = ctx->bpp;
+
+ drmInfo.front_offset = info->frontOffset;
+ drmInfo.front_pitch = info->frontPitch;
+
+ drmInfo.back_offset = info->backOffset;
+ drmInfo.back_pitch = info->backPitch;
+
+ drmInfo.depth_offset = info->depthOffset;
+ drmInfo.depth_pitch = info->depthPitch;
+ drmInfo.span_offset = info->spanOffset;
+
+ drmInfo.fb_offset = info->LinearAddr;
+ drmInfo.mmio_offset = info->registerHandle;
+ drmInfo.ring_offset = info->ringHandle;
+ drmInfo.ring_rptr_offset = info->ringReadPtrHandle;
+ drmInfo.buffers_offset = info->bufHandle;
+ drmInfo.agp_textures_offset = info->agpTexHandle;
+
+ if (drmCommandWrite(ctx->drmFD, DRM_R128_INIT,
+ &drmInfo, sizeof(drmR128Init)) < 0)
+ return GL_FALSE;
+
+ return GL_TRUE;
+}
+
+/* Add a map for the vertex buffers that will be accessed by any
+ DRI-based clients. */
+static GLboolean R128DRIBufInit(const DRIDriverContext *ctx)
+{
+ R128InfoPtr info = ctx->driverPrivate;
+ /* Initialize vertex buffers */
+ if (info->IsPCI) {
+ info->bufNumBufs = drmAddBufs(ctx->drmFD,
+ info->bufMapSize / R128_BUFFER_SIZE,
+ R128_BUFFER_SIZE,
+ DRM_SG_BUFFER,
+ info->bufStart);
+ } else {
+ info->bufNumBufs = drmAddBufs(ctx->drmFD,
+ info->bufMapSize / R128_BUFFER_SIZE,
+ R128_BUFFER_SIZE,
+ DRM_AGP_BUFFER,
+ info->bufStart);
+ }
+ if (info->bufNumBufs <= 0) {
+ fprintf(stderr,
+ "[drm] Could not create vertex/indirect buffers list\n");
+ return GL_FALSE;
+ }
+ fprintf(stderr,
+ "[drm] Added %d %d byte vertex/indirect buffers\n",
+ info->bufNumBufs, R128_BUFFER_SIZE);
+
+ if (!(info->buffers = drmMapBufs(ctx->drmFD))) {
+ fprintf(stderr,
+ "[drm] Failed to map vertex/indirect buffers list\n");
+ return GL_FALSE;
+ }
+ fprintf(stderr,
+ "[drm] Mapped %d vertex/indirect buffers\n",
+ info->buffers->count);
+
+ return GL_TRUE;
+}
+
+static void R128DRIIrqInit(const DRIDriverContext *ctx)
+{
+ R128InfoPtr info = ctx->driverPrivate;
+ unsigned char *R128MMIO = ctx->MMIOAddress;
+
+ if (!info->irq) {
+ info->irq = drmGetInterruptFromBusID(
+ ctx->drmFD,
+ ctx->pciBus,
+ ctx->pciDevice,
+ ctx->pciFunc);
+
+ if((drmCtlInstHandler(ctx->drmFD, info->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");
+ info->irq = 0;
+ } else {
+ info->gen_int_cntl = INREG( R128_GEN_INT_CNTL );
+ }
+ }
+
+ if (info->irq)
+ fprintf(stderr,
+ "[drm] dma control initialized, using IRQ %d\n",
+ info->irq);
+}
+
+static int R128CCEStop(const DRIDriverContext *ctx)
+{
+ R128InfoPtr info = ctx->driverPrivate;
+ drmR128CCEStop stop;
+ int ret, i;
+
+ stop.flush = 1;
+ stop.idle = 1;
+
+ ret = drmCommandWrite( ctx->drmFD, DRM_R128_CCE_STOP,
+ &stop, sizeof(drmR128CCEStop) );
+
+ if ( ret == 0 ) {
+ return 0;
+ } else if ( errno != EBUSY ) {
+ return -errno;
+ }
+
+ stop.flush = 0;
+
+ i = 0;
+ do {
+ ret = drmCommandWrite( ctx->drmFD, DRM_R128_CCE_STOP,
+ &stop, sizeof(drmR128CCEStop) );
+ } while ( ret && errno == EBUSY && i++ < R128_IDLE_RETRY );
+
+ if ( ret == 0 ) {
+ return 0;
+ } else if ( errno != EBUSY ) {
+ return -errno;
+ }
+
+ stop.idle = 0;
+
+ if ( drmCommandWrite( ctx->drmFD, DRM_R128_CCE_STOP,
+ &stop, sizeof(drmR128CCEStop) )) {
+ return -errno;
+ } else {
+ return 0;
+ }
+}
+
+/* Initialize the CCE state, and start the CCE (if used by the X server) */
+static void R128DRICCEInit(const DRIDriverContext *ctx)
+{
+ R128InfoPtr info = ctx->driverPrivate;
+
+ /* Turn on bus mastering */
+ info->BusCntl &= ~R128_BUS_MASTER_DIS;
+
+ /* CCEMode is initialized in r128_driver.c */
+ switch (info->CCEMode) {
+ case R128_PM4_NONPM4: info->CCEFifoSize = 0; break;
+ case R128_PM4_192PIO: info->CCEFifoSize = 192; break;
+ case R128_PM4_192BM: info->CCEFifoSize = 192; break;
+ case R128_PM4_128PIO_64INDBM: info->CCEFifoSize = 128; break;
+ case R128_PM4_128BM_64INDBM: info->CCEFifoSize = 128; break;
+ case R128_PM4_64PIO_128INDBM: info->CCEFifoSize = 64; break;
+ case R128_PM4_64BM_128INDBM: info->CCEFifoSize = 64; break;
+ case R128_PM4_64PIO_64VCBM_64INDBM: info->CCEFifoSize = 64; break;
+ case R128_PM4_64BM_64VCBM_64INDBM: info->CCEFifoSize = 64; break;
+ case R128_PM4_64PIO_64VCPIO_64INDPIO: info->CCEFifoSize = 64; break;
+ }
+
+ /* Make sure the CCE is on for the X server */
+ R128CCE_START(ctx, info);
+}
+
+
+static int R128MemoryInit(const DRIDriverContext *ctx)
+{
+ R128InfoPtr info = ctx->driverPrivate;
+ int width_bytes = ctx->shared.virtualWidth * ctx->cpp;
+ int cpp = ctx->cpp;
+ int bufferSize = ((ctx->shared.virtualHeight * width_bytes
+ + R128_BUFFER_ALIGN)
+ & ~R128_BUFFER_ALIGN);
+ int depthSize = ((((ctx->shared.virtualHeight+15) & ~15) * width_bytes
+ + R128_BUFFER_ALIGN)
+ & ~R128_BUFFER_ALIGN);
+ int l;
+
+ info->frontOffset = 0;
+ info->frontPitch = ctx->shared.virtualWidth;
+
+ fprintf(stderr,
+ "Using %d MB AGP aperture\n", info->agpSize);
+ fprintf(stderr,
+ "Using %d MB for the ring buffer\n", info->ringSize);
+ fprintf(stderr,
+ "Using %d MB for vertex/indirect buffers\n", info->bufSize);
+ fprintf(stderr,
+ "Using %d MB for AGP textures\n", info->agpTexSize);
+
+ /* Front, back and depth buffers - everything else texture??
+ */
+ info->textureSize = ctx->shared.fbSize - 2 * bufferSize - depthSize;
+
+ if (info->textureSize < 0)
+ return 0;
+
+ l = R128MinBits((info->textureSize-1) / R128_NR_TEX_REGIONS);
+ if (l < R128_LOG_TEX_GRANULARITY) l = R128_LOG_TEX_GRANULARITY;
+
+ /* Round the texture size up to the nearest whole number of
+ * texture regions. Again, be greedy about this, don't
+ * round down.
+ */
+ info->log2TexGran = l;
+ info->textureSize = (info->textureSize >> l) << l;
+
+ /* Set a minimum usable local texture heap size. This will fit
+ * two 256x256x32bpp textures.
+ */
+ if (info->textureSize < 512 * 1024) {
+ info->textureOffset = 0;
+ info->textureSize = 0;
+ }
+
+ /* Reserve space for textures */
+ info->textureOffset = ((ctx->shared.fbSize - info->textureSize +
+ R128_BUFFER_ALIGN) &
+ ~R128_BUFFER_ALIGN);
+
+ /* Reserve space for the shared depth
+ * buffer.
+ */
+ info->depthOffset = ((info->textureOffset - depthSize +
+ R128_BUFFER_ALIGN) &
+ ~R128_BUFFER_ALIGN);
+ info->depthPitch = ctx->shared.virtualWidth;
+
+ info->backOffset = ((info->depthOffset - bufferSize +
+ R128_BUFFER_ALIGN) &
+ ~R128_BUFFER_ALIGN);
+ info->backPitch = ctx->shared.virtualWidth;
+
+
+ fprintf(stderr,
+ "Will use back buffer at offset 0x%x\n",
+ info->backOffset);
+ fprintf(stderr,
+ "Will use depth buffer at offset 0x%x\n",
+ info->depthOffset);
+ fprintf(stderr,
+ "Will use %d kb for textures at offset 0x%x\n",
+ info->textureSize/1024, info->textureOffset);
+
+ return 1;
+}
+
+
+/* Initialize the screen-specific data structures for the DRI and the
+ Rage 128. This is the main entry point to the device-specific
+ initialization code. It calls device-independent DRI functions to
+ create the DRI data structures and initialize the DRI state. */
+static GLboolean R128DRIScreenInit(DRIDriverContext *ctx)
+{
+ R128InfoPtr info = ctx->driverPrivate;
+ R128DRIPtr pR128DRI;
+ int err, major, minor, patch;
+ drmVersionPtr version;
+
+ switch (ctx->bpp) {
+ case 8:
+ /* These modes are not supported (yet). */
+ case 15:
+ case 24:
+ fprintf(stderr,
+ "[dri] R128DRIScreenInit failed (depth %d not supported). "
+ "[dri] Disabling DRI.\n", ctx->bpp);
+ return GL_FALSE;
+
+ /* Only 16 and 32 color depths are supports currently. */
+ case 16:
+ case 32:
+ break;
+ }
+
+ info->registerSize = ctx->MMIOSize;
+ ctx->shared.SAREASize = DRM_PAGE_SIZE;
+
+ /* Note that drmOpen will try to load the kernel module, if needed. */
+ ctx->drmFD = drmOpen("r128", NULL );
+ if (ctx->drmFD < 0) {
+ fprintf(stderr, "[drm] drmOpen failed\n");
+ return 0;
+ }
+
+ /* Check the r128 DRM version */
+ version = drmGetVersion(ctx->drmFD);
+ if (version) {
+ if (version->version_major != 2 ||
+ version->version_minor < 2) {
+ /* incompatible drm version */
+ fprintf(stderr,
+ "[dri] R128DRIScreenInit failed because of a version mismatch.\n"
+ "[dri] r128.o kernel module version is %d.%d.%d but version 2.2 or greater is needed.\n"
+ "[dri] Disabling the DRI.\n",
+ version->version_major,
+ version->version_minor,
+ version->version_patchlevel);
+ drmFreeVersion(version);
+ return GL_FALSE;
+ }
+ info->drmMinor = version->version_minor;
+ drmFreeVersion(version);
+ }
+
+ 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,
+ (drmHandle)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 (!R128MemoryInit(ctx))
+ return GL_FALSE;
+
+ /* Initialize AGP */
+ if (!info->IsPCI && !R128DRIAgpInit(ctx)) {
+ info->IsPCI = GL_TRUE;
+ fprintf(stderr,
+ "[agp] AGP failed to initialize -- falling back to PCI mode.\n");
+ fprintf(stderr,
+ "[agp] Make sure you have the agpgart kernel module loaded.\n");
+ }
+
+ /* Initialize PCIGART */
+ if (info->IsPCI && !R128DRIPciInit(ctx)) {
+ return GL_FALSE;
+ }
+
+ /* DRIScreenInit doesn't add all the
+ common mappings. Add additional
+ mappings here. */
+ if (!R128DRIMapInit(ctx)) {
+ return GL_FALSE;
+ }
+
+ /* 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 (!R128DRIKernelInit(ctx)) {
+ return GL_FALSE;
+ }
+
+ /* Initialize the vertex buffers list */
+ if (!R128DRIBufInit(ctx)) {
+ return GL_FALSE;
+ }
+
+ /* Initialize IRQ */
+ R128DRIIrqInit(ctx);
+
+ /* Initialize and start the CCE if required */
+ R128DRICCEInit(ctx);
+
+ /* 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.
+ */
+ memset((char *)ctx->FBAddress + info->frontOffset,
+ 0,
+ info->frontPitch * ctx->cpp * ctx->shared.virtualHeight );
+
+ memset((char *)ctx->FBAddress + info->backOffset,
+ 0,
+ info->backPitch * ctx->cpp * ctx->shared.virtualHeight );
+
+ R128SAREAPrivPtr pSAREAPriv;
+ pSAREAPriv = (R128SAREAPrivPtr)(((char*)ctx->pSAREA) +
+ sizeof(XF86DRISAREARec));
+ memset(pSAREAPriv, 0, sizeof(*pSAREAPriv));
+
+ /* This is the struct passed to radeon_dri.so for its initialization */
+ ctx->driverClientMsg = malloc(sizeof(R128DRIRec));
+ ctx->driverClientMsgSize = sizeof(R128DRIRec);
+
+ pR128DRI = (R128DRIPtr)ctx->driverClientMsg;
+ pR128DRI->deviceID = info->Chipset;
+ pR128DRI->width = ctx->shared.virtualWidth;
+ pR128DRI->height = ctx->shared.virtualHeight;
+ pR128DRI->depth = ctx->bpp;
+ pR128DRI->bpp = ctx->bpp;
+
+ pR128DRI->IsPCI = info->IsPCI;
+ pR128DRI->AGPMode = info->agpMode;
+
+ pR128DRI->frontOffset = info->frontOffset;
+ pR128DRI->frontPitch = info->frontPitch;
+ pR128DRI->backOffset = info->backOffset;
+ pR128DRI->backPitch = info->backPitch;
+ pR128DRI->depthOffset = info->depthOffset;
+ pR128DRI->depthPitch = info->depthPitch;
+ pR128DRI->spanOffset = info->spanOffset;
+ pR128DRI->textureOffset = info->textureOffset;
+ pR128DRI->textureSize = info->textureSize;
+ pR128DRI->log2TexGran = info->log2TexGran;
+
+ pR128DRI->registerHandle = info->registerHandle;
+ pR128DRI->registerSize = info->registerSize;
+
+ pR128DRI->agpTexHandle = info->agpTexHandle;
+ pR128DRI->agpTexMapSize = info->agpTexMapSize;
+ pR128DRI->log2AGPTexGran = info->log2AGPTexGran;
+ pR128DRI->agpTexOffset = info->agpTexStart;
+ pR128DRI->sarea_priv_offset = sizeof(XF86DRISAREARec);
+
+ return GL_TRUE;
+}
+
+/* The screen is being closed, so clean up any state and free any
+ resources used by the DRI. */
+void R128DRICloseScreen(const DRIDriverContext *ctx)
+{
+ R128InfoPtr info = ctx->driverPrivate;
+ drmR128Init drmInfo;
+
+ /* Stop the CCE if it is still in use */
+ R128CCE_STOP(ctx, info);
+
+ if (info->irq) {
+ drmCtlUninstHandler(ctx->drmFD);
+ info->irq = 0;
+ }
+
+ /* De-allocate vertex buffers */
+ if (info->buffers) {
+ drmUnmapBufs(info->buffers);
+ info->buffers = NULL;
+ }
+
+ /* De-allocate all kernel resources */
+ memset(&drmInfo, 0, sizeof(drmR128Init));
+ drmInfo.func = DRM_R128_CLEANUP_CCE;
+ drmCommandWrite(ctx->drmFD, DRM_R128_INIT,
+ &drmInfo, sizeof(drmR128Init));
+
+ /* De-allocate all AGP resources */
+ if (info->agpTex) {
+ drmUnmap(info->agpTex, info->agpTexMapSize);
+ info->agpTex = NULL;
+ }
+ if (info->buf) {
+ drmUnmap(info->buf, info->bufMapSize);
+ info->buf = NULL;
+ }
+ if (info->ringReadPtr) {
+ drmUnmap(info->ringReadPtr, info->ringReadMapSize);
+ info->ringReadPtr = NULL;
+ }
+ if (info->ring) {
+ drmUnmap(info->ring, info->ringMapSize);
+ info->ring = NULL;
+ }
+ if (info->agpMemHandle != DRM_AGP_NO_HANDLE) {
+ drmAgpUnbind(ctx->drmFD, info->agpMemHandle);
+ drmAgpFree(ctx->drmFD, info->agpMemHandle);
+ info->agpMemHandle = 0;
+ drmAgpRelease(ctx->drmFD);
+ }
+ if (info->pciMemHandle) {
+ drmScatterGatherFree(ctx->drmFD, info->pciMemHandle);
+ info->pciMemHandle = 0;
+ }
+}
+
+static GLboolean R128PreInitDRI(const DRIDriverContext *ctx)
+{
+ R128InfoPtr info = ctx->driverPrivate;
+
+ /*info->CCEMode = R128_DEFAULT_CCE_PIO_MODE;*/
+ info->CCEMode = R128_DEFAULT_CCE_BM_MODE;
+ info->CCESecure = GL_TRUE;
+
+ info->agpMode = R128_DEFAULT_AGP_MODE;
+ info->agpSize = R128_DEFAULT_AGP_SIZE;
+ info->ringSize = R128_DEFAULT_RING_SIZE;
+ info->bufSize = R128_DEFAULT_BUFFER_SIZE;
+ info->agpTexSize = R128_DEFAULT_AGP_TEX_SIZE;
+
+ info->CCEusecTimeout = R128_DEFAULT_CCE_TIMEOUT;
+
+ return GL_TRUE;
+}
+
+/**
+ * \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 R128ScreenInit() for the screen initialization.
+ *
+ * Before exiting clears the framebuffer memory accessing it directly.
+ */
+static int R128InitFBDev( DRIDriverContext *ctx )
+{
+ R128InfoPtr info = calloc(1, sizeof(*info));
+
+ {
+ 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 *)info;
+
+ info->Chipset = ctx->chipset;
+
+ switch (info->Chipset) {
+ case PCI_DEVICE_ID_ATI_RAGE128_LE:
+ case PCI_DEVICE_ID_ATI_RAGE128_RE:
+ case PCI_DEVICE_ID_ATI_RAGE128_RK:
+ case PCI_DEVICE_ID_ATI_RAGE128_PD:
+ case PCI_DEVICE_ID_ATI_RAGE128_PP:
+ case PCI_DEVICE_ID_ATI_RAGE128_PR:
+ /* This is a PCI card */
+ info->IsPCI = GL_TRUE;
+ break;
+ default:
+ /* This is an AGP card */
+ info->IsPCI = GL_FALSE;
+ break;
+ }
+
+ info->frontPitch = ctx->shared.virtualWidth;
+ info->LinearAddr = ctx->FBStart & 0xfc000000;
+
+ if (!R128PreInitDRI(ctx))
+ return 0;
+
+ if (!R128DRIScreenInit(ctx))
+ 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 R128HaltFBDev( DRIDriverContext *ctx )
+{
+ drmUnmap( ctx->pSAREA, ctx->shared.SAREASize );
+ drmClose(ctx->drmFD);
+
+ if (ctx->driverPrivate) {
+ free(ctx->driverPrivate);
+ ctx->driverPrivate = 0;
+ }
+}
+
+
+/**
+ * \brief Validate the fbdev mode.
+ *
+ * \param ctx display handle.
+ *
+ * \return one on success, or zero on failure.
+ *
+ * Saves some registers and returns 1.
+ *
+ * \sa R128PostValidateMode().
+ */
+static int R128ValidateMode( 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 R128ValidateMode().
+ */
+static int R128PostValidateMode( const DRIDriverContext *ctx )
+{
+ return 1;
+}
+
+
+/**
+ * \brief Shutdown the drawing engine.
+ *
+ * \param ctx display handle
+ *
+ * Turns off the command processor engine & restores the graphics card
+ * to a state that fbdev understands.
+ */
+static int R128EngineShutdown( const DRIDriverContext *ctx )
+{
+ return 1;
+}
+
+/**
+ * \brief Restore the drawing engine.
+ *
+ * \param ctx display handle
+ *
+ * Resets the graphics card and sets initial values for several registers of
+ * the card's drawing engine.
+ *
+ * Turns on the R128 command processor engine (i.e., the ringbuffer).
+ */
+static int R128EngineRestore( const DRIDriverContext *ctx )
+{
+ return 1;
+}
+
+
+/**
+ * \brief Exported driver interface for Mini GLX.
+ *
+ * \sa DRIDriverRec.
+ */
+const struct DRIDriverRec __driDriver = {
+ R128InitContextModes,
+ R128ValidateMode,
+ R128PostValidateMode,
+ R128InitFBDev,
+ R128HaltFBDev,
+ R128EngineShutdown,
+ R128EngineRestore,
+ 0,
+};
diff --git a/src/mesa/drivers/dri/r128/server/r128_dri.h b/src/mesa/drivers/dri/r128/server/r128_dri.h
new file mode 100644
index 0000000000..80f94ded68
--- /dev/null
+++ b/src/mesa/drivers/dri/r128/server/r128_dri.h
@@ -0,0 +1,103 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_dri.h,v 1.7 2002/10/30 12:52:12 alanh Exp $ */
+/*
+ * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario,
+ * Precision Insight, Inc., Cedar Park, Texas, 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, 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
+ * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, PRECISION INSIGHT, 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:
+ * Kevin E. Martin <martin@valinux.com>
+ * Rickard E. Faith <faith@valinux.com>
+ * Gareth Hughes <gareth@valinux.com>
+ *
+ */
+
+#ifndef _R128_DRI_
+#define _R128_DRI_
+
+#include "xf86drm.h"
+#include "r128_common.h"
+
+/* DRI Driver defaults */
+#define R128_DEFAULT_CCE_PIO_MODE R128_PM4_64PIO_64VCBM_64INDBM
+#define R128_DEFAULT_CCE_BM_MODE R128_PM4_64BM_64VCBM_64INDBM
+#define R128_DEFAULT_AGP_MODE 1
+#define R128_DEFAULT_AGP_SIZE 8 /* MB (must be a power of 2 and > 4MB) */
+#define R128_DEFAULT_RING_SIZE 1 /* MB (must be page aligned) */
+#define R128_DEFAULT_BUFFER_SIZE 2 /* MB (must be page aligned) */
+#define R128_DEFAULT_AGP_TEX_SIZE 1 /* MB (must be page aligned) */
+
+#define R128_DEFAULT_CCE_TIMEOUT 10000 /* usecs */
+
+#define R128_AGP_MAX_MODE 4
+#define R128_BUFFER_ALIGN 0x00000fff
+
+#define R128_CARD_TYPE_R128 1
+#define R128_CARD_TYPE_R128_PRO 2
+#define R128_CARD_TYPE_R128_MOBILITY 3
+
+#define R128CCE_USE_RING_BUFFER(m) \
+(((m) == R128_PM4_192BM) || \
+ ((m) == R128_PM4_128BM_64INDBM) || \
+ ((m) == R128_PM4_64BM_128INDBM) || \
+ ((m) == R128_PM4_64BM_64VCBM_64INDBM))
+
+typedef struct {
+ /* DRI screen private data */
+ int deviceID; /* PCI device ID */
+ int width; /* Width in pixels of display */
+ int height; /* Height in scanlines of display */
+ int depth; /* Depth of display (8, 15, 16, 24) */
+ int bpp; /* Bit depth of display (8, 16, 24, 32) */
+
+ int IsPCI; /* Current card is a PCI card */
+ int AGPMode;
+
+ int frontOffset; /* Start of front buffer */
+ int frontPitch;
+ int backOffset; /* Start of shared back buffer */
+ int backPitch;
+ int depthOffset; /* Start of shared depth buffer */
+ int depthPitch;
+ int spanOffset; /* Start of scratch spanline */
+ int textureOffset;/* Start of texture data in frame buffer */
+ int textureSize;
+ int log2TexGran;
+
+ /* MMIO register data */
+ drmHandle registerHandle;
+ drmSize registerSize;
+
+ /* CCE AGP Texture data */
+ drmHandle agpTexHandle;
+ drmSize agpTexMapSize;
+ int log2AGPTexGran;
+ int agpTexOffset;
+ unsigned int sarea_priv_offset;
+} R128DRIRec, *R128DRIPtr;
+
+#endif
diff --git a/src/mesa/drivers/dri/r128/server/r128_macros.h b/src/mesa/drivers/dri/r128/server/r128_macros.h
new file mode 100644
index 0000000000..93b7feb02c
--- /dev/null
+++ b/src/mesa/drivers/dri/r128/server/r128_macros.h
@@ -0,0 +1,135 @@
+/**
+ * \file server/R128_macros.h
+ * \brief Macros for R128 MMIO operation.
+ *
+ * \authors Kevin E. Martin <martin@xfree86.org>
+ * \authors Rickard E. Faith <faith@valinux.com>
+ * \authors Alan Hourihane <alanh@fairlite.demon.co.uk>
+ */
+
+/*
+ * Copyright 2000 ATI Technologies Inc., Markham, Ontario, 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, 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
+ * 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.
+ */
+
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/R128_reg.h,v 1.20 2002/10/12 01:38:07 martin Exp $ */
+
+#ifndef _R128_MACROS_H_
+#define _R128_MACROS_H_
+
+
+
+# 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)
+
+
+ /* Memory mapped register access macros */
+#define INREG8(addr) MMIO_IN8(R128MMIO, addr)
+#define INREG16(addr) MMIO_IN16(R128MMIO, addr)
+#define INREG(addr) MMIO_IN32(R128MMIO, addr)
+#define OUTREG8(addr, val) MMIO_OUT8(R128MMIO, addr, val)
+#define OUTREG16(addr, val) MMIO_OUT16(R128MMIO, addr, val)
+#define OUTREG(addr, val) MMIO_OUT32(R128MMIO, addr, val)
+
+#define ADDRREG(addr) ((volatile GLuint *)(pointer)(R128MMIO + (addr)))
+
+
+#define OUTREGP(addr, val, mask) \
+do { \
+ GLuint tmp = INREG(addr); \
+ tmp &= (mask); \
+ tmp |= (val); \
+ OUTREG(addr, tmp); \
+} while (0)
+
+#define INPLL(dpy, addr) r128INPLL(dpy, addr)
+
+#define OUTPLL(addr, val) \
+do { \
+ OUTREG8(R128_CLOCK_CNTL_INDEX, (((addr) & 0x3f) | \
+ R128_PLL_WR_EN)); \
+ OUTREG(R128_CLOCK_CNTL_DATA, val); \
+} while (0)
+
+#define OUTPLLP(dpy, addr, val, mask) \
+do { \
+ GLuint tmp = INPLL(dpy, addr); \
+ tmp &= (mask); \
+ tmp |= (val); \
+ OUTPLL(addr, tmp); \
+} while (0)
+
+#define OUTPAL_START(idx) \
+do { \
+ OUTREG8(R128_PALETTE_INDEX, (idx)); \
+} while (0)
+
+#define OUTPAL_NEXT(r, g, b) \
+do { \
+ OUTREG(R128_PALETTE_DATA, ((r) << 16) | ((g) << 8) | (b)); \
+} while (0)
+
+#define OUTPAL_NEXT_CARD32(v) \
+do { \
+ OUTREG(R128_PALETTE_DATA, (v & 0x00ffffff)); \
+} while (0)
+
+#define OUTPAL(idx, r, g, b) \
+do { \
+ OUTPAL_START((idx)); \
+ OUTPAL_NEXT((r), (g), (b)); \
+} while (0)
+
+#define INPAL_START(idx) \
+do { \
+ OUTREG(R128_PALETTE_INDEX, (idx) << 16); \
+} while (0)
+
+#define INPAL_NEXT() INREG(R128_PALETTE_DATA)
+
+#define PAL_SELECT(idx) \
+do { \
+ if (!idx) { \
+ OUTREG(R128_DAC_CNTL2, INREG(R128_DAC_CNTL2) & \
+ (GLuint)~R128_DAC2_PALETTE_ACC_CTL); \
+ } else { \
+ OUTREG(R128_DAC_CNTL2, INREG(R128_DAC_CNTL2) | \
+ R128_DAC2_PALETTE_ACC_CTL); \
+ } \
+} while (0)
+
+
+#endif
diff --git a/src/mesa/drivers/dri/r128/server/r128_reg.h b/src/mesa/drivers/dri/r128/server/r128_reg.h
new file mode 100644
index 0000000000..7ec4004492
--- /dev/null
+++ b/src/mesa/drivers/dri/r128/server/r128_reg.h
@@ -0,0 +1,1431 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_reg.h,v 1.15 2002/12/16 16:19:11 dawes Exp $ */
+/*
+ * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario,
+ * Precision Insight, Inc., Cedar Park, Texas, 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, 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
+ * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, PRECISION INSIGHT, 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:
+ * Rickard E. Faith <faith@valinux.com>
+ * Kevin E. Martin <martin@valinux.com>
+ * Gareth Hughes <gareth@valinux.com>
+ *
+ * References:
+ *
+ * RAGE 128 VR/ RAGE 128 GL Register Reference Manual (Technical
+ * Reference Manual P/N RRG-G04100-C Rev. 0.04), ATI Technologies: April
+ * 1999.
+ *
+ * RAGE 128 Software Development Manual (Technical Reference Manual P/N
+ * SDK-G04000 Rev. 0.01), ATI Technologies: June 1999.
+ *
+ */
+
+#ifndef _R128_REG_H_
+#define _R128_REG_H_
+
+#define R128_ADAPTER_ID 0x0f2c /* PCI */
+#define R128_AGP_APER_OFFSET 0x0178
+#define R128_AGP_BASE 0x0170
+#define R128_AGP_CNTL 0x0174
+# define R128_AGP_APER_SIZE_256MB (0x00 << 0)
+# define R128_AGP_APER_SIZE_128MB (0x20 << 0)
+# define R128_AGP_APER_SIZE_64MB (0x30 << 0)
+# define R128_AGP_APER_SIZE_32MB (0x38 << 0)
+# define R128_AGP_APER_SIZE_16MB (0x3c << 0)
+# define R128_AGP_APER_SIZE_8MB (0x3e << 0)
+# define R128_AGP_APER_SIZE_4MB (0x3f << 0)
+# define R128_AGP_APER_SIZE_MASK (0x3f << 0)
+#define R128_AGP_CNTL_B 0x0b44
+#define R128_AGP_COMMAND 0x0f58 /* PCI */
+#define R128_AGP_PLL_CNTL 0x0010 /* PLL */
+#define R128_AGP_STATUS 0x0f54 /* PCI */
+# define R128_AGP_1X_MODE 0x01
+# define R128_AGP_2X_MODE 0x02
+# define R128_AGP_4X_MODE 0x04
+# define R128_AGP_MODE_MASK 0x07
+#define R128_AMCGPIO_A_REG 0x01a0
+#define R128_AMCGPIO_EN_REG 0x01a8
+#define R128_AMCGPIO_MASK 0x0194
+#define R128_AMCGPIO_Y_REG 0x01a4
+#define R128_ATTRDR 0x03c1 /* VGA */
+#define R128_ATTRDW 0x03c0 /* VGA */
+#define R128_ATTRX 0x03c0 /* VGA */
+#define R128_AUX_SC_CNTL 0x1660
+# define R128_AUX1_SC_EN (1 << 0)
+# define R128_AUX1_SC_MODE_OR (0 << 1)
+# define R128_AUX1_SC_MODE_NAND (1 << 1)
+# define R128_AUX2_SC_EN (1 << 2)
+# define R128_AUX2_SC_MODE_OR (0 << 3)
+# define R128_AUX2_SC_MODE_NAND (1 << 3)
+# define R128_AUX3_SC_EN (1 << 4)
+# define R128_AUX3_SC_MODE_OR (0 << 5)
+# define R128_AUX3_SC_MODE_NAND (1 << 5)
+#define R128_AUX1_SC_BOTTOM 0x1670
+#define R128_AUX1_SC_LEFT 0x1664
+#define R128_AUX1_SC_RIGHT 0x1668
+#define R128_AUX1_SC_TOP 0x166c
+#define R128_AUX2_SC_BOTTOM 0x1680
+#define R128_AUX2_SC_LEFT 0x1674
+#define R128_AUX2_SC_RIGHT 0x1678
+#define R128_AUX2_SC_TOP 0x167c
+#define R128_AUX3_SC_BOTTOM 0x1690
+#define R128_AUX3_SC_LEFT 0x1684
+#define R128_AUX3_SC_RIGHT 0x1688
+#define R128_AUX3_SC_TOP 0x168c
+#define R128_AUX_WINDOW_HORZ_CNTL 0x02d8
+#define R128_AUX_WINDOW_VERT_CNTL 0x02dc
+
+#define R128_BASE_CODE 0x0f0b
+#define R128_BIOS_0_SCRATCH 0x0010
+#define R128_BIOS_1_SCRATCH 0x0014
+#define R128_BIOS_2_SCRATCH 0x0018
+#define R128_BIOS_3_SCRATCH 0x001c
+#define R128_BIOS_4_SCRATCH 0x0020
+#define R128_BIOS_5_SCRATCH 0x0024
+# define R128_BIOS_DISPLAY_FP (1 << 0)
+# define R128_BIOS_DISPLAY_CRT (2 << 0)
+# define R128_BIOS_DISPLAY_FP_CRT (3 << 0)
+#define R128_BIOS_6_SCRATCH 0x0028
+#define R128_BIOS_7_SCRATCH 0x002c
+#define R128_BIOS_ROM 0x0f30 /* PCI */
+#define R128_BIST 0x0f0f /* PCI */
+#define R128_BM_CHUNK_0_VAL 0x0a18
+# define R128_BM_PTR_FORCE_TO_PCI (1 << 21)
+# define R128_BM_PM4_RD_FORCE_TO_PCI (1 << 22)
+# define R128_BM_GLOBAL_FORCE_TO_PCI (1 << 23)
+#define R128_BRUSH_DATA0 0x1480
+#define R128_BRUSH_DATA1 0x1484
+#define R128_BRUSH_DATA10 0x14a8
+#define R128_BRUSH_DATA11 0x14ac
+#define R128_BRUSH_DATA12 0x14b0
+#define R128_BRUSH_DATA13 0x14b4
+#define R128_BRUSH_DATA14 0x14b8
+#define R128_BRUSH_DATA15 0x14bc
+#define R128_BRUSH_DATA16 0x14c0
+#define R128_BRUSH_DATA17 0x14c4
+#define R128_BRUSH_DATA18 0x14c8
+#define R128_BRUSH_DATA19 0x14cc
+#define R128_BRUSH_DATA2 0x1488
+#define R128_BRUSH_DATA20 0x14d0
+#define R128_BRUSH_DATA21 0x14d4
+#define R128_BRUSH_DATA22 0x14d8
+#define R128_BRUSH_DATA23 0x14dc
+#define R128_BRUSH_DATA24 0x14e0
+#define R128_BRUSH_DATA25 0x14e4
+#define R128_BRUSH_DATA26 0x14e8
+#define R128_BRUSH_DATA27 0x14ec
+#define R128_BRUSH_DATA28 0x14f0
+#define R128_BRUSH_DATA29 0x14f4
+#define R128_BRUSH_DATA3 0x148c
+#define R128_BRUSH_DATA30 0x14f8
+#define R128_BRUSH_DATA31 0x14fc
+#define R128_BRUSH_DATA32 0x1500
+#define R128_BRUSH_DATA33 0x1504
+#define R128_BRUSH_DATA34 0x1508
+#define R128_BRUSH_DATA35 0x150c
+#define R128_BRUSH_DATA36 0x1510
+#define R128_BRUSH_DATA37 0x1514
+#define R128_BRUSH_DATA38 0x1518
+#define R128_BRUSH_DATA39 0x151c
+#define R128_BRUSH_DATA4 0x1490
+#define R128_BRUSH_DATA40 0x1520
+#define R128_BRUSH_DATA41 0x1524
+#define R128_BRUSH_DATA42 0x1528
+#define R128_BRUSH_DATA43 0x152c
+#define R128_BRUSH_DATA44 0x1530
+#define R128_BRUSH_DATA45 0x1534
+#define R128_BRUSH_DATA46 0x1538
+#define R128_BRUSH_DATA47 0x153c
+#define R128_BRUSH_DATA48 0x1540
+#define R128_BRUSH_DATA49 0x1544
+#define R128_BRUSH_DATA5 0x1494
+#define R128_BRUSH_DATA50 0x1548
+#define R128_BRUSH_DATA51 0x154c
+#define R128_BRUSH_DATA52 0x1550
+#define R128_BRUSH_DATA53 0x1554
+#define R128_BRUSH_DATA54 0x1558
+#define R128_BRUSH_DATA55 0x155c
+#define R128_BRUSH_DATA56 0x1560
+#define R128_BRUSH_DATA57 0x1564
+#define R128_BRUSH_DATA58 0x1568
+#define R128_BRUSH_DATA59 0x156c
+#define R128_BRUSH_DATA6 0x1498
+#define R128_BRUSH_DATA60 0x1570
+#define R128_BRUSH_DATA61 0x1574
+#define R128_BRUSH_DATA62 0x1578
+#define R128_BRUSH_DATA63 0x157c
+#define R128_BRUSH_DATA7 0x149c
+#define R128_BRUSH_DATA8 0x14a0
+#define R128_BRUSH_DATA9 0x14a4
+#define R128_BRUSH_SCALE 0x1470
+#define R128_BRUSH_Y_X 0x1474
+#define R128_BUS_CNTL 0x0030
+# define R128_BUS_MASTER_DIS (1 << 6)
+# define R128_BUS_RD_DISCARD_EN (1 << 24)
+# define R128_BUS_RD_ABORT_EN (1 << 25)
+# define R128_BUS_MSTR_DISCONNECT_EN (1 << 28)
+# define R128_BUS_WRT_BURST (1 << 29)
+# define R128_BUS_READ_BURST (1 << 30)
+#define R128_BUS_CNTL1 0x0034
+# define R128_BUS_WAIT_ON_LOCK_EN (1 << 4)
+
+#define R128_CACHE_CNTL 0x1724
+#define R128_CACHE_LINE 0x0f0c /* PCI */
+#define R128_CAP0_TRIG_CNTL 0x0950 /* ? */
+#define R128_CAP1_TRIG_CNTL 0x09c0 /* ? */
+#define R128_CAPABILITIES_ID 0x0f50 /* PCI */
+#define R128_CAPABILITIES_PTR 0x0f34 /* PCI */
+#define R128_CLK_PIN_CNTL 0x0001 /* PLL */
+#define R128_CLOCK_CNTL_DATA 0x000c
+#define R128_CLOCK_CNTL_INDEX 0x0008
+# define R128_PLL_WR_EN (1 << 7)
+# define R128_PLL_DIV_SEL (3 << 8)
+#define R128_CLR_CMP_CLR_3D 0x1a24
+#define R128_CLR_CMP_CLR_DST 0x15c8
+#define R128_CLR_CMP_CLR_SRC 0x15c4
+#define R128_CLR_CMP_CNTL 0x15c0
+# define R128_SRC_CMP_EQ_COLOR (4 << 0)
+# define R128_SRC_CMP_NEQ_COLOR (5 << 0)
+# define R128_CLR_CMP_SRC_SOURCE (1 << 24)
+#define R128_CLR_CMP_MASK 0x15cc
+# define R128_CLR_CMP_MSK 0xffffffff
+#define R128_CLR_CMP_MASK_3D 0x1A28
+#define R128_COMMAND 0x0f04 /* PCI */
+#define R128_COMPOSITE_SHADOW_ID 0x1a0c
+#define R128_CONFIG_APER_0_BASE 0x0100
+#define R128_CONFIG_APER_1_BASE 0x0104
+#define R128_CONFIG_APER_SIZE 0x0108
+#define R128_CONFIG_BONDS 0x00e8
+#define R128_CONFIG_CNTL 0x00e0
+# define APER_0_BIG_ENDIAN_16BPP_SWAP (1 << 0)
+# define APER_0_BIG_ENDIAN_32BPP_SWAP (2 << 0)
+#define R128_CONFIG_MEMSIZE 0x00f8
+#define R128_CONFIG_MEMSIZE_EMBEDDED 0x0114
+#define R128_CONFIG_REG_1_BASE 0x010c
+#define R128_CONFIG_REG_APER_SIZE 0x0110
+#define R128_CONFIG_XSTRAP 0x00e4
+#define R128_CONSTANT_COLOR_C 0x1d34
+# define R128_CONSTANT_COLOR_MASK 0x00ffffff
+# define R128_CONSTANT_COLOR_ONE 0x00ffffff
+# define R128_CONSTANT_COLOR_ZERO 0x00000000
+#define R128_CRC_CMDFIFO_ADDR 0x0740
+#define R128_CRC_CMDFIFO_DOUT 0x0744
+#define R128_CRTC_CRNT_FRAME 0x0214
+#define R128_CRTC_DEBUG 0x021c
+#define R128_CRTC_EXT_CNTL 0x0054
+# define R128_CRTC_VGA_XOVERSCAN (1 << 0)
+# define R128_VGA_ATI_LINEAR (1 << 3)
+# define R128_XCRT_CNT_EN (1 << 6)
+# define R128_CRTC_HSYNC_DIS (1 << 8)
+# define R128_CRTC_VSYNC_DIS (1 << 9)
+# define R128_CRTC_DISPLAY_DIS (1 << 10)
+# define R128_CRTC_CRT_ON (1 << 15)
+# define R128_FP_OUT_EN (1 << 22)
+# define R128_FP_ACTIVE (1 << 23)
+#define R128_CRTC_EXT_CNTL_DPMS_BYTE 0x0055
+# define R128_CRTC_HSYNC_DIS_BYTE (1 << 0)
+# define R128_CRTC_VSYNC_DIS_BYTE (1 << 1)
+# define R128_CRTC_DISPLAY_DIS_BYTE (1 << 2)
+#define R128_CRTC_GEN_CNTL 0x0050
+# define R128_CRTC_DBL_SCAN_EN (1 << 0)
+# define R128_CRTC_INTERLACE_EN (1 << 1)
+# define R128_CRTC_CSYNC_EN (1 << 4)
+# define R128_CRTC_CUR_EN (1 << 16)
+# define R128_CRTC_CUR_MODE_MASK (7 << 17)
+# define R128_CRTC_ICON_EN (1 << 20)
+# define R128_CRTC_EXT_DISP_EN (1 << 24)
+# define R128_CRTC_EN (1 << 25)
+# define R128_CRTC_DISP_REQ_EN_B (1 << 26)
+#define R128_CRTC_GUI_TRIG_VLINE 0x0218
+#define R128_CRTC_H_SYNC_STRT_WID 0x0204
+# define R128_CRTC_H_SYNC_STRT_PIX (0x07 << 0)
+# define R128_CRTC_H_SYNC_STRT_CHAR (0x1ff << 3)
+# define R128_CRTC_H_SYNC_STRT_CHAR_SHIFT 3
+# define R128_CRTC_H_SYNC_WID (0x3f << 16)
+# define R128_CRTC_H_SYNC_WID_SHIFT 16
+# define R128_CRTC_H_SYNC_POL (1 << 23)
+#define R128_CRTC_H_TOTAL_DISP 0x0200
+# define R128_CRTC_H_TOTAL (0x01ff << 0)
+# define R128_CRTC_H_TOTAL_SHIFT 0
+# define R128_CRTC_H_DISP (0x00ff << 16)
+# define R128_CRTC_H_DISP_SHIFT 16
+#define R128_CRTC_OFFSET 0x0224
+#define R128_CRTC_OFFSET_CNTL 0x0228
+#define R128_CRTC_PITCH 0x022c
+#define R128_CRTC_STATUS 0x005c
+# define R128_CRTC_VBLANK_SAVE (1 << 1)
+#define R128_CRTC_V_SYNC_STRT_WID 0x020c
+# define R128_CRTC_V_SYNC_STRT (0x7ff << 0)
+# define R128_CRTC_V_SYNC_STRT_SHIFT 0
+# define R128_CRTC_V_SYNC_WID (0x1f << 16)
+# define R128_CRTC_V_SYNC_WID_SHIFT 16
+# define R128_CRTC_V_SYNC_POL (1 << 23)
+#define R128_CRTC_V_TOTAL_DISP 0x0208
+# define R128_CRTC_V_TOTAL (0x07ff << 0)
+# define R128_CRTC_V_TOTAL_SHIFT 0
+# define R128_CRTC_V_DISP (0x07ff << 16)
+# define R128_CRTC_V_DISP_SHIFT 16
+#define R128_CRTC_VLINE_CRNT_VLINE 0x0210
+# define R128_CRTC_CRNT_VLINE_MASK (0x7ff << 16)
+#define R128_CRTC2_CRNT_FRAME 0x0314
+#define R128_CRTC2_DEBUG 0x031c
+#define R128_CRTC2_GEN_CNTL 0x03f8
+#define R128_CRTC2_GUI_TRIG_VLINE 0x0318
+#define R128_CRTC2_H_SYNC_STRT_WID 0x0304
+#define R128_CRTC2_H_TOTAL_DISP 0x0300
+#define R128_CRTC2_OFFSET 0x0324
+#define R128_CRTC2_OFFSET_CNTL 0x0328
+#define R128_CRTC2_PITCH 0x032c
+#define R128_CRTC2_STATUS 0x03fc
+#define R128_CRTC2_V_SYNC_STRT_WID 0x030c
+#define R128_CRTC2_V_TOTAL_DISP 0x0308
+#define R128_CRTC2_VLINE_CRNT_VLINE 0x0310
+#define R128_CRTC8_DATA 0x03d5 /* VGA, 0x3b5 */
+#define R128_CRTC8_IDX 0x03d4 /* VGA, 0x3b4 */
+#define R128_CUR_CLR0 0x026c
+#define R128_CUR_CLR1 0x0270
+#define R128_CUR_HORZ_VERT_OFF 0x0268
+#define R128_CUR_HORZ_VERT_POSN 0x0264
+#define R128_CUR_OFFSET 0x0260
+# define R128_CUR_LOCK (1 << 31)
+
+#define R128_DAC_CNTL 0x0058
+# define R128_DAC_RANGE_CNTL (3 << 0)
+# define R128_DAC_BLANKING (1 << 2)
+# define R128_DAC_CRT_SEL_CRTC2 (1 << 4)
+# define R128_DAC_PALETTE_ACC_CTL (1 << 5)
+# define R128_DAC_8BIT_EN (1 << 8)
+# define R128_DAC_VGA_ADR_EN (1 << 13)
+# define R128_DAC_MASK_ALL (0xff << 24)
+#define R128_DAC_CRC_SIG 0x02cc
+#define R128_DAC_DATA 0x03c9 /* VGA */
+#define R128_DAC_MASK 0x03c6 /* VGA */
+#define R128_DAC_R_INDEX 0x03c7 /* VGA */
+#define R128_DAC_W_INDEX 0x03c8 /* VGA */
+#define R128_DDA_CONFIG 0x02e0
+#define R128_DDA_ON_OFF 0x02e4
+#define R128_DEFAULT_OFFSET 0x16e0
+#define R128_DEFAULT_PITCH 0x16e4
+#define R128_DEFAULT_SC_BOTTOM_RIGHT 0x16e8
+# define R128_DEFAULT_SC_RIGHT_MAX (0x1fff << 0)
+# define R128_DEFAULT_SC_BOTTOM_MAX (0x1fff << 16)
+#define R128_DESTINATION_3D_CLR_CMP_VAL 0x1820
+#define R128_DESTINATION_3D_CLR_CMP_MSK 0x1824
+#define R128_DEVICE_ID 0x0f02 /* PCI */
+#define R128_DP_BRUSH_BKGD_CLR 0x1478
+#define R128_DP_BRUSH_FRGD_CLR 0x147c
+#define R128_DP_CNTL 0x16c0
+# define R128_DST_X_LEFT_TO_RIGHT (1 << 0)
+# define R128_DST_Y_TOP_TO_BOTTOM (1 << 1)
+#define R128_DP_CNTL_XDIR_YDIR_YMAJOR 0x16d0
+# define R128_DST_Y_MAJOR (1 << 2)
+# define R128_DST_Y_DIR_TOP_TO_BOTTOM (1 << 15)
+# define R128_DST_X_DIR_LEFT_TO_RIGHT (1 << 31)
+#define R128_DP_DATATYPE 0x16c4
+# define R128_HOST_BIG_ENDIAN_EN (1 << 29)
+#define R128_DP_GUI_MASTER_CNTL 0x146c
+# define R128_GMC_SRC_PITCH_OFFSET_CNTL (1 << 0)
+# define R128_GMC_DST_PITCH_OFFSET_CNTL (1 << 1)
+# define R128_GMC_SRC_CLIPPING (1 << 2)
+# define R128_GMC_DST_CLIPPING (1 << 3)
+# define R128_GMC_BRUSH_DATATYPE_MASK (0x0f << 4)
+# define R128_GMC_BRUSH_8X8_MONO_FG_BG (0 << 4)
+# define R128_GMC_BRUSH_8X8_MONO_FG_LA (1 << 4)
+# define R128_GMC_BRUSH_1X8_MONO_FG_BG (4 << 4)
+# define R128_GMC_BRUSH_1X8_MONO_FG_LA (5 << 4)
+# define R128_GMC_BRUSH_32x1_MONO_FG_BG (6 << 4)
+# define R128_GMC_BRUSH_32x1_MONO_FG_LA (7 << 4)
+# define R128_GMC_BRUSH_32x32_MONO_FG_BG (8 << 4)
+# define R128_GMC_BRUSH_32x32_MONO_FG_LA (9 << 4)
+# define R128_GMC_BRUSH_8x8_COLOR (10 << 4)
+# define R128_GMC_BRUSH_1X8_COLOR (12 << 4)
+# define R128_GMC_BRUSH_SOLID_COLOR (13 << 4)
+# define R128_GMC_BRUSH_NONE (15 << 4)
+# define R128_GMC_DST_8BPP_CI (2 << 8)
+# define R128_GMC_DST_15BPP (3 << 8)
+# define R128_GMC_DST_16BPP (4 << 8)
+# define R128_GMC_DST_24BPP (5 << 8)
+# define R128_GMC_DST_32BPP (6 << 8)
+# define R128_GMC_DST_8BPP_RGB (7 << 8)
+# define R128_GMC_DST_Y8 (8 << 8)
+# define R128_GMC_DST_RGB8 (9 << 8)
+# define R128_GMC_DST_VYUY (11 << 8)
+# define R128_GMC_DST_YVYU (12 << 8)
+# define R128_GMC_DST_AYUV444 (14 << 8)
+# define R128_GMC_DST_ARGB4444 (15 << 8)
+# define R128_GMC_DST_DATATYPE_MASK (0x0f << 8)
+# define R128_GMC_DST_DATATYPE_SHIFT 8
+# define R128_GMC_SRC_DATATYPE_MASK (3 << 12)
+# define R128_GMC_SRC_DATATYPE_MONO_FG_BG (0 << 12)
+# define R128_GMC_SRC_DATATYPE_MONO_FG_LA (1 << 12)
+# define R128_GMC_SRC_DATATYPE_COLOR (3 << 12)
+# define R128_GMC_BYTE_PIX_ORDER (1 << 14)
+# define R128_GMC_BYTE_MSB_TO_LSB (0 << 14)
+# define R128_GMC_BYTE_LSB_TO_MSB (1 << 14)
+# define R128_GMC_CONVERSION_TEMP (1 << 15)
+# define R128_GMC_CONVERSION_TEMP_6500 (0 << 15)
+# define R128_GMC_CONVERSION_TEMP_9300 (1 << 15)
+# define R128_GMC_ROP3_MASK (0xff << 16)
+# define R128_DP_SRC_SOURCE_MASK (7 << 24)
+# define R128_DP_SRC_SOURCE_MEMORY (2 << 24)
+# define R128_DP_SRC_SOURCE_HOST_DATA (3 << 24)
+# define R128_GMC_3D_FCN_EN (1 << 27)
+# define R128_GMC_CLR_CMP_CNTL_DIS (1 << 28)
+# define R128_GMC_AUX_CLIP_DIS (1 << 29)
+# define R128_GMC_WR_MSK_DIS (1 << 30)
+# define R128_GMC_LD_BRUSH_Y_X (1 << 31)
+# define R128_ROP3_ZERO 0x00000000
+# define R128_ROP3_DSa 0x00880000
+# define R128_ROP3_SDna 0x00440000
+# define R128_ROP3_S 0x00cc0000
+# define R128_ROP3_DSna 0x00220000
+# define R128_ROP3_D 0x00aa0000
+# define R128_ROP3_DSx 0x00660000
+# define R128_ROP3_DSo 0x00ee0000
+# define R128_ROP3_DSon 0x00110000
+# define R128_ROP3_DSxn 0x00990000
+# define R128_ROP3_Dn 0x00550000
+# define R128_ROP3_SDno 0x00dd0000
+# define R128_ROP3_Sn 0x00330000
+# define R128_ROP3_DSno 0x00bb0000
+# define R128_ROP3_DSan 0x00770000
+# define R128_ROP3_ONE 0x00ff0000
+# define R128_ROP3_DPa 0x00a00000
+# define R128_ROP3_PDna 0x00500000
+# define R128_ROP3_P 0x00f00000
+# define R128_ROP3_DPna 0x000a0000
+# define R128_ROP3_D 0x00aa0000
+# define R128_ROP3_DPx 0x005a0000
+# define R128_ROP3_DPo 0x00fa0000
+# define R128_ROP3_DPon 0x00050000
+# define R128_ROP3_PDxn 0x00a50000
+# define R128_ROP3_PDno 0x00f50000
+# define R128_ROP3_Pn 0x000f0000
+# define R128_ROP3_DPno 0x00af0000
+# define R128_ROP3_DPan 0x005f0000
+
+
+#define R128_DP_GUI_MASTER_CNTL_C 0x1c84
+#define R128_DP_MIX 0x16c8
+#define R128_DP_SRC_BKGD_CLR 0x15dc
+#define R128_DP_SRC_FRGD_CLR 0x15d8
+#define R128_DP_WRITE_MASK 0x16cc
+#define R128_DST_BRES_DEC 0x1630
+#define R128_DST_BRES_ERR 0x1628
+#define R128_DST_BRES_INC 0x162c
+#define R128_DST_BRES_LNTH 0x1634
+#define R128_DST_BRES_LNTH_SUB 0x1638
+#define R128_DST_HEIGHT 0x1410
+#define R128_DST_HEIGHT_WIDTH 0x143c
+#define R128_DST_HEIGHT_WIDTH_8 0x158c
+#define R128_DST_HEIGHT_WIDTH_BW 0x15b4
+#define R128_DST_HEIGHT_Y 0x15a0
+#define R128_DST_OFFSET 0x1404
+#define R128_DST_PITCH 0x1408
+#define R128_DST_PITCH_OFFSET 0x142c
+#define R128_DST_PITCH_OFFSET_C 0x1c80
+# define R128_PITCH_SHIFT 21
+# define R128_DST_TILE (1 << 31)
+#define R128_DST_WIDTH 0x140c
+#define R128_DST_WIDTH_HEIGHT 0x1598
+#define R128_DST_WIDTH_X 0x1588
+#define R128_DST_WIDTH_X_INCY 0x159c
+#define R128_DST_X 0x141c
+#define R128_DST_X_SUB 0x15a4
+#define R128_DST_X_Y 0x1594
+#define R128_DST_Y 0x1420
+#define R128_DST_Y_SUB 0x15a8
+#define R128_DST_Y_X 0x1438
+
+#define R128_EXT_MEM_CNTL 0x0144
+
+#define R128_FCP_CNTL 0x0012 /* PLL */
+#define R128_FLUSH_1 0x1704
+#define R128_FLUSH_2 0x1708
+#define R128_FLUSH_3 0x170c
+#define R128_FLUSH_4 0x1710
+#define R128_FLUSH_5 0x1714
+#define R128_FLUSH_6 0x1718
+#define R128_FLUSH_7 0x171c
+#define R128_FOG_3D_TABLE_START 0x1810
+#define R128_FOG_3D_TABLE_END 0x1814
+#define R128_FOG_3D_TABLE_DENSITY 0x181c
+#define R128_FOG_TABLE_INDEX 0x1a14
+#define R128_FOG_TABLE_DATA 0x1a18
+#define R128_FP_CRTC_H_TOTAL_DISP 0x0250
+#define R128_FP_CRTC_V_TOTAL_DISP 0x0254
+#define R128_FP_GEN_CNTL 0x0284
+# define R128_FP_FPON (1 << 0)
+# define R128_FP_BLANK_DIS (1 << 1)
+# define R128_FP_TDMS_EN (1 << 2)
+# define R128_FP_DETECT_SENSE (1 << 8)
+# define R128_FP_SEL_CRTC2 (1 << 13)
+# define R128_FP_CRTC_DONT_SHADOW_VPAR (1 << 16)
+# define R128_FP_CRTC_DONT_SHADOW_HEND (1 << 17)
+# define R128_FP_CRTC_USE_SHADOW_VEND (1 << 18)
+# define R128_FP_CRTC_USE_SHADOW_ROWCUR (1 << 19)
+# define R128_FP_CRTC_HORZ_DIV2_EN (1 << 20)
+# define R128_FP_CRTC_HOR_CRT_DIV2_DIS (1 << 21)
+# define R128_FP_CRT_SYNC_SEL (1 << 23)
+# define R128_FP_USE_SHADOW_EN (1 << 24)
+#define R128_FP_H_SYNC_STRT_WID 0x02c4
+#define R128_FP_HORZ_STRETCH 0x028c
+# define R128_HORZ_STRETCH_RATIO_MASK 0xffff
+# define R128_HORZ_STRETCH_RATIO_SHIFT 0
+# define R128_HORZ_STRETCH_RATIO_MAX 4096
+# define R128_HORZ_PANEL_SIZE (0xff << 16)
+# define R128_HORZ_PANEL_SHIFT 16
+# define R128_AUTO_HORZ_RATIO (0 << 24)
+# define R128_HORZ_STRETCH_PIXREP (0 << 25)
+# define R128_HORZ_STRETCH_BLEND (1 << 25)
+# define R128_HORZ_STRETCH_ENABLE (1 << 26)
+# define R128_HORZ_FP_LOOP_STRETCH (0x7 << 27)
+# define R128_HORZ_STRETCH_RESERVED (1 << 30)
+# define R128_HORZ_AUTO_RATIO_FIX_EN (1 << 31)
+
+#define R128_FP_PANEL_CNTL 0x0288
+# define R128_FP_DIGON (1 << 0)
+# define R128_FP_BLON (1 << 1)
+#define R128_FP_V_SYNC_STRT_WID 0x02c8
+#define R128_FP_VERT_STRETCH 0x0290
+# define R128_VERT_PANEL_SIZE (0x7ff << 0)
+# define R128_VERT_PANEL_SHIFT 0
+# define R128_VERT_STRETCH_RATIO_MASK 0x3ff
+# define R128_VERT_STRETCH_RATIO_SHIFT 11
+# define R128_VERT_STRETCH_RATIO_MAX 1024
+# define R128_VERT_STRETCH_ENABLE (1 << 24)
+# define R128_VERT_STRETCH_LINEREP (0 << 25)
+# define R128_VERT_STRETCH_BLEND (1 << 25)
+# define R128_VERT_AUTO_RATIO_EN (1 << 26)
+# define R128_VERT_STRETCH_RESERVED 0xf8e00000
+
+#define R128_GEN_INT_CNTL 0x0040
+#define R128_GEN_INT_STATUS 0x0044
+# define R128_VSYNC_INT_AK (1 << 2)
+# define R128_VSYNC_INT (1 << 2)
+#define R128_GEN_RESET_CNTL 0x00f0
+# define R128_SOFT_RESET_GUI (1 << 0)
+# define R128_SOFT_RESET_VCLK (1 << 8)
+# define R128_SOFT_RESET_PCLK (1 << 9)
+# define R128_SOFT_RESET_DISPENG_XCLK (1 << 11)
+# define R128_SOFT_RESET_MEMCTLR_XCLK (1 << 12)
+#define R128_GENENB 0x03c3 /* VGA */
+#define R128_GENFC_RD 0x03ca /* VGA */
+#define R128_GENFC_WT 0x03da /* VGA, 0x03ba */
+#define R128_GENMO_RD 0x03cc /* VGA */
+#define R128_GENMO_WT 0x03c2 /* VGA */
+#define R128_GENS0 0x03c2 /* VGA */
+#define R128_GENS1 0x03da /* VGA, 0x03ba */
+#define R128_GPIO_MONID 0x0068
+# define R128_GPIO_MONID_A_0 (1 << 0)
+# define R128_GPIO_MONID_A_1 (1 << 1)
+# define R128_GPIO_MONID_A_2 (1 << 2)
+# define R128_GPIO_MONID_A_3 (1 << 3)
+# define R128_GPIO_MONID_Y_0 (1 << 8)
+# define R128_GPIO_MONID_Y_1 (1 << 9)
+# define R128_GPIO_MONID_Y_2 (1 << 10)
+# define R128_GPIO_MONID_Y_3 (1 << 11)
+# define R128_GPIO_MONID_EN_0 (1 << 16)
+# define R128_GPIO_MONID_EN_1 (1 << 17)
+# define R128_GPIO_MONID_EN_2 (1 << 18)
+# define R128_GPIO_MONID_EN_3 (1 << 19)
+# define R128_GPIO_MONID_MASK_0 (1 << 24)
+# define R128_GPIO_MONID_MASK_1 (1 << 25)
+# define R128_GPIO_MONID_MASK_2 (1 << 26)
+# define R128_GPIO_MONID_MASK_3 (1 << 27)
+#define R128_GPIO_MONIDB 0x006c
+#define R128_GRPH8_DATA 0x03cf /* VGA */
+#define R128_GRPH8_IDX 0x03ce /* VGA */
+#define R128_GUI_DEBUG0 0x16a0
+#define R128_GUI_DEBUG1 0x16a4
+#define R128_GUI_DEBUG2 0x16a8
+#define R128_GUI_DEBUG3 0x16ac
+#define R128_GUI_DEBUG4 0x16b0
+#define R128_GUI_DEBUG5 0x16b4
+#define R128_GUI_DEBUG6 0x16b8
+#define R128_GUI_PROBE 0x16bc
+#define R128_GUI_SCRATCH_REG0 0x15e0
+#define R128_GUI_SCRATCH_REG1 0x15e4
+#define R128_GUI_SCRATCH_REG2 0x15e8
+#define R128_GUI_SCRATCH_REG3 0x15ec
+#define R128_GUI_SCRATCH_REG4 0x15f0
+#define R128_GUI_SCRATCH_REG5 0x15f4
+#define R128_GUI_STAT 0x1740
+# define R128_GUI_FIFOCNT_MASK 0x0fff
+# define R128_GUI_ACTIVE (1 << 31)
+
+#define R128_HEADER 0x0f0e /* PCI */
+#define R128_HOST_DATA0 0x17c0
+#define R128_HOST_DATA1 0x17c4
+#define R128_HOST_DATA2 0x17c8
+#define R128_HOST_DATA3 0x17cc
+#define R128_HOST_DATA4 0x17d0
+#define R128_HOST_DATA5 0x17d4
+#define R128_HOST_DATA6 0x17d8
+#define R128_HOST_DATA7 0x17dc
+#define R128_HOST_DATA_LAST 0x17e0
+#define R128_HOST_PATH_CNTL 0x0130
+#define R128_HTOTAL_CNTL 0x0009 /* PLL */
+#define R128_HW_DEBUG 0x0128
+#define R128_HW_DEBUG2 0x011c
+
+#define R128_I2C_CNTL_1 0x0094 /* ? */
+#define R128_INTERRUPT_LINE 0x0f3c /* PCI */
+#define R128_INTERRUPT_PIN 0x0f3d /* PCI */
+#define R128_IO_BASE 0x0f14 /* PCI */
+
+#define R128_LATENCY 0x0f0d /* PCI */
+#define R128_LEAD_BRES_DEC 0x1608
+#define R128_LEAD_BRES_ERR 0x1600
+#define R128_LEAD_BRES_INC 0x1604
+#define R128_LEAD_BRES_LNTH 0x161c
+#define R128_LEAD_BRES_LNTH_SUB 0x1624
+#define R128_LVDS_GEN_CNTL 0x02d0
+# define R128_LVDS_ON (1 << 0)
+# define R128_LVDS_DISPLAY_DIS (1 << 1)
+# define R128_LVDS_EN (1 << 7)
+# define R128_LVDS_DIGON (1 << 18)
+# define R128_LVDS_BLON (1 << 19)
+# define R128_LVDS_SEL_CRTC2 (1 << 23)
+# define R128_HSYNC_DELAY_SHIFT 28
+# define R128_HSYNC_DELAY_MASK (0xf << 28)
+
+#define R128_MAX_LATENCY 0x0f3f /* PCI */
+#define R128_MCLK_CNTL 0x000f /* PLL */
+# define R128_FORCE_GCP (1 << 16)
+# define R128_FORCE_PIPE3D_CP (1 << 17)
+# define R128_FORCE_RCP (1 << 18)
+#define R128_MDGPIO_A_REG 0x01ac
+#define R128_MDGPIO_EN_REG 0x01b0
+#define R128_MDGPIO_MASK 0x0198
+#define R128_MDGPIO_Y_REG 0x01b4
+#define R128_MEM_ADDR_CONFIG 0x0148
+#define R128_MEM_BASE 0x0f10 /* PCI */
+#define R128_MEM_CNTL 0x0140
+#define R128_MEM_INIT_LAT_TIMER 0x0154
+#define R128_MEM_INTF_CNTL 0x014c
+#define R128_MEM_SDRAM_MODE_REG 0x0158
+#define R128_MEM_STR_CNTL 0x0150
+#define R128_MEM_VGA_RP_SEL 0x003c
+#define R128_MEM_VGA_WP_SEL 0x0038
+#define R128_MIN_GRANT 0x0f3e /* PCI */
+#define R128_MM_DATA 0x0004
+#define R128_MM_INDEX 0x0000
+#define R128_MPLL_CNTL 0x000e /* PLL */
+#define R128_MPP_TB_CONFIG 0x01c0 /* ? */
+#define R128_MPP_GP_CONFIG 0x01c8 /* ? */
+
+#define R128_N_VIF_COUNT 0x0248
+
+#define R128_OVR_CLR 0x0230
+#define R128_OVR_WID_LEFT_RIGHT 0x0234
+#define R128_OVR_WID_TOP_BOTTOM 0x0238
+
+/* first overlay unit (there is only one) */
+
+#define R128_OV0_Y_X_START 0x0400
+#define R128_OV0_Y_X_END 0x0404
+#define R128_OV0_EXCLUSIVE_HORZ 0x0408
+# define R128_EXCL_HORZ_START_MASK 0x000000ff
+# define R128_EXCL_HORZ_END_MASK 0x0000ff00
+# define R128_EXCL_HORZ_BACK_PORCH_MASK 0x00ff0000
+# define R128_EXCL_HORZ_EXCLUSIVE_EN 0x80000000
+#define R128_OV0_EXCLUSIVE_VERT 0x040C
+# define R128_EXCL_VERT_START_MASK 0x000003ff
+# define R128_EXCL_VERT_END_MASK 0x03ff0000
+#define R128_OV0_REG_LOAD_CNTL 0x0410
+# define R128_REG_LD_CTL_LOCK 0x00000001L
+# define R128_REG_LD_CTL_VBLANK_DURING_LOCK 0x00000002L
+# define R128_REG_LD_CTL_STALL_GUI_UNTIL_FLIP 0x00000004L
+# define R128_REG_LD_CTL_LOCK_READBACK 0x00000008L
+#define R128_OV0_SCALE_CNTL 0x0420
+# define R128_SCALER_PIX_EXPAND 0x00000001L
+# define R128_SCALER_Y2R_TEMP 0x00000002L
+# define R128_SCALER_HORZ_PICK_NEAREST 0x00000003L
+# define R128_SCALER_VERT_PICK_NEAREST 0x00000004L
+# define R128_SCALER_SIGNED_UV 0x00000010L
+# define R128_SCALER_GAMMA_SEL_MASK 0x00000060L
+# define R128_SCALER_GAMMA_SEL_BRIGHT 0x00000000L
+# define R128_SCALER_GAMMA_SEL_G22 0x00000020L
+# define R128_SCALER_GAMMA_SEL_G18 0x00000040L
+# define R128_SCALER_GAMMA_SEL_G14 0x00000060L
+# define R128_SCALER_COMCORE_SHIFT_UP_ONE 0x00000080L
+# define R128_SCALER_SURFAC_FORMAT 0x00000f00L
+# define R128_SCALER_SOURCE_15BPP 0x00000300L
+# define R128_SCALER_SOURCE_16BPP 0x00000400L
+# define R128_SCALER_SOURCE_32BPP 0x00000600L
+# define R128_SCALER_SOURCE_YUV9 0x00000900L
+# define R128_SCALER_SOURCE_YUV12 0x00000A00L
+# define R128_SCALER_SOURCE_VYUY422 0x00000B00L
+# define R128_SCALER_SOURCE_YVYU422 0x00000C00L
+# define R128_SCALER_SMART_SWITCH 0x00008000L
+# define R128_SCALER_BURST_PER_PLANE 0x00ff0000L
+# define R128_SCALER_DOUBLE_BUFFER 0x01000000L
+# define R128_SCALER_DIS_LIMIT 0x08000000L
+# define R128_SCALER_PRG_LOAD_START 0x10000000L
+# define R128_SCALER_INT_EMU 0x20000000L
+# define R128_SCALER_ENABLE 0x40000000L
+# define R128_SCALER_SOFT_RESET 0x80000000L
+#define R128_OV0_V_INC 0x0424
+#define R128_OV0_P1_V_ACCUM_INIT 0x0428
+# define R128_OV0_P1_MAX_LN_IN_PER_LN_OUT 0x00000003L
+# define R128_OV0_P1_V_ACCUM_INIT_MASK 0x01ff8000L
+#define R128_OV0_P23_V_ACCUM_INIT 0x042C
+#define R128_OV0_P1_BLANK_LINES_AT_TOP 0x0430
+# define R128_P1_BLNK_LN_AT_TOP_M1_MASK 0x00000fffL
+# define R128_P1_ACTIVE_LINES_M1 0x0fff0000L
+#define R128_OV0_P23_BLANK_LINES_AT_TOP 0x0434
+# define R128_P23_BLNK_LN_AT_TOP_M1_MASK 0x000007ffL
+# define R128_P23_ACTIVE_LINES_M1 0x07ff0000L
+#define R128_OV0_VID_BUF0_BASE_ADRS 0x0440
+# define R128_VIF_BUF0_PITCH_SEL 0x00000001L
+# define R128_VIF_BUF0_TILE_ADRS 0x00000002L
+# define R128_VIF_BUF0_BASE_ADRS_MASK 0x03fffff0L
+# define R128_VIF_BUF0_1ST_LINE_LSBS_MASK 0x48000000L
+#define R128_OV0_VID_BUF1_BASE_ADRS 0x0444
+# define R128_VIF_BUF1_PITCH_SEL 0x00000001L
+# define R128_VIF_BUF1_TILE_ADRS 0x00000002L
+# define R128_VIF_BUF1_BASE_ADRS_MASK 0x03fffff0L
+# define R128_VIF_BUF1_1ST_LINE_LSBS_MASK 0x48000000L
+#define R128_OV0_VID_BUF2_BASE_ADRS 0x0448
+# define R128_VIF_BUF2_PITCH_SEL 0x00000001L
+# define R128_VIF_BUF2_TILE_ADRS 0x00000002L
+# define R128_VIF_BUF2_BASE_ADRS_MASK 0x03fffff0L
+# define R128_VIF_BUF2_1ST_LINE_LSBS_MASK 0x48000000L
+#define R128_OV0_VID_BUF3_BASE_ADRS 0x044C
+#define R128_OV0_VID_BUF4_BASE_ADRS 0x0450
+#define R128_OV0_VID_BUF5_BASE_ADRS 0x0454
+#define R128_OV0_VID_BUF_PITCH0_VALUE 0x0460
+#define R128_OV0_VID_BUF_PITCH1_VALUE 0x0464
+#define R128_OV0_AUTO_FLIP_CNTL 0x0470
+#define R128_OV0_DEINTERLACE_PATTERN 0x0474
+#define R128_OV0_H_INC 0x0480
+#define R128_OV0_STEP_BY 0x0484
+#define R128_OV0_P1_H_ACCUM_INIT 0x0488
+#define R128_OV0_P23_H_ACCUM_INIT 0x048C
+#define R128_OV0_P1_X_START_END 0x0494
+#define R128_OV0_P2_X_START_END 0x0498
+#define R128_OV0_P3_X_START_END 0x049C
+#define R128_OV0_FILTER_CNTL 0x04A0
+#define R128_OV0_FOUR_TAP_COEF_0 0x04B0
+#define R128_OV0_FOUR_TAP_COEF_1 0x04B4
+#define R128_OV0_FOUR_TAP_COEF_2 0x04B8
+#define R128_OV0_FOUR_TAP_COEF_3 0x04BC
+#define R128_OV0_FOUR_TAP_COEF_4 0x04C0
+#define R128_OV0_COLOUR_CNTL 0x04E0
+#define R128_OV0_VIDEO_KEY_CLR 0x04E4
+#define R128_OV0_VIDEO_KEY_MSK 0x04E8
+#define R128_OV0_GRAPHICS_KEY_CLR 0x04EC
+#define R128_OV0_GRAPHICS_KEY_MSK 0x04F0
+#define R128_OV0_KEY_CNTL 0x04F4
+# define R128_VIDEO_KEY_FN_MASK 0x00000007L
+# define R128_VIDEO_KEY_FN_FALSE 0x00000000L
+# define R128_VIDEO_KEY_FN_TRUE 0x00000001L
+# define R128_VIDEO_KEY_FN_EQ 0x00000004L
+# define R128_VIDEO_KEY_FN_NE 0x00000005L
+# define R128_GRAPHIC_KEY_FN_MASK 0x00000070L
+# define R128_GRAPHIC_KEY_FN_FALSE 0x00000000L
+# define R128_GRAPHIC_KEY_FN_TRUE 0x00000010L
+# define R128_GRAPHIC_KEY_FN_EQ 0x00000040L
+# define R128_GRAPHIC_KEY_FN_NE 0x00000050L
+# define R128_CMP_MIX_MASK 0x00000100L
+# define R128_CMP_MIX_OR 0x00000000L
+# define R128_CMP_MIX_AND 0x00000100L
+#define R128_OV0_TEST 0x04F8
+
+
+#define R128_PALETTE_DATA 0x00b4
+#define R128_PALETTE_INDEX 0x00b0
+#define R128_PC_DEBUG_MODE 0x1760
+#define R128_PC_GUI_CTLSTAT 0x1748
+#define R128_PC_GUI_MODE 0x1744
+# define R128_PC_IGNORE_UNIFY (1 << 5)
+#define R128_PC_MISC_CNTL 0x0188
+#define R128_PC_NGUI_CTLSTAT 0x0184
+# define R128_PC_FLUSH_GUI (3 << 0)
+# define R128_PC_RI_GUI (1 << 2)
+# define R128_PC_FLUSH_ALL 0x00ff
+# define R128_PC_BUSY (1 << 31)
+#define R128_PC_NGUI_MODE 0x0180
+#define R128_PCI_GART_PAGE 0x017c
+#define R128_PLANE_3D_MASK_C 0x1d44
+#define R128_PLL_TEST_CNTL 0x0013 /* PLL */
+#define R128_PMI_CAP_ID 0x0f5c /* PCI */
+#define R128_PMI_DATA 0x0f63 /* PCI */
+#define R128_PMI_NXT_CAP_PTR 0x0f5d /* PCI */
+#define R128_PMI_PMC_REG 0x0f5e /* PCI */
+#define R128_PMI_PMCSR_REG 0x0f60 /* PCI */
+#define R128_PMI_REGISTER 0x0f5c /* PCI */
+#define R128_PPLL_CNTL 0x0002 /* PLL */
+# define R128_PPLL_RESET (1 << 0)
+# define R128_PPLL_SLEEP (1 << 1)
+# define R128_PPLL_ATOMIC_UPDATE_EN (1 << 16)
+# define R128_PPLL_VGA_ATOMIC_UPDATE_EN (1 << 17)
+#define R128_PPLL_DIV_0 0x0004 /* PLL */
+#define R128_PPLL_DIV_1 0x0005 /* PLL */
+#define R128_PPLL_DIV_2 0x0006 /* PLL */
+#define R128_PPLL_DIV_3 0x0007 /* PLL */
+# define R128_PPLL_FB3_DIV_MASK 0x07ff
+# define R128_PPLL_POST3_DIV_MASK 0x00070000
+#define R128_PPLL_REF_DIV 0x0003 /* PLL */
+# define R128_PPLL_REF_DIV_MASK 0x03ff
+# define R128_PPLL_ATOMIC_UPDATE_R (1 << 15) /* same as _W */
+# define R128_PPLL_ATOMIC_UPDATE_W (1 << 15) /* same as _R */
+#define R128_PWR_MNGMT_CNTL_STATUS 0x0f60 /* PCI */
+#define R128_REG_BASE 0x0f18 /* PCI */
+#define R128_REGPROG_INF 0x0f09 /* PCI */
+#define R128_REVISION_ID 0x0f08 /* PCI */
+
+#define R128_SC_BOTTOM 0x164c
+#define R128_SC_BOTTOM_RIGHT 0x16f0
+#define R128_SC_BOTTOM_RIGHT_C 0x1c8c
+#define R128_SC_LEFT 0x1640
+#define R128_SC_RIGHT 0x1644
+#define R128_SC_TOP 0x1648
+#define R128_SC_TOP_LEFT 0x16ec
+#define R128_SC_TOP_LEFT_C 0x1c88
+#define R128_SEQ8_DATA 0x03c5 /* VGA */
+#define R128_SEQ8_IDX 0x03c4 /* VGA */
+#define R128_SNAPSHOT_F_COUNT 0x0244
+#define R128_SNAPSHOT_VH_COUNTS 0x0240
+#define R128_SNAPSHOT_VIF_COUNT 0x024c
+#define R128_SRC_OFFSET 0x15ac
+#define R128_SRC_PITCH 0x15b0
+#define R128_SRC_PITCH_OFFSET 0x1428
+#define R128_SRC_SC_BOTTOM 0x165c
+#define R128_SRC_SC_BOTTOM_RIGHT 0x16f4
+#define R128_SRC_SC_RIGHT 0x1654
+#define R128_SRC_X 0x1414
+#define R128_SRC_X_Y 0x1590
+#define R128_SRC_Y 0x1418
+#define R128_SRC_Y_X 0x1434
+#define R128_STATUS 0x0f06 /* PCI */
+#define R128_SUBPIC_CNTL 0x0540 /* ? */
+#define R128_SUB_CLASS 0x0f0a /* PCI */
+#define R128_SURFACE_DELAY 0x0b00
+#define R128_SURFACE0_INFO 0x0b0c
+#define R128_SURFACE0_LOWER_BOUND 0x0b04
+#define R128_SURFACE0_UPPER_BOUND 0x0b08
+#define R128_SURFACE1_INFO 0x0b1c
+#define R128_SURFACE1_LOWER_BOUND 0x0b14
+#define R128_SURFACE1_UPPER_BOUND 0x0b18
+#define R128_SURFACE2_INFO 0x0b2c
+#define R128_SURFACE2_LOWER_BOUND 0x0b24
+#define R128_SURFACE2_UPPER_BOUND 0x0b28
+#define R128_SURFACE3_INFO 0x0b3c
+#define R128_SURFACE3_LOWER_BOUND 0x0b34
+#define R128_SURFACE3_UPPER_BOUND 0x0b38
+#define R128_SW_SEMAPHORE 0x013c
+
+#define R128_TEST_DEBUG_CNTL 0x0120
+#define R128_TEST_DEBUG_MUX 0x0124
+#define R128_TEST_DEBUG_OUT 0x012c
+#define R128_TMDS_CRC 0x02a0
+#define R128_TMDS_TRANSMITTER_CNTL 0x02a4
+# define R128_TMDS_PLLEN (1 << 0)
+# define R128_TMDS_PLLRST (1 << 1)
+#define R128_TRAIL_BRES_DEC 0x1614
+#define R128_TRAIL_BRES_ERR 0x160c
+#define R128_TRAIL_BRES_INC 0x1610
+#define R128_TRAIL_X 0x1618
+#define R128_TRAIL_X_SUB 0x1620
+
+#define R128_VCLK_ECP_CNTL 0x0008 /* PLL */
+#define R128_VENDOR_ID 0x0f00 /* PCI */
+#define R128_VGA_DDA_CONFIG 0x02e8
+#define R128_VGA_DDA_ON_OFF 0x02ec
+#define R128_VID_BUFFER_CONTROL 0x0900
+#define R128_VIDEOMUX_CNTL 0x0190
+#define R128_VIPH_CONTROL 0x01D0 /* ? */
+
+#define R128_WAIT_UNTIL 0x1720
+
+#define R128_X_MPLL_REF_FB_DIV 0x000a /* PLL */
+#define R128_XCLK_CNTL 0x000d /* PLL */
+#define R128_XDLL_CNTL 0x000c /* PLL */
+#define R128_XPLL_CNTL 0x000b /* PLL */
+
+ /* Registers for CCE and Microcode Engine */
+#define R128_PM4_MICROCODE_ADDR 0x07d4
+#define R128_PM4_MICROCODE_RADDR 0x07d8
+#define R128_PM4_MICROCODE_DATAH 0x07dc
+#define R128_PM4_MICROCODE_DATAL 0x07e0
+
+#define R128_PM4_BUFFER_OFFSET 0x0700
+#define R128_PM4_BUFFER_CNTL 0x0704
+# define R128_PM4_NONPM4 (0 << 28)
+# define R128_PM4_192PIO (1 << 28)
+# define R128_PM4_192BM (2 << 28)
+# define R128_PM4_128PIO_64INDBM (3 << 28)
+# define R128_PM4_128BM_64INDBM (4 << 28)
+# define R128_PM4_64PIO_128INDBM (5 << 28)
+# define R128_PM4_64BM_128INDBM (6 << 28)
+# define R128_PM4_64PIO_64VCBM_64INDBM (7 << 28)
+# define R128_PM4_64BM_64VCBM_64INDBM (8 << 28)
+# define R128_PM4_64PIO_64VCPIO_64INDPIO (15 << 28)
+#define R128_PM4_BUFFER_WM_CNTL 0x0708
+# define R128_WMA_SHIFT 0
+# define R128_WMB_SHIFT 8
+# define R128_WMC_SHIFT 16
+# define R128_WB_WM_SHIFT 24
+#define R128_PM4_BUFFER_DL_RPTR_ADDR 0x070c
+#define R128_PM4_BUFFER_DL_RPTR 0x0710
+#define R128_PM4_BUFFER_DL_WPTR 0x0714
+# define R128_PM4_BUFFER_DL_DONE (1 << 31)
+#define R128_PM4_BUFFER_DL_WPTR_DELAY 0x0718
+# define R128_PRE_WRITE_TIMER_SHIFT 0
+# define R128_PRE_WRITE_LIMIT_SHIFT 23
+#define R128_PM4_VC_FPU_SETUP 0x071c
+# define R128_FRONT_DIR_CW (0 << 0)
+# define R128_FRONT_DIR_CCW (1 << 0)
+# define R128_FRONT_DIR_MASK (1 << 0)
+# define R128_BACKFACE_CULL (0 << 1)
+# define R128_BACKFACE_POINTS (1 << 1)
+# define R128_BACKFACE_LINES (2 << 1)
+# define R128_BACKFACE_SOLID (3 << 1)
+# define R128_BACKFACE_MASK (3 << 1)
+# define R128_FRONTFACE_CULL (0 << 3)
+# define R128_FRONTFACE_POINTS (1 << 3)
+# define R128_FRONTFACE_LINES (2 << 3)
+# define R128_FRONTFACE_SOLID (3 << 3)
+# define R128_FRONTFACE_MASK (3 << 3)
+# define R128_FPU_COLOR_SOLID (0 << 5)
+# define R128_FPU_COLOR_FLAT (1 << 5)
+# define R128_FPU_COLOR_GOURAUD (2 << 5)
+# define R128_FPU_COLOR_GOURAUD2 (3 << 5)
+# define R128_FPU_COLOR_MASK (3 << 5)
+# define R128_FPU_SUB_PIX_2BITS (0 << 7)
+# define R128_FPU_SUB_PIX_4BITS (1 << 7)
+# define R128_FPU_MODE_2D (0 << 8)
+# define R128_FPU_MODE_3D (1 << 8)
+# define R128_TRAP_BITS_DISABLE (1 << 9)
+# define R128_EDGE_ANTIALIAS (1 << 10)
+# define R128_SUPERSAMPLE (1 << 11)
+# define R128_XFACTOR_2 (0 << 12)
+# define R128_XFACTOR_4 (1 << 12)
+# define R128_YFACTOR_2 (0 << 13)
+# define R128_YFACTOR_4 (1 << 13)
+# define R128_FLAT_SHADE_VERTEX_D3D (0 << 14)
+# define R128_FLAT_SHADE_VERTEX_OGL (1 << 14)
+# define R128_FPU_ROUND_TRUNCATE (0 << 15)
+# define R128_FPU_ROUND_NEAREST (1 << 15)
+# define R128_WM_SEL_8DW (0 << 16)
+# define R128_WM_SEL_16DW (1 << 16)
+# define R128_WM_SEL_32DW (2 << 16)
+#define R128_PM4_VC_DEBUG_CONFIG 0x07a4
+#define R128_PM4_VC_STAT 0x07a8
+#define R128_PM4_VC_TIMESTAMP0 0x07b0
+#define R128_PM4_VC_TIMESTAMP1 0x07b4
+#define R128_PM4_STAT 0x07b8
+# define R128_PM4_FIFOCNT_MASK 0x0fff
+# define R128_PM4_BUSY (1 << 16)
+# define R128_PM4_GUI_ACTIVE (1 << 31)
+#define R128_PM4_BUFFER_ADDR 0x07f0
+#define R128_PM4_MICRO_CNTL 0x07fc
+# define R128_PM4_MICRO_FREERUN (1 << 30)
+#define R128_PM4_FIFO_DATA_EVEN 0x1000
+#define R128_PM4_FIFO_DATA_ODD 0x1004
+
+#define R128_SCALE_3D_CNTL 0x1a00
+# define R128_SCALE_DITHER_ERR_DIFF (0 << 1)
+# define R128_SCALE_DITHER_TABLE (1 << 1)
+# define R128_TEX_CACHE_SIZE_FULL (0 << 2)
+# define R128_TEX_CACHE_SIZE_HALF (1 << 2)
+# define R128_DITHER_INIT_CURR (0 << 3)
+# define R128_DITHER_INIT_RESET (1 << 3)
+# define R128_ROUND_24BIT (1 << 4)
+# define R128_TEX_CACHE_DISABLE (1 << 5)
+# define R128_SCALE_3D_NOOP (0 << 6)
+# define R128_SCALE_3D_SCALE (1 << 6)
+# define R128_SCALE_3D_TEXMAP_SHADE (2 << 6)
+# define R128_SCALE_PIX_BLEND (0 << 8)
+# define R128_SCALE_PIX_REPLICATE (1 << 8)
+# define R128_TEX_CACHE_SPLIT (1 << 9)
+# define R128_APPLE_YUV_MODE (1 << 10)
+# define R128_TEX_CACHE_PALLETE_MODE (1 << 11)
+# define R128_ALPHA_COMB_ADD_CLAMP (0 << 12)
+# define R128_ALPHA_COMB_ADD_NCLAMP (1 << 12)
+# define R128_ALPHA_COMB_SUB_DST_SRC_CLAMP (2 << 12)
+# define R128_ALPHA_COMB_SUB_DST_SRC_NCLAMP (3 << 12)
+# define R128_FOG_TABLE (1 << 14)
+# define R128_SIGNED_DST_CLAMP (1 << 15)
+# define R128_ALPHA_BLEND_SRC_ZERO (0 << 16)
+# define R128_ALPHA_BLEND_SRC_ONE (1 << 16)
+# define R128_ALPHA_BLEND_SRC_SRCCOLOR (2 << 16)
+# define R128_ALPHA_BLEND_SRC_INVSRCCOLOR (3 << 16)
+# define R128_ALPHA_BLEND_SRC_SRCALPHA (4 << 16)
+# define R128_ALPHA_BLEND_SRC_INVSRCALPHA (5 << 16)
+# define R128_ALPHA_BLEND_SRC_DSTALPHA (6 << 16)
+# define R128_ALPHA_BLEND_SRC_INVDSTALPHA (7 << 16)
+# define R128_ALPHA_BLEND_SRC_DSTCOLOR (8 << 16)
+# define R128_ALPHA_BLEND_SRC_INVDSTCOLOR (9 << 16)
+# define R128_ALPHA_BLEND_SRC_SAT (10 << 16)
+# define R128_ALPHA_BLEND_SRC_BLEND (11 << 16)
+# define R128_ALPHA_BLEND_SRC_INVBLEND (12 << 16)
+# define R128_ALPHA_BLEND_DST_ZERO (0 << 20)
+# define R128_ALPHA_BLEND_DST_ONE (1 << 20)
+# define R128_ALPHA_BLEND_DST_SRCCOLOR (2 << 20)
+# define R128_ALPHA_BLEND_DST_INVSRCCOLOR (3 << 20)
+# define R128_ALPHA_BLEND_DST_SRCALPHA (4 << 20)
+# define R128_ALPHA_BLEND_DST_INVSRCALPHA (5 << 20)
+# define R128_ALPHA_BLEND_DST_DSTALPHA (6 << 20)
+# define R128_ALPHA_BLEND_DST_INVDSTALPHA (7 << 20)
+# define R128_ALPHA_BLEND_DST_DSTCOLOR (8 << 20)
+# define R128_ALPHA_BLEND_DST_INVDSTCOLOR (9 << 20)
+# define R128_ALPHA_TEST_NEVER (0 << 24)
+# define R128_ALPHA_TEST_LESS (1 << 24)
+# define R128_ALPHA_TEST_LESSEQUAL (2 << 24)
+# define R128_ALPHA_TEST_EQUAL (3 << 24)
+# define R128_ALPHA_TEST_GREATEREQUAL (4 << 24)
+# define R128_ALPHA_TEST_GREATER (5 << 24)
+# define R128_ALPHA_TEST_NEQUAL (6 << 24)
+# define R128_ALPHA_TEST_ALWAYS (7 << 24)
+# define R128_COMPOSITE_SHADOW_CMP_EQUAL (0 << 28)
+# define R128_COMPOSITE_SHADOW_CMP_NEQUAL (1 << 28)
+# define R128_COMPOSITE_SHADOW (1 << 29)
+# define R128_TEX_MAP_ALPHA_IN_TEXTURE (1 << 30)
+# define R128_TEX_CACHE_LINE_SIZE_8QW (0 << 31)
+# define R128_TEX_CACHE_LINE_SIZE_4QW (1 << 31)
+#define R128_SCALE_3D_DATATYPE 0x1a20
+
+#define R128_SETUP_CNTL 0x1bc4
+# define R128_DONT_START_TRIANGLE (1 << 0)
+# define R128_Z_BIAS (0 << 1)
+# define R128_DONT_START_ANY_ON (1 << 2)
+# define R128_COLOR_SOLID_COLOR (0 << 3)
+# define R128_COLOR_FLAT_VERT_1 (1 << 3)
+# define R128_COLOR_FLAT_VERT_2 (2 << 3)
+# define R128_COLOR_FLAT_VERT_3 (3 << 3)
+# define R128_COLOR_GOURAUD (4 << 3)
+# define R128_PRIM_TYPE_TRI (0 << 7)
+# define R128_PRIM_TYPE_LINE (1 << 7)
+# define R128_PRIM_TYPE_POINT (2 << 7)
+# define R128_PRIM_TYPE_POLY_EDGE (3 << 7)
+# define R128_TEXTURE_ST_MULT_W (0 << 9)
+# define R128_TEXTURE_ST_DIRECT (1 << 9)
+# define R128_STARTING_VERTEX_1 (1 << 14)
+# define R128_STARTING_VERTEX_2 (2 << 14)
+# define R128_STARTING_VERTEX_3 (3 << 14)
+# define R128_ENDING_VERTEX_1 (1 << 16)
+# define R128_ENDING_VERTEX_2 (2 << 16)
+# define R128_ENDING_VERTEX_3 (3 << 16)
+# define R128_SU_POLY_LINE_LAST (0 << 18)
+# define R128_SU_POLY_LINE_NOT_LAST (1 << 18)
+# define R128_SUB_PIX_2BITS (0 << 19)
+# define R128_SUB_PIX_4BITS (1 << 19)
+# define R128_SET_UP_CONTINUE (1 << 31)
+
+#define R128_WINDOW_XY_OFFSET 0x1bcc
+# define R128_WINDOW_Y_SHIFT 4
+# define R128_WINDOW_X_SHIFT 20
+
+#define R128_Z_OFFSET_C 0x1c90
+#define R128_Z_PITCH_C 0x1c94
+# define R128_Z_TILE (1 << 16)
+#define R128_Z_STEN_CNTL_C 0x1c98
+# define R128_Z_PIX_WIDTH_16 (0 << 1)
+# define R128_Z_PIX_WIDTH_24 (1 << 1)
+# define R128_Z_PIX_WIDTH_32 (2 << 1)
+# define R128_Z_PIX_WIDTH_MASK (3 << 1)
+# define R128_Z_TEST_NEVER (0 << 4)
+# define R128_Z_TEST_LESS (1 << 4)
+# define R128_Z_TEST_LESSEQUAL (2 << 4)
+# define R128_Z_TEST_EQUAL (3 << 4)
+# define R128_Z_TEST_GREATEREQUAL (4 << 4)
+# define R128_Z_TEST_GREATER (5 << 4)
+# define R128_Z_TEST_NEQUAL (6 << 4)
+# define R128_Z_TEST_ALWAYS (7 << 4)
+# define R128_Z_TEST_MASK (7 << 4)
+# define R128_STENCIL_TEST_NEVER (0 << 12)
+# define R128_STENCIL_TEST_LESS (1 << 12)
+# define R128_STENCIL_TEST_LESSEQUAL (2 << 12)
+# define R128_STENCIL_TEST_EQUAL (3 << 12)
+# define R128_STENCIL_TEST_GREATEREQUAL (4 << 12)
+# define R128_STENCIL_TEST_GREATER (5 << 12)
+# define R128_STENCIL_TEST_NEQUAL (6 << 12)
+# define R128_STENCIL_TEST_ALWAYS (7 << 12)
+# define R128_STENCIL_S_FAIL_KEEP (0 << 16)
+# define R128_STENCIL_S_FAIL_ZERO (1 << 16)
+# define R128_STENCIL_S_FAIL_REPLACE (2 << 16)
+# define R128_STENCIL_S_FAIL_INC (3 << 16)
+# define R128_STENCIL_S_FAIL_DEC (4 << 16)
+# define R128_STENCIL_S_FAIL_INV (5 << 16)
+# define R128_STENCIL_ZPASS_KEEP (0 << 20)
+# define R128_STENCIL_ZPASS_ZERO (1 << 20)
+# define R128_STENCIL_ZPASS_REPLACE (2 << 20)
+# define R128_STENCIL_ZPASS_INC (3 << 20)
+# define R128_STENCIL_ZPASS_DEC (4 << 20)
+# define R128_STENCIL_ZPASS_INV (5 << 20)
+# define R128_STENCIL_ZFAIL_KEEP (0 << 24)
+# define R128_STENCIL_ZFAIL_ZERO (1 << 24)
+# define R128_STENCIL_ZFAIL_REPLACE (2 << 24)
+# define R128_STENCIL_ZFAIL_INC (3 << 24)
+# define R128_STENCIL_ZFAIL_DEC (4 << 24)
+# define R128_STENCIL_ZFAIL_INV (5 << 24)
+#define R128_TEX_CNTL_C 0x1c9c
+# define R128_Z_ENABLE (1 << 0)
+# define R128_Z_WRITE_ENABLE (1 << 1)
+# define R128_STENCIL_ENABLE (1 << 3)
+# define R128_SHADE_ENABLE (0 << 4)
+# define R128_TEXMAP_ENABLE (1 << 4)
+# define R128_SEC_TEXMAP_ENABLE (1 << 5)
+# define R128_FOG_ENABLE (1 << 7)
+# define R128_DITHER_ENABLE (1 << 8)
+# define R128_ALPHA_ENABLE (1 << 9)
+# define R128_ALPHA_TEST_ENABLE (1 << 10)
+# define R128_SPEC_LIGHT_ENABLE (1 << 11)
+# define R128_TEX_CHROMA_KEY_ENABLE (1 << 12)
+# define R128_ALPHA_IN_TEX_COMPLETE_A (0 << 13)
+# define R128_ALPHA_IN_TEX_LSB_A (1 << 13)
+# define R128_LIGHT_DIS (0 << 14)
+# define R128_LIGHT_COPY (1 << 14)
+# define R128_LIGHT_MODULATE (2 << 14)
+# define R128_LIGHT_ADD (3 << 14)
+# define R128_LIGHT_BLEND_CONSTANT (4 << 14)
+# define R128_LIGHT_BLEND_TEXTURE (5 << 14)
+# define R128_LIGHT_BLEND_VERTEX (6 << 14)
+# define R128_LIGHT_BLEND_CONST_COLOR (7 << 14)
+# define R128_ALPHA_LIGHT_DIS (0 << 18)
+# define R128_ALPHA_LIGHT_COPY (1 << 18)
+# define R128_ALPHA_LIGHT_MODULATE (2 << 18)
+# define R128_ALPHA_LIGHT_ADD (3 << 18)
+# define R128_ANTI_ALIAS (1 << 21)
+# define R128_TEX_CACHE_FLUSH (1 << 23)
+# define R128_LOD_BIAS_SHIFT 24
+# define R128_LOD_BIAS_MASK (0xff << 24)
+#define R128_MISC_3D_STATE_CNTL_REG 0x1ca0
+# define R128_REF_ALPHA_MASK 0xff
+# define R128_MISC_SCALE_3D_NOOP (0 << 8)
+# define R128_MISC_SCALE_3D_SCALE (1 << 8)
+# define R128_MISC_SCALE_3D_TEXMAP_SHADE (2 << 8)
+# define R128_MISC_SCALE_PIX_BLEND (0 << 10)
+# define R128_MISC_SCALE_PIX_REPLICATE (1 << 10)
+# define R128_ALPHA_COMB_ADD_CLAMP (0 << 12)
+# define R128_ALPHA_COMB_ADD_NO_CLAMP (1 << 12)
+# define R128_ALPHA_COMB_SUB_SRC_DST_CLAMP (2 << 12)
+# define R128_ALPHA_COMB_SUB_SRC_DST_NO_CLAMP (3 << 12)
+# define R128_FOG_VERTEX (0 << 14)
+# define R128_FOG_TABLE (1 << 14)
+# define R128_ALPHA_BLEND_SRC_ZERO (0 << 16)
+# define R128_ALPHA_BLEND_SRC_ONE (1 << 16)
+# define R128_ALPHA_BLEND_SRC_SRCCOLOR (2 << 16)
+# define R128_ALPHA_BLEND_SRC_INVSRCCOLOR (3 << 16)
+# define R128_ALPHA_BLEND_SRC_SRCALPHA (4 << 16)
+# define R128_ALPHA_BLEND_SRC_INVSRCALPHA (5 << 16)
+# define R128_ALPHA_BLEND_SRC_DESTALPHA (6 << 16)
+# define R128_ALPHA_BLEND_SRC_INVDESTALPHA (7 << 16)
+# define R128_ALPHA_BLEND_SRC_DESTCOLOR (8 << 16)
+# define R128_ALPHA_BLEND_SRC_INVDESTCOLOR (9 << 16)
+# define R128_ALPHA_BLEND_SRC_SRCALPHASAT (10 << 16)
+# define R128_ALPHA_BLEND_SRC_BOTHSRCALPHA (11 << 16)
+# define R128_ALPHA_BLEND_SRC_BOTHINVSRCALPHA (12 << 16)
+# define R128_ALPHA_BLEND_SRC_MASK (15 << 16)
+# define R128_ALPHA_BLEND_DST_ZERO (0 << 20)
+# define R128_ALPHA_BLEND_DST_ONE (1 << 20)
+# define R128_ALPHA_BLEND_DST_SRCCOLOR (2 << 20)
+# define R128_ALPHA_BLEND_DST_INVSRCCOLOR (3 << 20)
+# define R128_ALPHA_BLEND_DST_SRCALPHA (4 << 20)
+# define R128_ALPHA_BLEND_DST_INVSRCALPHA (5 << 20)
+# define R128_ALPHA_BLEND_DST_DESTALPHA (6 << 20)
+# define R128_ALPHA_BLEND_DST_INVDESTALPHA (7 << 20)
+# define R128_ALPHA_BLEND_DST_DESTCOLOR (8 << 20)
+# define R128_ALPHA_BLEND_DST_INVDESTCOLOR (9 << 20)
+# define R128_ALPHA_BLEND_DST_SRCALPHASAT (10 << 20)
+# define R128_ALPHA_BLEND_DST_MASK (15 << 20)
+# define R128_ALPHA_TEST_NEVER (0 << 24)
+# define R128_ALPHA_TEST_LESS (1 << 24)
+# define R128_ALPHA_TEST_LESSEQUAL (2 << 24)
+# define R128_ALPHA_TEST_EQUAL (3 << 24)
+# define R128_ALPHA_TEST_GREATEREQUAL (4 << 24)
+# define R128_ALPHA_TEST_GREATER (5 << 24)
+# define R128_ALPHA_TEST_NEQUAL (6 << 24)
+# define R128_ALPHA_TEST_ALWAYS (7 << 24)
+# define R128_ALPHA_TEST_MASK (7 << 24)
+#define R128_TEXTURE_CLR_CMP_CLR_C 0x1ca4
+#define R128_TEXTURE_CLR_CMP_MSK_C 0x1ca8
+#define R128_FOG_COLOR_C 0x1cac
+# define R128_FOG_BLUE_SHIFT 0
+# define R128_FOG_GREEN_SHIFT 8
+# define R128_FOG_RED_SHIFT 16
+#define R128_PRIM_TEX_CNTL_C 0x1cb0
+# define R128_MIN_BLEND_NEAREST (0 << 1)
+# define R128_MIN_BLEND_LINEAR (1 << 1)
+# define R128_MIN_BLEND_MIPNEAREST (2 << 1)
+# define R128_MIN_BLEND_MIPLINEAR (3 << 1)
+# define R128_MIN_BLEND_LINEARMIPNEAREST (4 << 1)
+# define R128_MIN_BLEND_LINEARMIPLINEAR (5 << 1)
+# define R128_MIN_BLEND_MASK (7 << 1)
+# define R128_MAG_BLEND_NEAREST (0 << 4)
+# define R128_MAG_BLEND_LINEAR (1 << 4)
+# define R128_MAG_BLEND_MASK (7 << 4)
+# define R128_MIP_MAP_DISABLE (1 << 7)
+# define R128_TEX_CLAMP_S_WRAP (0 << 8)
+# define R128_TEX_CLAMP_S_MIRROR (1 << 8)
+# define R128_TEX_CLAMP_S_CLAMP (2 << 8)
+# define R128_TEX_CLAMP_S_BORDER_COLOR (3 << 8)
+# define R128_TEX_CLAMP_S_MASK (3 << 8)
+# define R128_TEX_WRAP_S (1 << 10)
+# define R128_TEX_CLAMP_T_WRAP (0 << 11)
+# define R128_TEX_CLAMP_T_MIRROR (1 << 11)
+# define R128_TEX_CLAMP_T_CLAMP (2 << 11)
+# define R128_TEX_CLAMP_T_BORDER_COLOR (3 << 11)
+# define R128_TEX_CLAMP_T_MASK (3 << 11)
+# define R128_TEX_WRAP_T (1 << 13)
+# define R128_TEX_PERSPECTIVE_DISABLE (1 << 14)
+# define R128_DATATYPE_VQ (0 << 16)
+# define R128_DATATYPE_CI4 (1 << 16)
+# define R128_DATATYPE_CI8 (2 << 16)
+# define R128_DATATYPE_ARGB1555 (3 << 16)
+# define R128_DATATYPE_RGB565 (4 << 16)
+# define R128_DATATYPE_RGB888 (5 << 16)
+# define R128_DATATYPE_ARGB8888 (6 << 16)
+# define R128_DATATYPE_RGB332 (7 << 16)
+# define R128_DATATYPE_Y8 (8 << 16)
+# define R128_DATATYPE_RGB8 (9 << 16)
+# define R128_DATATYPE_CI16 (10 << 16)
+# define R128_DATATYPE_YVYU422 (11 << 16)
+# define R128_DATATYPE_VYUY422 (12 << 16)
+# define R128_DATATYPE_AYUV444 (14 << 16)
+# define R128_DATATYPE_ARGB4444 (15 << 16)
+# define R128_PALLETE_EITHER (0 << 20)
+# define R128_PALLETE_1 (1 << 20)
+# define R128_PALLETE_2 (2 << 20)
+# define R128_PSEUDOCOLOR_DT_RGB565 (0 << 24)
+# define R128_PSEUDOCOLOR_DT_ARGB1555 (1 << 24)
+# define R128_PSEUDOCOLOR_DT_ARGB4444 (2 << 24)
+#define R128_PRIM_TEXTURE_COMBINE_CNTL_C 0x1cb4
+# define R128_COMB_DIS (0 << 0)
+# define R128_COMB_COPY (1 << 0)
+# define R128_COMB_COPY_INP (2 << 0)
+# define R128_COMB_MODULATE (3 << 0)
+# define R128_COMB_MODULATE2X (4 << 0)
+# define R128_COMB_MODULATE4X (5 << 0)
+# define R128_COMB_ADD (6 << 0)
+# define R128_COMB_ADD_SIGNED (7 << 0)
+# define R128_COMB_BLEND_VERTEX (8 << 0)
+# define R128_COMB_BLEND_TEXTURE (9 << 0)
+# define R128_COMB_BLEND_CONST (10 << 0)
+# define R128_COMB_BLEND_PREMULT (11 << 0)
+# define R128_COMB_BLEND_PREV (12 << 0)
+# define R128_COMB_BLEND_PREMULT_INV (13 << 0)
+# define R128_COMB_ADD_SIGNED2X (14 << 0)
+# define R128_COMB_BLEND_CONST_COLOR (15 << 0)
+# define R128_COMB_MASK (15 << 0)
+# define R128_COLOR_FACTOR_CONST_COLOR (0 << 4)
+# define R128_COLOR_FACTOR_NCONST_COLOR (1 << 4)
+# define R128_COLOR_FACTOR_TEX (4 << 4)
+# define R128_COLOR_FACTOR_NTEX (5 << 4)
+# define R128_COLOR_FACTOR_ALPHA (6 << 4)
+# define R128_COLOR_FACTOR_NALPHA (7 << 4)
+# define R128_COLOR_FACTOR_PREV_COLOR (8 << 4)
+# define R128_COLOR_FACTOR_MASK (15 << 4)
+# define R128_COMB_FCN_MSB (1 << 8)
+# define R128_INPUT_FACTOR_CONST_COLOR (2 << 10)
+# define R128_INPUT_FACTOR_CONST_ALPHA (3 << 10)
+# define R128_INPUT_FACTOR_INT_COLOR (4 << 10)
+# define R128_INPUT_FACTOR_INT_ALPHA (5 << 10)
+# define R128_INPUT_FACTOR_MASK (15 << 10)
+# define R128_COMB_ALPHA_DIS (0 << 14)
+# define R128_COMB_ALPHA_COPY (1 << 14)
+# define R128_COMB_ALPHA_COPY_INP (2 << 14)
+# define R128_COMB_ALPHA_MODULATE (3 << 14)
+# define R128_COMB_ALPHA_MODULATE2X (4 << 14)
+# define R128_COMB_ALPHA_MODULATE4X (5 << 14)
+# define R128_COMB_ALPHA_ADD (6 << 14)
+# define R128_COMB_ALPHA_ADD_SIGNED (7 << 14)
+# define R128_COMB_ALPHA_ADD_SIGNED2X (14 << 14)
+# define R128_COMB_ALPHA_MASK (15 << 14)
+# define R128_ALPHA_FACTOR_TEX_ALPHA (6 << 18)
+# define R128_ALPHA_FACTOR_NTEX_ALPHA (7 << 18)
+# define R128_ALPHA_FACTOR_MASK (15 << 18)
+# define R128_INP_FACTOR_A_CONST_ALPHA (1 << 25)
+# define R128_INP_FACTOR_A_INT_ALPHA (2 << 25)
+# define R128_INP_FACTOR_A_MASK (7 << 25)
+#define R128_TEX_SIZE_PITCH_C 0x1cb8
+# define R128_TEX_PITCH_SHIFT 0
+# define R128_TEX_SIZE_SHIFT 4
+# define R128_TEX_HEIGHT_SHIFT 8
+# define R128_TEX_MIN_SIZE_SHIFT 12
+# define R128_SEC_TEX_PITCH_SHIFT 16
+# define R128_SEC_TEX_SIZE_SHIFT 20
+# define R128_SEC_TEX_HEIGHT_SHIFT 24
+# define R128_SEC_TEX_MIN_SIZE_SHIFT 28
+# define R128_TEX_PITCH_MASK (0x0f << 0)
+# define R128_TEX_SIZE_MASK (0x0f << 4)
+# define R128_TEX_HEIGHT_MASK (0x0f << 8)
+# define R128_TEX_MIN_SIZE_MASK (0x0f << 12)
+# define R128_SEC_TEX_PITCH_MASK (0x0f << 16)
+# define R128_SEC_TEX_SIZE_MASK (0x0f << 20)
+# define R128_SEC_TEX_HEIGHT_MASK (0x0f << 24)
+# define R128_SEC_TEX_MIN_SIZE_MASK (0x0f << 28)
+# define R128_TEX_SIZE_PITCH_SHIFT 0
+# define R128_SEC_TEX_SIZE_PITCH_SHIFT 16
+# define R128_TEX_SIZE_PITCH_MASK (0xffff << 0)
+# define R128_SEC_TEX_SIZE_PITCH_MASK (0xffff << 16)
+#define R128_PRIM_TEX_0_OFFSET_C 0x1cbc
+#define R128_PRIM_TEX_1_OFFSET_C 0x1cc0
+#define R128_PRIM_TEX_2_OFFSET_C 0x1cc4
+#define R128_PRIM_TEX_3_OFFSET_C 0x1cc8
+#define R128_PRIM_TEX_4_OFFSET_C 0x1ccc
+#define R128_PRIM_TEX_5_OFFSET_C 0x1cd0
+#define R128_PRIM_TEX_6_OFFSET_C 0x1cd4
+#define R128_PRIM_TEX_7_OFFSET_C 0x1cd8
+#define R128_PRIM_TEX_8_OFFSET_C 0x1cdc
+#define R128_PRIM_TEX_9_OFFSET_C 0x1ce0
+#define R128_PRIM_TEX_10_OFFSET_C 0x1ce4
+# define R128_TEX_NO_TILE (0 << 30)
+# define R128_TEX_TILED_BY_HOST (1 << 30)
+# define R128_TEX_TILED_BY_STORAGE (2 << 30)
+# define R128_TEX_TILED_BY_STORAGE2 (3 << 30)
+
+#define R128_SEC_TEX_CNTL_C 0x1d00
+# define R128_SEC_SELECT_PRIM_ST (0 << 0)
+# define R128_SEC_SELECT_SEC_ST (1 << 0)
+#define R128_SEC_TEX_COMBINE_CNTL_C 0x1d04
+# define R128_INPUT_FACTOR_PREV_COLOR (8 << 10)
+# define R128_INPUT_FACTOR_PREV_ALPHA (9 << 10)
+# define R128_INP_FACTOR_A_PREV_ALPHA (4 << 25)
+#define R128_SEC_TEX_0_OFFSET_C 0x1d08
+#define R128_SEC_TEX_1_OFFSET_C 0x1d0c
+#define R128_SEC_TEX_2_OFFSET_C 0x1d10
+#define R128_SEC_TEX_3_OFFSET_C 0x1d14
+#define R128_SEC_TEX_4_OFFSET_C 0x1d18
+#define R128_SEC_TEX_5_OFFSET_C 0x1d1c
+#define R128_SEC_TEX_6_OFFSET_C 0x1d20
+#define R128_SEC_TEX_7_OFFSET_C 0x1d24
+#define R128_SEC_TEX_8_OFFSET_C 0x1d28
+#define R128_SEC_TEX_9_OFFSET_C 0x1d2c
+#define R128_SEC_TEX_10_OFFSET_C 0x1d30
+#define R128_CONSTANT_COLOR_C 0x1d34
+# define R128_CONSTANT_BLUE_SHIFT 0
+# define R128_CONSTANT_GREEN_SHIFT 8
+# define R128_CONSTANT_RED_SHIFT 16
+# define R128_CONSTANT_ALPHA_SHIFT 24
+#define R128_PRIM_TEXTURE_BORDER_COLOR_C 0x1d38
+# define R128_PRIM_TEX_BORDER_BLUE_SHIFT 0
+# define R128_PRIM_TEX_BORDER_GREEN_SHIFT 8
+# define R128_PRIM_TEX_BORDER_RED_SHIFT 16
+# define R128_PRIM_TEX_BORDER_ALPHA_SHIFT 24
+#define R128_SEC_TEXTURE_BORDER_COLOR_C 0x1d3c
+# define R128_SEC_TEX_BORDER_BLUE_SHIFT 0
+# define R128_SEC_TEX_BORDER_GREEN_SHIFT 8
+# define R128_SEC_TEX_BORDER_RED_SHIFT 16
+# define R128_SEC_TEX_BORDER_ALPHA_SHIFT 24
+#define R128_STEN_REF_MASK_C 0x1d40
+# define R128_STEN_REFERENCE_SHIFT 0
+# define R128_STEN_MASK_SHIFT 16
+# define R128_STEN_WRITE_MASK_SHIFT 24
+#define R128_PLANE_3D_MASK_C 0x1d44
+#define R128_TEX_CACHE_STAT_COUNT 0x1974
+
+
+ /* Constants */
+#define R128_AGP_TEX_OFFSET 0x02000000
+
+#define R128_LAST_FRAME_REG R128_GUI_SCRATCH_REG0
+
+ /* CCE packet types */
+#define R128_CCE_PACKET0 0x00000000
+#define R128_CCE_PACKET0_ONE_REG_WR 0x00008000
+#define R128_CCE_PACKET1 0x40000000
+#define R128_CCE_PACKET2 0x80000000
+#define R128_CCE_PACKET3 0xC0000000
+#define R128_CCE_PACKET3_NOP 0xC0001000
+#define R128_CCE_PACKET3_PAINT 0xC0001100
+#define R128_CCE_PACKET3_BITBLT 0xC0001200
+#define R128_CCE_PACKET3_SMALLTEXT 0xC0001300
+#define R128_CCE_PACKET3_HOSTDATA_BLT 0xC0001400
+#define R128_CCE_PACKET3_POLYLINE 0xC0001500
+#define R128_CCE_PACKET3_SCALING 0xC0001600
+#define R128_CCE_PACKET3_TRANS_SCALING 0xC0001700
+#define R128_CCE_PACKET3_POLYSCANLINES 0xC0001800
+#define R128_CCE_PACKET3_NEXT_CHAR 0xC0001900
+#define R128_CCE_PACKET3_PAINT_MULTI 0xC0001A00
+#define R128_CCE_PACKET3_BITBLT_MULTI 0xC0001B00
+#define R128_CCE_PACKET3_PLY_NEXTSCAN 0xC0001D00
+#define R128_CCE_PACKET3_SET_SCISSORS 0xC0001E00
+#define R128_CCE_PACKET3_SET_MODE24BPP 0xC0001F00
+#define R128_CCE_PACKET3_CNTL_PAINT 0xC0009100
+#define R128_CCE_PACKET3_CNTL_BITBLT 0xC0009200
+#define R128_CCE_PACKET3_CNTL_SMALLTEXT 0xC0009300
+#define R128_CCE_PACKET3_CNTL_HOSTDATA_BLT 0xC0009400
+#define R128_CCE_PACKET3_CNTL_POLYLINE 0xC0009500
+#define R128_CCE_PACKET3_CNTL_SCALING 0xC0009600
+#define R128_CCE_PACKET3_CNTL_TRANS_SCALING 0xC0009700
+#define R128_CCE_PACKET3_CNTL_POLYSCANLINES 0xC0009800
+#define R128_CCE_PACKET3_CNTL_NEXT_CHAR 0xC0009900
+#define R128_CCE_PACKET3_CNTL_PAINT_MULTI 0xC0009A00
+#define R128_CCE_PACKET3_CNTL_BITBLT_MULTI 0xC0009B00
+#define R128_CCE_PACKET3_CNTL_TRANS_BITBLT 0xC0009C00
+#define R128_CCE_PACKET3_3D_SAVE_CONTEXT 0xC0002000
+#define R128_CCE_PACKET3_3D_PLAY_CONTEXT 0xC0002100
+#define R128_CCE_PACKET3_3D_RNDR_GEN_INDX_PRIM 0xC0002300
+#define R128_CCE_PACKET3_3D_RNDR_GEN_PRIM 0xC0002500
+#define R128_CCE_PACKET3_LOAD_PALETTE 0xC0002C00
+#define R128_CCE_PACKET3_PURGE 0xC0002D00
+#define R128_CCE_PACKET3_NEXT_VERTEX_BUNDLE 0xC0002E00
+# define R128_CCE_PACKET_MASK 0xC0000000
+# define R128_CCE_PACKET_COUNT_MASK 0x3fff0000
+# define R128_CCE_PACKET_MAX_DWORDS (1 << 12)
+# define R128_CCE_PACKET0_REG_MASK 0x000007ff
+# define R128_CCE_PACKET1_REG0_MASK 0x000007ff
+# define R128_CCE_PACKET1_REG1_MASK 0x003ff800
+
+#define R128_CCE_VC_FRMT_RHW 0x00000001
+#define R128_CCE_VC_FRMT_DIFFUSE_BGR 0x00000002
+#define R128_CCE_VC_FRMT_DIFFUSE_A 0x00000004
+#define R128_CCE_VC_FRMT_DIFFUSE_ARGB 0x00000008
+#define R128_CCE_VC_FRMT_SPEC_BGR 0x00000010
+#define R128_CCE_VC_FRMT_SPEC_F 0x00000020
+#define R128_CCE_VC_FRMT_SPEC_FRGB 0x00000040
+#define R128_CCE_VC_FRMT_S_T 0x00000080
+#define R128_CCE_VC_FRMT_S2_T2 0x00000100
+#define R128_CCE_VC_FRMT_RHW2 0x00000200
+
+#define R128_CCE_VC_CNTL_PRIM_TYPE_NONE 0x00000000
+#define R128_CCE_VC_CNTL_PRIM_TYPE_POINT 0x00000001
+#define R128_CCE_VC_CNTL_PRIM_TYPE_LINE 0x00000002
+#define R128_CCE_VC_CNTL_PRIM_TYPE_POLY_LINE 0x00000003
+#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST 0x00000004
+#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_FAN 0x00000005
+#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_STRIP 0x00000006
+#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 0x00000007
+#define R128_CCE_VC_CNTL_PRIM_WALK_IND 0x00000010
+#define R128_CCE_VC_CNTL_PRIM_WALK_LIST 0x00000020
+#define R128_CCE_VC_CNTL_PRIM_WALK_RING 0x00000030
+#define R128_CCE_VC_CNTL_NUM_SHIFT 16
+
+/* hmm copyed blindly (no specs) from radeon.h ... */
+#define R128_RE_TOP_LEFT 0x26c0
+# define R128_RE_LEFT_SHIFT 0
+# define R128_RE_TOP_SHIFT 16
+#define R128_RE_WIDTH_HEIGHT 0x1c44
+# define R128_RE_WIDTH_SHIFT 0
+# define R128_RE_HEIGHT_SHIFT 16
+
+#endif
diff --git a/src/mesa/drivers/dri/r128/server/r128_sarea.h b/src/mesa/drivers/dri/r128/server/r128_sarea.h
new file mode 100644
index 0000000000..8a9f3a4176
--- /dev/null
+++ b/src/mesa/drivers/dri/r128/server/r128_sarea.h
@@ -0,0 +1,195 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_sarea.h,v 1.7 2002/02/16 21:26:35 herrb Exp $ */
+/*
+ * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario,
+ * Precision Insight, Inc., Cedar Park, Texas, 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, 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
+ * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, PRECISION INSIGHT, 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:
+ * Kevin E. Martin <martin@valinux.com>
+ * Gareth Hughes <gareth@valinux.com>
+ *
+ */
+
+#ifndef _R128_SAREA_H_
+#define _R128_SAREA_H_
+
+/* WARNING: If you change any of these defines, make sure to change the
+ * defines in the kernel file (r128_drm.h)
+ */
+#ifndef __R128_SAREA_DEFINES__
+#define __R128_SAREA_DEFINES__
+
+/* What needs to be changed for the current vertex buffer?
+ */
+#define R128_UPLOAD_CONTEXT 0x001
+#define R128_UPLOAD_SETUP 0x002
+#define R128_UPLOAD_TEX0 0x004
+#define R128_UPLOAD_TEX1 0x008
+#define R128_UPLOAD_TEX0IMAGES 0x010
+#define R128_UPLOAD_TEX1IMAGES 0x020
+#define R128_UPLOAD_CORE 0x040
+#define R128_UPLOAD_MASKS 0x080
+#define R128_UPLOAD_WINDOW 0x100
+#define R128_UPLOAD_CLIPRECTS 0x200 /* handled client-side */
+#define R128_REQUIRE_QUIESCENCE 0x400
+#define R128_UPLOAD_ALL 0x7ff
+
+#define R128_FRONT 0x1
+#define R128_BACK 0x2
+#define R128_DEPTH 0x4
+
+/* Primitive types
+ */
+#define R128_POINTS 0x1
+#define R128_LINES 0x2
+#define R128_LINE_STRIP 0x3
+#define R128_TRIANGLES 0x4
+#define R128_TRIANGLE_FAN 0x5
+#define R128_TRIANGLE_STRIP 0x6
+
+/* Vertex/indirect buffer size
+ */
+#define R128_BUFFER_SIZE 16384
+
+/* Byte offsets for indirect buffer data
+ */
+#define R128_INDEX_PRIM_OFFSET 20
+#define R128_HOSTDATA_BLIT_OFFSET 32
+
+/* Keep these small for testing
+ */
+#define R128_NR_SAREA_CLIPRECTS 12
+
+/* There are 2 heaps (local/AGP). Each region within a heap is a
+ * minimum of 64k, and there are at most 64 of them per heap.
+ */
+#define R128_CARD_HEAP 0
+#define R128_AGP_HEAP 1
+#define R128_NR_TEX_HEAPS 2
+#define R128_NR_TEX_REGIONS 64
+#define R128_LOG_TEX_GRANULARITY 16
+
+#define R128_NR_CONTEXT_REGS 12
+
+#define R128_MAX_TEXTURE_LEVELS 11
+#define R128_MAX_TEXTURE_UNITS 2
+
+#endif /* __R128_SAREA_DEFINES__ */
+
+typedef struct {
+ /* Context state - can be written in one large chunk */
+ unsigned int dst_pitch_offset_c;
+ unsigned int dp_gui_master_cntl_c;
+ unsigned int sc_top_left_c;
+ unsigned int sc_bottom_right_c;
+ unsigned int z_offset_c;
+ unsigned int z_pitch_c;
+ unsigned int z_sten_cntl_c;
+ unsigned int tex_cntl_c;
+ unsigned int misc_3d_state_cntl_reg;
+ unsigned int texture_clr_cmp_clr_c;
+ unsigned int texture_clr_cmp_msk_c;
+ unsigned int fog_color_c;
+
+ /* Texture state */
+ unsigned int tex_size_pitch_c;
+ unsigned int constant_color_c;
+
+ /* Setup state */
+ unsigned int pm4_vc_fpu_setup;
+ unsigned int setup_cntl;
+
+ /* Mask state */
+ unsigned int dp_write_mask;
+ unsigned int sten_ref_mask_c;
+ unsigned int plane_3d_mask_c;
+
+ /* Window state */
+ unsigned int window_xy_offset;
+
+ /* Core state */
+ unsigned int scale_3d_cntl;
+} r128_context_regs_t;
+
+/* Setup registers for each texture unit
+ */
+typedef struct {
+ unsigned int tex_cntl;
+ unsigned int tex_combine_cntl;
+ unsigned int tex_size_pitch;
+ unsigned int tex_offset[R128_MAX_TEXTURE_LEVELS];
+ unsigned int tex_border_color;
+} r128_texture_regs_t;
+
+typedef struct {
+ /* The channel for communication of state information to the kernel
+ * on firing a vertex buffer.
+ */
+ r128_context_regs_t ContextState;
+ r128_texture_regs_t TexState[R128_MAX_TEXTURE_UNITS];
+ unsigned int dirty;
+ unsigned int vertsize;
+ unsigned int vc_format;
+
+#if defined(XF86DRI) | defined(_SOLO)
+ /* The current cliprects, or a subset thereof.
+ */
+ XF86DRIClipRectRec boxes[R128_NR_SAREA_CLIPRECTS];
+ unsigned int nbox;
+#endif
+
+ /* Counters for throttling of rendering clients.
+ */
+ unsigned int last_frame;
+ unsigned int last_dispatch;
+
+ /* Maintain an LRU of contiguous regions of texture space. If you
+ * think you own a region of texture memory, and it has an age
+ * different to the one you set, then you are mistaken and it has
+ * been stolen by another client. If global texAge hasn't changed,
+ * there is no need to walk the list.
+ *
+ * These regions can be used as a proxy for the fine-grained texture
+ * information of other clients - by maintaining them in the same
+ * lru which is used to age their own textures, clients have an
+ * approximate lru for the whole of global texture space, and can
+ * make informed decisions as to which areas to kick out. There is
+ * no need to choose whether to kick out your own texture or someone
+ * else's - simply eject them all in LRU order.
+ */
+ /* Last elt is sentinal */
+ drmTextureRegion texList[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS+1];
+ /* last time texture was uploaded */
+ unsigned int texAge[R128_NR_TEX_HEAPS];
+
+ int ctxOwner; /* last context to upload state */
+ int pfAllowPageFlip; /* set by the 2d driver, read by the client */
+ int pfCurrentPage; /* set by kernel, read by others */
+} R128SAREAPriv, *R128SAREAPrivPtr;
+
+#endif
diff --git a/src/mesa/drivers/dri/r128/server/r128_version.h b/src/mesa/drivers/dri/r128/server/r128_version.h
new file mode 100644
index 0000000000..589d8d40bc
--- /dev/null
+++ b/src/mesa/drivers/dri/r128/server/r128_version.h
@@ -0,0 +1,60 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_version.h,v 1.6 2003/01/01 19:16:35 tsi Exp $ */
+/*
+ * Copyright 2000 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _R128_VERSION_H_
+#define _R128_VERSION_H_ 1
+
+#undef R128_NAME
+#undef R128_DRIVER_NAME
+#undef R128_VERSION_MAJOR
+#undef R128_VERSION_MINOR
+#undef R128_VERSION_PATCH
+#undef R128_VERSION_CURRENT
+#undef R128_VERSION_EVALUATE
+#undef R128_VERSION_STRINGIFY
+#undef R128_VERSION_NAME
+
+#define R128_NAME "R128"
+#define R128_DRIVER_NAME "r128"
+
+#define R128_VERSION_MAJOR 4
+#define R128_VERSION_MINOR 0
+#define R128_VERSION_PATCH 1
+
+#ifndef R128_VERSION_EXTRA
+#define R128_VERSION_EXTRA ""
+#endif
+
+#define R128_VERSION_CURRENT \
+ ((R128_VERSION_MAJOR << 20) | \
+ (R128_VERSION_MINOR << 10) | \
+ (R128_VERSION_PATCH))
+
+#define R128_VERSION_EVALUATE(__x) #__x
+#define R128_VERSION_STRINGIFY(_x) R128_VERSION_EVALUATE(_x)
+#define R128_VERSION_NAME \
+ R128_VERSION_STRINGIFY(R128_VERSION_MAJOR) "." \
+ R128_VERSION_STRINGIFY(R128_VERSION_MINOR) "." \
+ R128_VERSION_STRINGIFY(R128_VERSION_MINOR) R128_VERSION_EXTRA
+
+#endif /* _R128_VERSION_H_ */
diff --git a/src/mesa/drivers/dri/r200/Makefile.X11 b/src/mesa/drivers/dri/r200/Makefile.X11
index b182ba559a..f1887b5914 100644
--- a/src/mesa/drivers/dri/r200/Makefile.X11
+++ b/src/mesa/drivers/dri/r200/Makefile.X11
@@ -1,4 +1,4 @@
-# $Id: Makefile.X11,v 1.1 2003/08/06 17:59:57 keithw Exp $
+# $Id: Makefile.X11,v 1.2 2003/08/22 20:11:45 brianp Exp $
# Mesa 3-D graphics library
# Version: 5.0
@@ -6,8 +6,10 @@
TOP = ../../../../..
+default: linux-solo
+
SHARED_INCLUDES = $(INCLUDE_DIRS) -I. -I../common -Iserver
-MINIGLX_INCLUDES = -I$(TOP)/src/miniglx
+MINIGLX_INCLUDES = -I$(TOP)/src/glx/mini
DEFINES += \
-D_HAVE_SWRAST=1 \
@@ -62,7 +64,7 @@ WINOBJ=$(MESABUILDDIR)/dri/dri.a
WINLIB=
else
WINOBJ=
-WINLIB=-L$(MESA)/src/miniglx
+WINLIB=-L$(MESA)/src/glx/mini
endif
ASM_SOURCES =
@@ -107,7 +109,7 @@ INCLUDE_DIRS = \
##### TARGETS #####
-targets: r200_dri.so
+targets: depend r200_dri.so
r200_dri.so: $(SYMLINKS) $(OBJECTS) $(MESA_MODULES) $(WINOBJ) Makefile.X11
rm -f $@ && gcc -o $@ -shared $(OBJECTS) $(MESA_MODULES) $(WINOBJ) $(WINLIB) -lc $(GL_LIB_DEPS)
@@ -116,8 +118,8 @@ r200_dri.so: $(SYMLINKS) $(OBJECTS) $(MESA_MODULES) $(WINOBJ) Makefile.X11
# Run 'make -f Makefile.X11 dep' to update the dependencies if you change
# what's included by any source file.
-dep: $(C_SOURCES) $(ASM_SOURCES)
- makedepend -fdepend -Y $(SHARED_INCLUDES) \
+depend: $(C_SOURCES) $(ASM_SOURCES)
+ makedepend -fdepend -Y $(SHARED_INCLUDES) $(MINIGLX_INCLUDES) \
$(C_SOURCES) $(ASM_SOURCES)
@@ -128,7 +130,7 @@ tags:
# Remove .o and backup files
clean:
- -rm -f *.o *~ *.o *~ *.so
+ -rm -f *.o */*.o *~ *.o *~ *.so server/*.o
include $(TOP)/Make-config
diff --git a/src/mesa/drivers/dri/r200/r200_context.c b/src/mesa/drivers/dri/r200/r200_context.c
index c5f23effab..ec95f05e6e 100644
--- a/src/mesa/drivers/dri/r200/r200_context.c
+++ b/src/mesa/drivers/dri/r200/r200_context.c
@@ -492,8 +492,9 @@ void r200DestroyContext( __DRIcontextPrivate *driContextPriv )
* texture object data.
*/
int i;
-
- assert( is_empty_list( & rmesa->swapped ) );
+
+ /* this assert is wrong. The default textures are always on swap list
+ assert( is_empty_list( & rmesa->swapped ) ); */
for ( i = 0 ; i < rmesa->nr_heaps ; i++ ) {
driDestroyTextureHeap( rmesa->texture_heaps[ i ] );
diff --git a/src/mesa/drivers/dri/r200/r200_context.h b/src/mesa/drivers/dri/r200/r200_context.h
index 3802deead9..9e00d7a358 100644
--- a/src/mesa/drivers/dri/r200/r200_context.h
+++ b/src/mesa/drivers/dri/r200/r200_context.h
@@ -615,7 +615,7 @@ struct r200_swtcl_info {
GLuint vertex_size;
GLuint vertex_stride_shift;
GLuint vertex_format;
- char *verts;
+ GLubyte *verts;
/* Fallback rasterization functions
*/
diff --git a/src/mesa/drivers/dri/r200/r200_ioctl.c b/src/mesa/drivers/dri/r200/r200_ioctl.c
index ea67216238..480121a094 100644
--- a/src/mesa/drivers/dri/r200/r200_ioctl.c
+++ b/src/mesa/drivers/dri/r200/r200_ioctl.c
@@ -320,7 +320,7 @@ static CARD32 r200GetLastFrame(r200ContextPtr rmesa)
CARD32 frame;
gp.param = RADEON_PARAM_LAST_FRAME;
- gp.value = (int *)&frame;
+ gp.value = &frame;
ret = drmCommandWriteRead( rmesa->dri.fd, DRM_RADEON_GETPARAM,
&gp, sizeof(gp) );
if ( ret ) {
@@ -404,7 +404,7 @@ void r200CopyBuffer( const __DRIdrawablePrivate *dPriv )
r200ContextPtr rmesa;
GLint nbox, i, ret;
GLboolean missed_target;
- int64_t ust;
+ uint64_t ust;
assert(dPriv);
assert(dPriv->driContextPriv);
@@ -616,7 +616,7 @@ static void r200Clear( GLcontext *ctx, GLbitfield mask, GLboolean all,
int clear;
gp.param = RADEON_PARAM_LAST_CLEAR;
- gp.value = (int *)&clear;
+ gp.value = &clear;
ret = drmCommandWriteRead( rmesa->dri.fd,
DRM_RADEON_GETPARAM, &gp, sizeof(gp) );
diff --git a/src/mesa/drivers/dri/r200/r200_swtcl.c b/src/mesa/drivers/dri/r200/r200_swtcl.c
index 6a436509a0..dd4025235b 100644
--- a/src/mesa/drivers/dri/r200/r200_swtcl.c
+++ b/src/mesa/drivers/dri/r200/r200_swtcl.c
@@ -446,7 +446,7 @@ static __inline void *r200AllocDmaLowVerts( r200ContextPtr rmesa,
{
- GLubyte *head = rmesa->dma.current.address + rmesa->dma.current.ptr;
+ char *head = rmesa->dma.current.address + rmesa->dma.current.ptr;
rmesa->dma.current.ptr += bytes;
rmesa->swtcl.numverts += nverts;
return head;
@@ -1260,7 +1260,7 @@ void r200InitSwtcl( GLcontext *ctx )
tnl->Driver.Render.ResetLineStipple = r200ResetLineStipple;
tnl->Driver.Render.BuildVertices = r200BuildVertices;
- rmesa->swtcl.verts = (char *)ALIGN_MALLOC( size * 16 * 4, 32 );
+ rmesa->swtcl.verts = (GLubyte *)ALIGN_MALLOC( size * 16 * 4, 32 );
rmesa->swtcl.RenderIndex = ~0;
rmesa->swtcl.render_primitive = GL_TRIANGLES;
rmesa->swtcl.hw_primitive = 0;
diff --git a/src/mesa/drivers/dri/r200/r200_tcl.c b/src/mesa/drivers/dri/r200/r200_tcl.c
index 994221d80c..9869ad6196 100644
--- a/src/mesa/drivers/dri/r200/r200_tcl.c
+++ b/src/mesa/drivers/dri/r200/r200_tcl.c
@@ -102,33 +102,23 @@ static GLboolean discrete_prim[0x10] = {
};
-#define LOCAL_VARS r200ContextPtr rmesa = R200_CONTEXT(ctx);rmesa = rmesa
-#define ELTS_VARS GLushort *dest
+#define LOCAL_VARS r200ContextPtr rmesa = R200_CONTEXT(ctx)
+#define ELT_TYPE GLushort
#define ELT_INIT(prim, hw_prim) \
r200TclPrimitive( ctx, prim, hw_prim | R200_VF_PRIM_WALK_IND )
-#define GET_ELTS() rmesa->tcl.Elts
+#define GET_MESA_ELTS() rmesa->tcl.Elts
-#define NEW_PRIMITIVE() R200_NEWPRIM( rmesa )
-#define NEW_BUFFER() r200RefillCurrentDmaRegion( rmesa )
-
/* Don't really know how many elts will fit in what's left of cmdbuf,
* as there is state to emit, etc:
*/
-#if 0
-#define GET_CURRENT_VB_MAX_ELTS() \
- ((R200_CMD_BUF_SZ - (rmesa->store.cmd_used + 16)) / 2)
-#define GET_SUBSEQUENT_VB_MAX_ELTS() ((R200_CMD_BUF_SZ - 16) / 2)
-#else
/* Testing on isosurf shows a maximum around here. Don't know if it's
* the card or driver or kernel module that is causing the behaviour.
*/
-#define GET_CURRENT_VB_MAX_ELTS() 300
-#define GET_SUBSEQUENT_VB_MAX_ELTS() 300
-#endif
+#define GET_MAX_HW_ELTS() 300
#define RESET_STIPPLE() do { \
R200_STATECHANGE( rmesa, lin ); \
@@ -147,32 +137,22 @@ static GLboolean discrete_prim[0x10] = {
} while (0)
-/* How do you extend an existing primitive?
- */
-#define ALLOC_ELTS(nr) \
-do { \
- if (rmesa->dma.flush == r200FlushElts && \
- rmesa->store.cmd_used + nr*2 < R200_CMD_BUF_SZ) { \
- \
- dest = (GLushort *)(rmesa->store.cmd_buf + \
- rmesa->store.cmd_used); \
- rmesa->store.cmd_used += nr*2; \
- } \
- else { \
- if (rmesa->dma.flush) \
- rmesa->dma.flush( rmesa ); \
- \
- r200EmitAOS( rmesa, \
- rmesa->tcl.aos_components, \
- rmesa->tcl.nr_aos_components, \
- 0 ); \
- \
- dest = r200AllocEltsOpenEnded( rmesa, \
- rmesa->tcl.hw_primitive, \
- nr ); \
- } \
-} while (0)
+#define ALLOC_ELTS(nr) r200AllocElts( rmesa, nr )
+static GLushort *r200AllocElts( r200ContextPtr rmesa, GLuint nr )
+{
+ if (rmesa->dma.flush)
+ rmesa->dma.flush( rmesa );
+
+ r200EmitAOS( rmesa,
+ rmesa->tcl.aos_components,
+ rmesa->tcl.nr_aos_components, 0 );
+
+ return r200AllocEltsOpenEnded( rmesa, rmesa->tcl.hw_primitive, nr );
+}
+
+
+#define CLOSE_ELTS() R200_NEWPRIM( rmesa )
/* TODO: Try to extend existing primitive if both are identical,
@@ -217,17 +197,15 @@ static void EMIT_PRIM( GLcontext *ctx,
#ifdef MESA_BIG_ENDIAN
/* We could do without (most of) this ugliness if dest was always 32 bit word aligned... */
-#define EMIT_ELT(offset, x) do { \
+#define EMIT_ELT(dest, offset, x) do { \
int off = offset + ( ( (GLuint)dest & 0x2 ) >> 1 ); \
GLushort *des = (GLushort *)( (GLuint)dest & ~0x2 ); \
(des)[ off + 1 - 2 * ( off & 1 ) ] = (GLushort)(x); } while (0)
#else
-#define EMIT_ELT(offset, x) (dest)[offset] = (GLushort) (x)
+#define EMIT_ELT(dest, offset, x) (dest)[offset] = (GLushort) (x)
#endif
-#define EMIT_TWO_ELTS(offset, x, y) *(GLuint *)(dest+offset) = ((y)<<16)|(x);
-#define INCR_ELTS( nr ) dest += nr
-#define RELEASE_ELT_VERTS() \
- r200ReleaseArrays( ctx, ~0 )
+
+#define EMIT_TWO_ELTS(dest, offset, x, y) *(GLuint *)((dest)+offset) = ((y)<<16)|(x);
diff --git a/src/mesa/drivers/dri/radeon/Makefile.X11 b/src/mesa/drivers/dri/radeon/Makefile.X11
new file mode 100644
index 0000000000..b73abe8f51
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/Makefile.X11
@@ -0,0 +1,154 @@
+# $Id: Makefile.X11,v 1.1 2003/08/22 20:11:45 brianp Exp $
+
+# Mesa 3-D graphics library
+# Version: 5.0
+# Copyright (C) 1995-2002 Brian Paul
+
+TOP = ../../../../..
+
+default: linux-solo
+
+SHARED_INCLUDES = $(INCLUDE_DIRS) -I. -I../common -Iserver
+MINIGLX_INCLUDES = -I$(TOP)/src/glx/mini
+
+ifeq ($(EMBEDDED),true)
+TARGET = radeon_es_dri.so
+DEFINES += \
+ -D_EMBEDDED \
+ -D_HAVE_SWRAST=0 \
+ -D_HAVE_SWTNL=0 \
+ -D_HAVE_SANITY=0 \
+ -D_HAVE_CODEGEN=0 \
+ -D_HAVE_LIGHTING=0 \
+ -D_HAVE_TEXGEN=0 \
+ -D_HAVE_USERCLIP=0 \
+ -DGLX_DIRECT_RENDERING
+else
+TARGET = radeon_dri.so
+DEFINES += \
+ -D_HAVE_SWRAST=1 \
+ -D_HAVE_SWTNL=1 \
+ -D_HAVE_SANITY=1 \
+ -D_HAVE_CODEGEN=1 \
+ -D_HAVE_LIGHTING=1 \
+ -D_HAVE_TEXGEN=1 \
+ -D_HAVE_USERCLIP=1 \
+ -DGLX_DIRECT_RENDERING
+endif
+
+MESA_MODULES = $(TOP)/src/mesa/mesa.a
+
+MINIGLX_SOURCES = server/radeon_dri.c
+
+DRIVER_SOURCES = radeon_context.c \
+ radeon_ioctl.c \
+ radeon_lock.c \
+ radeon_screen.c \
+ radeon_state.c \
+ radeon_state_init.c \
+ ../common/mm.c \
+ ../common/utils.c \
+ ../common/texmem.c \
+ ../common/vblank.c
+
+SUBSET_DRIVER_SOURCES = \
+ radeon_subset_bitmap.c \
+ radeon_subset_readpix.c \
+ radeon_subset_select.c \
+ radeon_subset_tex.c \
+ radeon_subset_vtx.c
+
+FULL_DRIVER_SOURCES = \
+ radeon_tex.c \
+ radeon_texmem.c \
+ radeon_texstate.c \
+ radeon_tcl.c \
+ radeon_swtcl.c \
+ radeon_span.c \
+ radeon_maos.c \
+ radeon_sanity.c \
+ radeon_compat.c \
+ radeon_vtxfmt.c \
+ radeon_vtxfmt_c.c \
+ radeon_vtxfmt_sse.c \
+ radeon_vtxfmt_x86.c
+
+
+INCLUDES = $(MINIGLX_INCLUDES) \
+ $(SHARED_INCLUDES)
+
+
+ifeq ($(EMBEDDED),true)
+C_SOURCES = $(DRIVER_SOURCES) \
+ $(SUBSET_DRIVER_SOURCES) \
+ $(MINIGLX_SOURCES)
+else
+C_SOURCES = $(DRIVER_SOURCES) \
+ $(FULL_DRIVER_SOURCES) \
+ $(MINIGLX_SOURCES)
+endif
+
+
+ifeq ($(WINDOW_SYSTEM),dri)
+WINOBJ=$(MESABUILDDIR)/dri/dri.a
+WINLIB=
+else
+WINOBJ=
+WINLIB=-L$(MESA)/src/glx/mini
+endif
+
+ASM_SOURCES =
+OBJECTS = $(C_SOURCES:.c=.o) \
+ $(ASM_SOURCES:.S=.o)
+
+### Include directories
+
+INCLUDE_DIRS = \
+ -I$(TOP)/include \
+ -I$(TOP)/src/mesa \
+ -I$(TOP)/src/mesa/main \
+ -I$(TOP)/src/mesa/glapi \
+ -I$(TOP)/src/mesa/math \
+ -I$(TOP)/src/mesa/transform \
+ -I$(TOP)/src/mesa/swrast \
+ -I$(TOP)/src/mesa/swrast_setup
+
+
+##### RULES #####
+
+.c.o:
+ $(CC) -c $(SHARED_INCLUDES) $(MINIGLX_INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
+
+.S.o:
+ $(CC) -c $(SHARED_INCLUDES) $(MINIGLX_INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
+
+
+##### TARGETS #####
+
+targets: depend $(TARGET)
+
+$(TARGET): $(OBJECTS) $(MESA_MODULES) $(WINOBJ) Makefile.X11
+ rm -f $@ && gcc -o $@ -shared $(OBJECTS) $(MESA_MODULES) $(WINOBJ) $(WINLIB) -lc -lm
+ rm -f $(TOP)/lib/$(TARGET) && \
+ install $(TARGET) $(TOP)/lib/$(TARGET)
+
+# Run 'make -f Makefile.X11 dep' to update the dependencies if you change
+# what's included by any source file.
+depend: $(C_SOURCES) $(ASM_SOURCES)
+ makedepend -fdepend -Y $(SHARED_INCLUDES) $(MINIGLX_INCLUDES)\
+ $(C_SOURCES) $(ASM_SOURCES)
+
+
+# Emacs tags
+tags:
+ etags `find . -name \*.[ch]` `find ../include`
+
+
+# Remove .o and backup files
+clean:
+ -rm -f *.o *~ *.o *~ *.so server/*.o
+
+
+include $(TOP)/Make-config
+
+include depend
diff --git a/src/mesa/drivers/dri/radeon/radeon_compat.c b/src/mesa/drivers/dri/radeon/radeon_compat.c
new file mode 100644
index 0000000000..0c32641530
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_compat.c
@@ -0,0 +1,304 @@
+/* $XFree86$ */
+/**************************************************************************
+
+Copyright 2002 ATI Technologies Inc., Ontario, Canada, and
+ Tungsten Graphics Inc., Austin, Texas.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+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, TUNGSTEN GRAPHICS 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>
+ *
+ */
+
+#include "glheader.h"
+#include "imports.h"
+
+#include "radeon_context.h"
+#include "radeon_state.h"
+#include "radeon_ioctl.h"
+
+
+static struct {
+ int start;
+ int len;
+ const char *name;
+} packet[RADEON_MAX_STATE_PACKETS] = {
+ { RADEON_PP_MISC,7,"RADEON_PP_MISC" },
+ { RADEON_PP_CNTL,3,"RADEON_PP_CNTL" },
+ { RADEON_RB3D_COLORPITCH,1,"RADEON_RB3D_COLORPITCH" },
+ { RADEON_RE_LINE_PATTERN,2,"RADEON_RE_LINE_PATTERN" },
+ { RADEON_SE_LINE_WIDTH,1,"RADEON_SE_LINE_WIDTH" },
+ { RADEON_PP_LUM_MATRIX,1,"RADEON_PP_LUM_MATRIX" },
+ { RADEON_PP_ROT_MATRIX_0,2,"RADEON_PP_ROT_MATRIX_0" },
+ { RADEON_RB3D_STENCILREFMASK,3,"RADEON_RB3D_STENCILREFMASK" },
+ { RADEON_SE_VPORT_XSCALE,6,"RADEON_SE_VPORT_XSCALE" },
+ { RADEON_SE_CNTL,2,"RADEON_SE_CNTL" },
+ { RADEON_SE_CNTL_STATUS,1,"RADEON_SE_CNTL_STATUS" },
+ { RADEON_RE_MISC,1,"RADEON_RE_MISC" },
+ { RADEON_PP_TXFILTER_0,6,"RADEON_PP_TXFILTER_0" },
+ { RADEON_PP_BORDER_COLOR_0,1,"RADEON_PP_BORDER_COLOR_0" },
+ { RADEON_PP_TXFILTER_1,6,"RADEON_PP_TXFILTER_1" },
+ { RADEON_PP_BORDER_COLOR_1,1,"RADEON_PP_BORDER_COLOR_1" },
+ { RADEON_PP_TXFILTER_2,6,"RADEON_PP_TXFILTER_2" },
+ { RADEON_PP_BORDER_COLOR_2,1,"RADEON_PP_BORDER_COLOR_2" },
+ { RADEON_SE_ZBIAS_FACTOR,2,"RADEON_SE_ZBIAS_FACTOR" },
+ { RADEON_SE_TCL_OUTPUT_VTX_FMT,11,"RADEON_SE_TCL_OUTPUT_VTX_FMT" },
+ { RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED,17,"RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED" },
+};
+
+
+static void radeonCompatEmitPacket( radeonContextPtr rmesa,
+ struct radeon_state_atom *state )
+{
+ RADEONSAREAPrivPtr sarea = rmesa->sarea;
+ radeon_context_regs_t *ctx = &sarea->ContextState;
+ radeon_texture_regs_t *tex0 = &sarea->TexState[0];
+ radeon_texture_regs_t *tex1 = &sarea->TexState[1];
+ int i;
+ int *buf = state->cmd;
+
+ for ( i = 0 ; i < state->cmd_size ; ) {
+ drmRadeonCmdHeader *header = (drmRadeonCmdHeader *)&buf[i++];
+
+ if (RADEON_DEBUG & DEBUG_STATE)
+ fprintf(stderr, "%s %d: %s\n", __FUNCTION__, header->packet.packet_id,
+ packet[(int)header->packet.packet_id].name);
+
+ switch (header->packet.packet_id) {
+ case RADEON_EMIT_PP_MISC:
+ ctx->pp_misc = buf[i++];
+ ctx->pp_fog_color = buf[i++];
+ ctx->re_solid_color = buf[i++];
+ ctx->rb3d_blendcntl = buf[i++];
+ ctx->rb3d_depthoffset = buf[i++];
+ ctx->rb3d_depthpitch = buf[i++];
+ ctx->rb3d_zstencilcntl = buf[i++];
+ sarea->dirty |= RADEON_UPLOAD_CONTEXT;
+ break;
+ case RADEON_EMIT_PP_CNTL:
+ ctx->pp_cntl = buf[i++];
+ ctx->rb3d_cntl = buf[i++];
+ ctx->rb3d_coloroffset = buf[i++];
+ sarea->dirty |= RADEON_UPLOAD_CONTEXT;
+ break;
+ case RADEON_EMIT_RB3D_COLORPITCH:
+ ctx->rb3d_colorpitch = buf[i++];
+ sarea->dirty |= RADEON_UPLOAD_CONTEXT;
+ break;
+ case RADEON_EMIT_RE_LINE_PATTERN:
+ ctx->re_line_pattern = buf[i++];
+ ctx->re_line_state = buf[i++];
+ sarea->dirty |= RADEON_UPLOAD_LINE;
+ break;
+ case RADEON_EMIT_SE_LINE_WIDTH:
+ ctx->se_line_width = buf[i++];
+ sarea->dirty |= RADEON_UPLOAD_LINE;
+ break;
+ case RADEON_EMIT_PP_LUM_MATRIX:
+ ctx->pp_lum_matrix = buf[i++];
+ sarea->dirty |= RADEON_UPLOAD_BUMPMAP;
+ break;
+ case RADEON_EMIT_PP_ROT_MATRIX_0:
+ ctx->pp_rot_matrix_0 = buf[i++];
+ ctx->pp_rot_matrix_1 = buf[i++];
+ sarea->dirty |= RADEON_UPLOAD_BUMPMAP;
+ break;
+ case RADEON_EMIT_RB3D_STENCILREFMASK:
+ ctx->rb3d_stencilrefmask = buf[i++];
+ ctx->rb3d_ropcntl = buf[i++];
+ ctx->rb3d_planemask = buf[i++];
+ sarea->dirty |= RADEON_UPLOAD_MASKS;
+ break;
+ case RADEON_EMIT_SE_VPORT_XSCALE:
+ ctx->se_vport_xscale = buf[i++];
+ ctx->se_vport_xoffset = buf[i++];
+ ctx->se_vport_yscale = buf[i++];
+ ctx->se_vport_yoffset = buf[i++];
+ ctx->se_vport_zscale = buf[i++];
+ ctx->se_vport_zoffset = buf[i++];
+ sarea->dirty |= RADEON_UPLOAD_VIEWPORT;
+ break;
+ case RADEON_EMIT_SE_CNTL:
+ ctx->se_cntl = buf[i++];
+ ctx->se_coord_fmt = buf[i++];
+ sarea->dirty |= RADEON_UPLOAD_CONTEXT | RADEON_UPLOAD_VERTFMT;
+ break;
+ case RADEON_EMIT_SE_CNTL_STATUS:
+ ctx->se_cntl_status = buf[i++];
+ sarea->dirty |= RADEON_UPLOAD_SETUP;
+ break;
+ case RADEON_EMIT_RE_MISC:
+ ctx->re_misc = buf[i++];
+ sarea->dirty |= RADEON_UPLOAD_MISC;
+ break;
+ case RADEON_EMIT_PP_TXFILTER_0:
+ tex0->pp_txfilter = buf[i++];
+ tex0->pp_txformat = buf[i++];
+ tex0->pp_txoffset = buf[i++];
+ tex0->pp_txcblend = buf[i++];
+ tex0->pp_txablend = buf[i++];
+ tex0->pp_tfactor = buf[i++];
+ sarea->dirty |= RADEON_UPLOAD_TEX0;
+ break;
+ case RADEON_EMIT_PP_BORDER_COLOR_0:
+ tex0->pp_border_color = buf[i++];
+ sarea->dirty |= RADEON_UPLOAD_TEX0;
+ break;
+ case RADEON_EMIT_PP_TXFILTER_1:
+ tex1->pp_txfilter = buf[i++];
+ tex1->pp_txformat = buf[i++];
+ tex1->pp_txoffset = buf[i++];
+ tex1->pp_txcblend = buf[i++];
+ tex1->pp_txablend = buf[i++];
+ tex1->pp_tfactor = buf[i++];
+ sarea->dirty |= RADEON_UPLOAD_TEX1;
+ break;
+ case RADEON_EMIT_PP_BORDER_COLOR_1:
+ tex1->pp_border_color = buf[i++];
+ sarea->dirty |= RADEON_UPLOAD_TEX1;
+ break;
+
+ case RADEON_EMIT_SE_ZBIAS_FACTOR:
+ i++;
+ i++;
+ break;
+
+ case RADEON_EMIT_PP_TXFILTER_2:
+ case RADEON_EMIT_PP_BORDER_COLOR_2:
+ case RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT:
+ case RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED:
+ default:
+ /* These states aren't understood by radeon drm 1.1 */
+ fprintf(stderr, "Tried to emit unsupported state\n");
+ return;
+ }
+ }
+}
+
+
+
+static void radeonCompatEmitStateLocked( radeonContextPtr rmesa )
+{
+ struct radeon_state_atom *state, *tmp;
+
+ if (RADEON_DEBUG & (DEBUG_STATE|DEBUG_PRIMS))
+ fprintf(stderr, "%s\n", __FUNCTION__);
+
+ if (rmesa->lost_context) {
+ if (RADEON_DEBUG & (DEBUG_STATE|DEBUG_PRIMS|DEBUG_IOCTL))
+ fprintf(stderr, "%s - lost context\n", __FUNCTION__);
+
+ foreach_s( state, tmp, &(rmesa->hw.clean) )
+ move_to_tail(&(rmesa->hw.dirty), state );
+
+ rmesa->lost_context = 0;
+ }
+
+ foreach_s( state, tmp, &(rmesa->hw.dirty) ) {
+ if (!state->is_tcl)
+ radeonCompatEmitPacket( rmesa, state );
+ move_to_head( &(rmesa->hw.clean), state );
+ }
+}
+
+
+
+static void radeonCompatEmitPrimitiveLocked( radeonContextPtr rmesa,
+ GLuint hw_primitive,
+ GLuint nverts,
+ XF86DRIClipRectPtr pbox,
+ GLuint nbox )
+{
+ int i;
+
+ for ( i = 0 ; i < nbox ; ) {
+ int nr = MIN2( i + RADEON_NR_SAREA_CLIPRECTS, nbox );
+ XF86DRIClipRectPtr b = rmesa->sarea->boxes;
+ drmRadeonVertex vtx;
+
+ rmesa->sarea->dirty |= RADEON_UPLOAD_CLIPRECTS;
+ rmesa->sarea->nbox = nr - i;
+
+ for ( ; i < nr ; i++)
+ *b++ = pbox[i];
+
+ if (RADEON_DEBUG & DEBUG_IOCTL)
+ fprintf(stderr,
+ "RadeonFlushVertexBuffer: prim %x buf %d verts %d "
+ "disc %d nbox %d\n",
+ hw_primitive,
+ rmesa->dma.current.buf->buf->idx,
+ nverts,
+ nr == nbox,
+ rmesa->sarea->nbox );
+
+ vtx.prim = hw_primitive;
+ vtx.idx = rmesa->dma.current.buf->buf->idx;
+ vtx.count = nverts;
+ vtx.discard = (nr == nbox);
+
+ drmCommandWrite( rmesa->dri.fd,
+ DRM_RADEON_VERTEX,
+ &vtx, sizeof(vtx));
+ }
+}
+
+
+
+/* No 'start' for 1.1 vertices ioctl: only one vertex prim/buffer!
+ */
+void radeonCompatEmitPrimitive( radeonContextPtr rmesa,
+ GLuint vertex_format,
+ GLuint hw_primitive,
+ GLuint nrverts )
+{
+ if (RADEON_DEBUG & DEBUG_IOCTL)
+ fprintf(stderr, "%s\n", __FUNCTION__);
+
+ LOCK_HARDWARE( rmesa );
+
+ radeonCompatEmitStateLocked( rmesa );
+ rmesa->sarea->vc_format = vertex_format;
+
+ if (rmesa->state.scissor.enabled) {
+ radeonCompatEmitPrimitiveLocked( rmesa,
+ hw_primitive,
+ nrverts,
+ rmesa->state.scissor.pClipRects,
+ rmesa->state.scissor.numClipRects );
+ }
+ else {
+ radeonCompatEmitPrimitiveLocked( rmesa,
+ hw_primitive,
+ nrverts,
+ rmesa->pClipRects,
+ rmesa->numClipRects );
+ }
+
+
+ UNLOCK_HARDWARE( rmesa );
+}
+
diff --git a/src/mesa/drivers/dri/radeon/radeon_context.c b/src/mesa/drivers/dri/radeon/radeon_context.c
new file mode 100644
index 0000000000..835cecbc3a
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_context.c
@@ -0,0 +1,598 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_context.c,v 1.7 2003/02/08 21:26:45 dawes 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 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 THE COPYRIGHT OWNER(S) 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:
+ * Kevin E. Martin <martin@valinux.com>
+ * Gareth Hughes <gareth@valinux.com>
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "glheader.h"
+#include "api_arrayelt.h"
+#include "context.h"
+#include "simple_list.h"
+#include "imports.h"
+#include "matrix.h"
+#include "extensions.h"
+
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "array_cache/acache.h"
+
+#include "tnl/tnl.h"
+#include "tnl/t_pipeline.h"
+
+#include "radeon_context.h"
+#include "radeon_ioctl.h"
+#include "radeon_state.h"
+#include "radeon_span.h"
+#include "radeon_tex.h"
+#include "radeon_swtcl.h"
+#include "radeon_tcl.h"
+#include "radeon_vtxfmt.h"
+#include "radeon_maos.h"
+
+#define DRIVER_DATE "20030328"
+
+#include "vblank.h"
+#include "utils.h"
+#ifndef RADEON_DEBUG
+int RADEON_DEBUG = (0);
+#endif
+
+
+
+/* Return the width and height of the given buffer.
+ */
+static void radeonGetBufferSize( GLframebuffer *buffer,
+ GLuint *width, GLuint *height )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ LOCK_HARDWARE( rmesa );
+ *width = rmesa->dri.drawable->w;
+ *height = rmesa->dri.drawable->h;
+ UNLOCK_HARDWARE( rmesa );
+}
+
+/* Return various strings for glGetString().
+ */
+static const GLubyte *radeonGetString( GLcontext *ctx, GLenum name )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ static char buffer[128];
+ unsigned offset;
+ GLuint agp_mode = rmesa->radeonScreen->IsPCI ? 0 :
+ rmesa->radeonScreen->AGPMode;
+
+ switch ( name ) {
+ case GL_VENDOR:
+ return (GLubyte *)"Tungsten Graphics, Inc.";
+
+ case GL_RENDERER:
+ offset = driGetRendererString( buffer, "Radeon", DRIVER_DATE,
+ agp_mode );
+
+ sprintf( & buffer[ offset ], "%s %sTCL",
+ ( rmesa->dri.drmMinor < 3 ) ? " DRM-COMPAT" : "",
+ !(rmesa->TclFallback & RADEON_TCL_FALLBACK_TCL_DISABLE)
+ ? "" : "NO-" );
+
+ return (GLubyte *)buffer;
+
+ default:
+ return NULL;
+ }
+}
+
+
+/* Extension strings exported by the R100 driver.
+ */
+static const char * const card_extensions[] =
+{
+ "GL_ARB_multisample",
+ "GL_ARB_multitexture",
+ "GL_ARB_texture_border_clamp",
+ "GL_ARB_texture_compression",
+ "GL_ARB_texture_env_add",
+ "GL_ARB_texture_env_combine",
+ "GL_ARB_texture_env_dot3",
+ "GL_ARB_texture_mirrored_repeat",
+ "GL_EXT_blend_logic_op",
+ "GL_EXT_blend_subtract",
+ "GL_EXT_secondary_color",
+ "GL_EXT_texture_edge_clamp",
+ "GL_EXT_texture_env_add",
+ "GL_EXT_texture_env_combine",
+ "GL_EXT_texture_env_dot3",
+ "GL_EXT_texture_filter_anisotropic",
+ "GL_EXT_texture_lod_bias",
+ "GL_ATI_texture_env_combine3",
+ "GL_ATI_texture_mirror_once",
+ "GL_IBM_texture_mirrored_repeat",
+ "GL_MESA_ycbcr_texture",
+ "GL_NV_blend_square",
+ "GL_SGIS_generate_mipmap",
+ "GL_SGIS_texture_border_clamp",
+ "GL_SGIS_texture_edge_clamp",
+ NULL
+};
+
+extern const struct gl_pipeline_stage _radeon_texrect_stage;
+extern const struct gl_pipeline_stage _radeon_render_stage;
+extern const struct gl_pipeline_stage _radeon_tcl_stage;
+
+static const struct gl_pipeline_stage *radeon_pipeline[] = {
+
+ /* Try and go straight to t&l
+ */
+ &_radeon_tcl_stage,
+
+ /* Catch any t&l fallbacks
+ */
+ &_tnl_vertex_transform_stage,
+ &_tnl_normal_transform_stage,
+ &_tnl_lighting_stage,
+ &_tnl_fog_coordinate_stage,
+ &_tnl_texgen_stage,
+ &_tnl_texture_transform_stage,
+
+ /* Scale texture rectangle to 0..1.
+ */
+ &_radeon_texrect_stage,
+
+ &_radeon_render_stage,
+ &_tnl_render_stage, /* FALLBACK: */
+ 0,
+};
+
+
+
+/* Initialize the driver's misc functions.
+ */
+static void radeonInitDriverFuncs( GLcontext *ctx )
+{
+ ctx->Driver.GetBufferSize = radeonGetBufferSize;
+ ctx->Driver.ResizeBuffers = _swrast_alloc_buffers;
+ ctx->Driver.GetString = radeonGetString;
+
+ ctx->Driver.Error = NULL;
+ ctx->Driver.DrawPixels = NULL;
+ ctx->Driver.Bitmap = NULL;
+}
+
+static const struct dri_debug_control debug_control[] =
+{
+ { "fall", DEBUG_FALLBACKS },
+ { "tex", DEBUG_TEXTURE },
+ { "ioctl", DEBUG_IOCTL },
+ { "prim", DEBUG_PRIMS },
+ { "vert", DEBUG_VERTS },
+ { "state", DEBUG_STATE },
+ { "code", DEBUG_CODEGEN },
+ { "vfmt", DEBUG_VFMT },
+ { "vtxf", DEBUG_VFMT },
+ { "verb", DEBUG_VERBOSE },
+ { "dri", DEBUG_DRI },
+ { "dma", DEBUG_DMA },
+ { "san", DEBUG_SANITY },
+ { NULL, 0 }
+};
+
+
+static int
+get_ust_nop( uint64_t * ust )
+{
+ *ust = 1;
+ return 0;
+}
+
+
+/* Create the device specific context.
+ */
+GLboolean
+radeonCreateContext( const __GLcontextModes *glVisual,
+ __DRIcontextPrivate *driContextPriv,
+ void *sharedContextPrivate)
+{
+ __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
+ radeonScreenPtr screen = (radeonScreenPtr)(sPriv->private);
+ radeonContextPtr rmesa;
+ GLcontext *ctx, *shareCtx;
+ int i;
+
+ assert(glVisual);
+ assert(driContextPriv);
+ assert(screen);
+
+ /* Allocate the Radeon context */
+ rmesa = (radeonContextPtr) CALLOC( sizeof(*rmesa) );
+ if ( !rmesa )
+ return GL_FALSE;
+
+ /* Allocate the Mesa context */
+ if (sharedContextPrivate)
+ shareCtx = ((radeonContextPtr) sharedContextPrivate)->glCtx;
+ else
+ shareCtx = NULL;
+ rmesa->glCtx = _mesa_create_context(glVisual, shareCtx, (void *) rmesa, GL_TRUE);
+ if (!rmesa->glCtx) {
+ FREE(rmesa);
+ return GL_FALSE;
+ }
+ driContextPriv->driverPrivate = rmesa;
+
+ /* Init radeon context data */
+ rmesa->dri.context = driContextPriv;
+ rmesa->dri.screen = sPriv;
+ rmesa->dri.drawable = NULL; /* Set by XMesaMakeCurrent */
+ rmesa->dri.hwContext = driContextPriv->hHWContext;
+ rmesa->dri.hwLock = &sPriv->pSAREA->lock;
+ rmesa->dri.fd = sPriv->fd;
+
+ /* If we don't have 1.3, fallback to the 1.1 interfaces.
+ */
+ if (getenv("RADEON_COMPAT") || sPriv->drmMinor < 3 )
+ rmesa->dri.drmMinor = 1;
+ else
+ rmesa->dri.drmMinor = sPriv->drmMinor;
+
+ rmesa->radeonScreen = screen;
+ rmesa->sarea = (RADEONSAREAPrivPtr)((GLubyte *)sPriv->pSAREA +
+ screen->sarea_priv_offset);
+
+
+ rmesa->dma.buf0_address = rmesa->radeonScreen->buffers->list[0].address;
+
+ (void) memset( rmesa->texture_heaps, 0, sizeof( rmesa->texture_heaps ) );
+ make_empty_list( & rmesa->swapped );
+
+ rmesa->nr_heaps = screen->numTexHeaps;
+ for ( i = 0 ; i < rmesa->nr_heaps ; i++ ) {
+ rmesa->texture_heaps[i] = driCreateTextureHeap( i, rmesa,
+ screen->texSize[i],
+ 12,
+ RADEON_NR_TEX_REGIONS,
+ rmesa->sarea->texList[i],
+ & rmesa->sarea->texAge[i],
+ & rmesa->swapped,
+ sizeof( radeonTexObj ),
+ (destroy_texture_object_t *) radeonDestroyTexObj );
+
+ driSetTextureSwapCounterLocation( rmesa->texture_heaps[i],
+ & rmesa->c_textureSwaps );
+ }
+
+ rmesa->swtcl.RenderIndex = ~0;
+ rmesa->lost_context = 1;
+
+ /* Set the maximum texture size small enough that we can guarentee that
+ * all texture units can bind a maximal texture and have them both in
+ * texturable memory at once.
+ */
+
+ ctx = rmesa->glCtx;
+ ctx->Const.MaxTextureUnits = 2;
+
+ driCalculateMaxTextureLevels( rmesa->texture_heaps,
+ rmesa->nr_heaps,
+ & ctx->Const,
+ 4,
+ 11, /* max 2D texture size is 2048x2048 */
+ 0, /* 3D textures unsupported. */
+ 0, /* cube textures unsupported. */
+ 11, /* max rect texture size is 2048x2048. */
+ 12,
+ GL_FALSE );
+
+ ctx->Const.MaxTextureMaxAnisotropy = 16.0;
+
+ /* No wide points.
+ */
+ ctx->Const.MinPointSize = 1.0;
+ ctx->Const.MinPointSizeAA = 1.0;
+ ctx->Const.MaxPointSize = 1.0;
+ ctx->Const.MaxPointSizeAA = 1.0;
+
+ ctx->Const.MinLineWidth = 1.0;
+ ctx->Const.MinLineWidthAA = 1.0;
+ ctx->Const.MaxLineWidth = 10.0;
+ ctx->Const.MaxLineWidthAA = 10.0;
+ ctx->Const.LineWidthGranularity = 0.0625;
+
+ /* Set maxlocksize (and hence vb size) small enough to avoid
+ * fallbacks in radeon_tcl.c. ie. guarentee that all vertices can
+ * fit in a single dma buffer for indexed rendering of quad strips,
+ * etc.
+ */
+ ctx->Const.MaxArrayLockSize =
+ MIN2( ctx->Const.MaxArrayLockSize,
+ RADEON_BUFFER_SIZE / RADEON_MAX_TCL_VERTSIZE );
+
+ rmesa->boxes = (getenv("LIBGL_PERFORMANCE_BOXES") != NULL);
+
+ /* Initialize the software rasterizer and helper modules.
+ */
+ _swrast_CreateContext( ctx );
+ _ac_CreateContext( ctx );
+ _tnl_CreateContext( ctx );
+ _swsetup_CreateContext( ctx );
+ _ae_create_context( ctx );
+
+ /* Install the customized pipeline:
+ */
+ _tnl_destroy_pipeline( ctx );
+ _tnl_install_pipeline( ctx, radeon_pipeline );
+ ctx->Driver.FlushVertices = radeonFlushVertices;
+
+ /* Try and keep materials and vertices separate:
+ */
+ _tnl_isolate_materials( ctx, GL_TRUE );
+
+
+/* _mesa_allow_light_in_model( ctx, GL_FALSE ); */
+
+ /* Try and keep materials and vertices separate:
+ */
+ _tnl_isolate_materials( ctx, GL_TRUE );
+
+
+ /* Configure swrast to match hardware characteristics:
+ */
+ _swrast_allow_pixel_fog( ctx, GL_FALSE );
+ _swrast_allow_vertex_fog( ctx, GL_TRUE );
+
+
+ _math_matrix_ctr( &rmesa->TexGenMatrix[0] );
+ _math_matrix_ctr( &rmesa->TexGenMatrix[1] );
+ _math_matrix_ctr( &rmesa->tmpmat );
+ _math_matrix_set_identity( &rmesa->TexGenMatrix[0] );
+ _math_matrix_set_identity( &rmesa->TexGenMatrix[1] );
+ _math_matrix_set_identity( &rmesa->tmpmat );
+
+ driInitExtensions( ctx, card_extensions, GL_TRUE );
+
+ if (rmesa->dri.drmMinor >= 9)
+ _mesa_enable_extension( ctx, "GL_NV_texture_rectangle");
+
+ radeonInitDriverFuncs( ctx );
+ radeonInitIoctlFuncs( ctx );
+ radeonInitStateFuncs( ctx );
+ radeonInitSpanFuncs( ctx );
+ radeonInitTextureFuncs( ctx );
+ radeonInitState( rmesa );
+ radeonInitSwtcl( ctx );
+
+ rmesa->iw.irq_seq = -1;
+ rmesa->irqsEmitted = 0;
+ rmesa->do_irqs = (rmesa->radeonScreen->irq && !getenv("RADEON_NO_IRQS"));
+
+ rmesa->do_usleeps = !getenv("RADEON_NO_USLEEPS");
+
+ rmesa->vblank_flags = (rmesa->do_irqs)
+ ? driGetDefaultVBlankFlags() : VBLANK_FLAG_NO_IRQ;
+
+#ifndef _SOLO
+ rmesa->get_ust = (PFNGLXGETUSTPROC) glXGetProcAddress( "__glXGetUST" );
+ if ( rmesa->get_ust == NULL )
+#endif
+ {
+ rmesa->get_ust = get_ust_nop;
+ }
+
+ (*rmesa->get_ust)( & rmesa->swap_ust );
+
+
+#if DO_DEBUG
+ RADEON_DEBUG = driParseDebugString( getenv( "RADEON_DEBUG" ),
+ debug_control );
+#endif
+
+ if (getenv("RADEON_NO_RAST")) {
+ fprintf(stderr, "disabling 3D acceleration\n");
+ FALLBACK(rmesa, RADEON_FALLBACK_DISABLE, 1);
+ }
+ else if (getenv("RADEON_TCL_FORCE_ENABLE")) {
+ fprintf(stderr, "Enabling TCL support... this will probably crash\n");
+ fprintf(stderr, " your card if it isn't capable of TCL!\n");
+ rmesa->radeonScreen->chipset |= RADEON_CHIPSET_TCL;
+ } else if (getenv("RADEON_TCL_FORCE_DISABLE") ||
+ rmesa->dri.drmMinor < 3 ||
+ !(rmesa->radeonScreen->chipset & RADEON_CHIPSET_TCL)) {
+ rmesa->radeonScreen->chipset &= ~RADEON_CHIPSET_TCL;
+ fprintf(stderr, "disabling TCL support\n");
+ TCL_FALLBACK(rmesa->glCtx, RADEON_TCL_FALLBACK_TCL_DISABLE, 1);
+ }
+
+ if (rmesa->radeonScreen->chipset & RADEON_CHIPSET_TCL) {
+ if (!getenv("RADEON_NO_VTXFMT"))
+ radeonVtxfmtInit( ctx );
+
+ _tnl_need_dlist_norm_lengths( ctx, GL_FALSE );
+ }
+ return GL_TRUE;
+}
+
+
+/* Destroy the device specific context.
+ */
+/* Destroy the Mesa and driver specific context data.
+ */
+void radeonDestroyContext( __DRIcontextPrivate *driContextPriv )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = (radeonContextPtr) driContextPriv->driverPrivate;
+ radeonContextPtr current = ctx ? RADEON_CONTEXT(ctx) : NULL;
+
+ /* check if we're deleting the currently bound context */
+ if (rmesa == current) {
+ RADEON_FIREVERTICES( rmesa );
+ _mesa_make_current2(NULL, NULL, NULL);
+ }
+
+ /* Free radeon context resources */
+ assert(rmesa); /* should never be null */
+ if ( rmesa ) {
+ GLboolean release_texture_heaps;
+
+
+ release_texture_heaps = (rmesa->glCtx->Shared->RefCount == 1);
+ _swsetup_DestroyContext( rmesa->glCtx );
+ _tnl_DestroyContext( rmesa->glCtx );
+ _ac_DestroyContext( rmesa->glCtx );
+ _swrast_DestroyContext( rmesa->glCtx );
+
+ radeonDestroySwtcl( rmesa->glCtx );
+ radeonReleaseArrays( rmesa->glCtx, ~0 );
+ if (rmesa->dma.current.buf) {
+ radeonReleaseDmaRegion( rmesa, &rmesa->dma.current, __FUNCTION__ );
+ radeonFlushCmdBuf( rmesa, __FUNCTION__ );
+ }
+
+ if (!rmesa->TclFallback & RADEON_TCL_FALLBACK_TCL_DISABLE)
+ if (!getenv("RADEON_NO_VTXFMT"))
+ radeonVtxfmtDestroy( rmesa->glCtx );
+
+ /* free the Mesa context */
+ rmesa->glCtx->DriverCtx = NULL;
+ _mesa_destroy_context( rmesa->glCtx );
+
+ if (rmesa->state.scissor.pClipRects) {
+ FREE(rmesa->state.scissor.pClipRects);
+ rmesa->state.scissor.pClipRects = 0;
+ }
+
+ if ( release_texture_heaps ) {
+ /* This share group is about to go away, free our private
+ * texture object data.
+ */
+ int i;
+
+ /* this assert is not correct, default textures are always on swap list
+ assert( is_empty_list( & rmesa->swapped ) ); */
+
+ for ( i = 0 ; i < rmesa->nr_heaps ; i++ ) {
+ driDestroyTextureHeap( rmesa->texture_heaps[ i ] );
+ rmesa->texture_heaps[ i ] = NULL;
+ }
+ }
+
+ FREE( rmesa );
+ }
+}
+
+
+
+
+void
+radeonSwapBuffers( __DRIdrawablePrivate *dPriv )
+{
+
+ if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
+ radeonContextPtr rmesa;
+ GLcontext *ctx;
+ rmesa = (radeonContextPtr) dPriv->driContextPriv->driverPrivate;
+ ctx = rmesa->glCtx;
+ if (ctx->Visual.doubleBufferMode) {
+ _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
+
+ if ( rmesa->doPageFlip ) {
+ radeonPageFlip( dPriv );
+ }
+ else {
+ radeonCopyBuffer( 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!", __FUNCTION__);
+ }
+}
+
+
+/* Force the context `c' to be the current context and associate with it
+ * buffer `b'.
+ */
+GLboolean
+radeonMakeCurrent( __DRIcontextPrivate *driContextPriv,
+ __DRIdrawablePrivate *driDrawPriv,
+ __DRIdrawablePrivate *driReadPriv )
+{
+ if ( driContextPriv ) {
+ radeonContextPtr newCtx =
+ (radeonContextPtr) driContextPriv->driverPrivate;
+
+ if (RADEON_DEBUG & DEBUG_DRI)
+ fprintf(stderr, "%s ctx %p\n", __FUNCTION__, newCtx->glCtx);
+
+ if ( newCtx->dri.drawable != driDrawPriv ) {
+ newCtx->dri.drawable = driDrawPriv;
+ radeonUpdateWindow( newCtx->glCtx );
+ radeonUpdateViewportOffset( newCtx->glCtx );
+ }
+
+ _mesa_make_current2( newCtx->glCtx,
+ (GLframebuffer *) driDrawPriv->driverPrivate,
+ (GLframebuffer *) driReadPriv->driverPrivate );
+
+ if ( !newCtx->glCtx->Viewport.Width ) {
+ _mesa_set_viewport( newCtx->glCtx, 0, 0,
+ driDrawPriv->w, driDrawPriv->h );
+ }
+
+ if (newCtx->vb.enabled)
+ radeonVtxfmtMakeCurrent( newCtx->glCtx );
+
+ } else {
+ if (RADEON_DEBUG & DEBUG_DRI)
+ fprintf(stderr, "%s ctx is null\n", __FUNCTION__);
+ _mesa_make_current( 0, 0 );
+ }
+
+ if (RADEON_DEBUG & DEBUG_DRI)
+ fprintf(stderr, "End %s\n", __FUNCTION__);
+ return GL_TRUE;
+}
+
+/* Force the context `c' to be unbound from its buffer.
+ */
+GLboolean
+radeonUnbindContext( __DRIcontextPrivate *driContextPriv )
+{
+ radeonContextPtr rmesa = (radeonContextPtr) driContextPriv->driverPrivate;
+
+ if (RADEON_DEBUG & DEBUG_DRI)
+ fprintf(stderr, "%s ctx %p\n", __FUNCTION__, rmesa->glCtx);
+
+ return GL_TRUE;
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_context.h b/src/mesa/drivers/dri/radeon/radeon_context.h
new file mode 100644
index 0000000000..5f1f9659e8
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_context.h
@@ -0,0 +1,839 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_context.h,v 1.6 2002/12/16 16:18:58 dawes 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 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 THE COPYRIGHT OWNER(S) 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:
+ * Kevin E. Martin <martin@valinux.com>
+ * Gareth Hughes <gareth@valinux.com>
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef __RADEON_CONTEXT_H__
+#define __RADEON_CONTEXT_H__
+
+#ifdef GLX_DIRECT_RENDERING
+
+#include <inttypes.h>
+#include "dri_util.h"
+#include "radeon_common.h"
+#include "texmem.h"
+
+#include "macros.h"
+#include "mtypes.h"
+#include "colormac.h"
+
+struct radeon_context;
+typedef struct radeon_context radeonContextRec;
+typedef struct radeon_context *radeonContextPtr;
+
+#include "radeon_lock.h"
+#include "radeon_screen.h"
+#include "mm.h"
+
+/* Flags for software fallback cases */
+/* See correponding strings in radeon_swtcl.c */
+#define RADEON_FALLBACK_TEXTURE 0x0001
+#define RADEON_FALLBACK_DRAW_BUFFER 0x0002
+#define RADEON_FALLBACK_STENCIL 0x0004
+#define RADEON_FALLBACK_RENDER_MODE 0x0008
+#define RADEON_FALLBACK_BLEND_EQ 0x0010
+#define RADEON_FALLBACK_BLEND_FUNC 0x0020
+#define RADEON_FALLBACK_DISABLE 0x0040
+#define RADEON_FALLBACK_BORDER_MODE 0x0080
+
+/* The blit width for texture uploads
+ */
+#define BLIT_WIDTH_BYTES 1024
+
+/* Use the templated vertex format:
+ */
+#define COLOR_IS_RGBA
+#define TAG(x) radeon##x
+#include "tnl_dd/t_dd_vertex.h"
+#undef TAG
+
+typedef void (*radeon_tri_func)( radeonContextPtr,
+ radeonVertex *,
+ radeonVertex *,
+ radeonVertex * );
+
+typedef void (*radeon_line_func)( radeonContextPtr,
+ radeonVertex *,
+ radeonVertex * );
+
+typedef void (*radeon_point_func)( radeonContextPtr,
+ radeonVertex * );
+
+
+struct radeon_colorbuffer_state {
+ GLuint clear;
+ GLint drawOffset, drawPitch;
+};
+
+
+struct radeon_depthbuffer_state {
+ GLuint clear;
+ GLfloat scale;
+};
+
+struct radeon_pixel_state {
+ GLint readOffset, readPitch;
+};
+
+struct radeon_scissor_state {
+ XF86DRIClipRectRec rect;
+ GLboolean enabled;
+
+ GLuint numClipRects; /* Cliprects active */
+ GLuint numAllocedClipRects; /* Cliprects available */
+ XF86DRIClipRectPtr pClipRects;
+};
+
+struct radeon_stencilbuffer_state {
+ GLboolean hwBuffer;
+ GLuint clear; /* rb3d_stencilrefmask value */
+};
+
+struct radeon_stipple_state {
+ GLuint mask[32];
+};
+
+
+
+#define TEX_0 0x1
+#define TEX_1 0x2
+#define TEX_ALL 0x3
+
+typedef struct radeon_tex_obj radeonTexObj, *radeonTexObjPtr;
+
+/* Texture object in locally shared texture space.
+ */
+struct radeon_tex_obj {
+ driTextureObject base;
+
+ GLuint bufAddr; /* Offset to start of locally
+ shared texture block */
+
+ GLuint dirty_state; /* Flags (1 per texunit) for
+ whether or not this texobj
+ has dirty hardware state
+ (pp_*) that needs to be
+ brought into the
+ texunit. */
+
+ drmRadeonTexImage image[6][RADEON_MAX_TEXTURE_LEVELS];
+ /* Six, for the cube faces */
+
+ GLuint pp_txfilter; /* hardware register values */
+ GLuint pp_txformat;
+ GLuint pp_txoffset; /* Image location in texmem.
+ All cube faces follow. */
+ GLuint pp_txsize; /* npot only */
+ GLuint pp_txpitch; /* npot only */
+ GLuint pp_border_color;
+ GLuint pp_cubic_faces; /* cube face 1,2,3,4 log2 sizes */
+
+ GLboolean border_fallback;
+};
+
+
+struct radeon_texture_env_state {
+ radeonTexObjPtr texobj;
+ GLenum format;
+ GLenum envMode;
+};
+
+struct radeon_texture_state {
+ struct radeon_texture_env_state unit[RADEON_MAX_TEXTURE_UNITS];
+};
+
+
+struct radeon_state_atom {
+ struct radeon_state_atom *next, *prev;
+ const char *name; /* for debug */
+ int cmd_size; /* size in bytes */
+ GLuint is_tcl;
+ int *cmd; /* one or more cmd's */
+ int *lastcmd; /* one or more cmd's */
+ GLboolean (*check)( GLcontext * ); /* is this state active? */
+};
+
+
+
+/* Trying to keep these relatively short as the variables are becoming
+ * extravagently long. Drop the driver name prefix off the front of
+ * everything - I think we know which driver we're in by now, and keep the
+ * prefix to 3 letters unless absolutely impossible.
+ */
+
+#define CTX_CMD_0 0
+#define CTX_PP_MISC 1
+#define CTX_PP_FOG_COLOR 2
+#define CTX_RE_SOLID_COLOR 3
+#define CTX_RB3D_BLENDCNTL 4
+#define CTX_RB3D_DEPTHOFFSET 5
+#define CTX_RB3D_DEPTHPITCH 6
+#define CTX_RB3D_ZSTENCILCNTL 7
+#define CTX_CMD_1 8
+#define CTX_PP_CNTL 9
+#define CTX_RB3D_CNTL 10
+#define CTX_RB3D_COLOROFFSET 11
+#define CTX_CMD_2 12
+#define CTX_RB3D_COLORPITCH 13
+#define CTX_STATE_SIZE 14
+
+#define SET_CMD_0 0
+#define SET_SE_CNTL 1
+#define SET_SE_COORDFMT 2
+#define SET_CMD_1 3
+#define SET_SE_CNTL_STATUS 4
+#define SET_STATE_SIZE 5
+
+#define LIN_CMD_0 0
+#define LIN_RE_LINE_PATTERN 1
+#define LIN_RE_LINE_STATE 2
+#define LIN_CMD_1 3
+#define LIN_SE_LINE_WIDTH 4
+#define LIN_STATE_SIZE 5
+
+#define MSK_CMD_0 0
+#define MSK_RB3D_STENCILREFMASK 1
+#define MSK_RB3D_ROPCNTL 2
+#define MSK_RB3D_PLANEMASK 3
+#define MSK_STATE_SIZE 4
+
+#define VPT_CMD_0 0
+#define VPT_SE_VPORT_XSCALE 1
+#define VPT_SE_VPORT_XOFFSET 2
+#define VPT_SE_VPORT_YSCALE 3
+#define VPT_SE_VPORT_YOFFSET 4
+#define VPT_SE_VPORT_ZSCALE 5
+#define VPT_SE_VPORT_ZOFFSET 6
+#define VPT_STATE_SIZE 7
+
+#define MSC_CMD_0 0
+#define MSC_RE_MISC 1
+#define MSC_STATE_SIZE 2
+
+#define TEX_CMD_0 0
+#define TEX_PP_TXFILTER 1
+#define TEX_PP_TXFORMAT 2
+#define TEX_PP_TXOFFSET 3
+#define TEX_PP_TXCBLEND 4
+#define TEX_PP_TXABLEND 5
+#define TEX_PP_TFACTOR 6
+#define TEX_CMD_1 7
+#define TEX_PP_BORDER_COLOR 8
+#define TEX_STATE_SIZE 9
+
+#define TXR_CMD_0 0 /* rectangle textures */
+#define TXR_PP_TEX_SIZE 1 /* 0x1d04, 0x1d0c for NPOT! */
+#define TXR_PP_TEX_PITCH 2 /* 0x1d08, 0x1d10 for NPOT! */
+#define TXR_STATE_SIZE 3
+
+#define ZBS_CMD_0 0
+#define ZBS_SE_ZBIAS_FACTOR 1
+#define ZBS_SE_ZBIAS_CONSTANT 2
+#define ZBS_STATE_SIZE 3
+
+#define TCL_CMD_0 0
+#define TCL_OUTPUT_VTXFMT 1
+#define TCL_OUTPUT_VTXSEL 2
+#define TCL_MATRIX_SELECT_0 3
+#define TCL_MATRIX_SELECT_1 4
+#define TCL_UCP_VERT_BLEND_CTL 5
+#define TCL_TEXTURE_PROC_CTL 6
+#define TCL_LIGHT_MODEL_CTL 7
+#define TCL_PER_LIGHT_CTL_0 8
+#define TCL_PER_LIGHT_CTL_1 9
+#define TCL_PER_LIGHT_CTL_2 10
+#define TCL_PER_LIGHT_CTL_3 11
+#define TCL_STATE_SIZE 12
+
+#define MTL_CMD_0 0
+#define MTL_EMMISSIVE_RED 1
+#define MTL_EMMISSIVE_GREEN 2
+#define MTL_EMMISSIVE_BLUE 3
+#define MTL_EMMISSIVE_ALPHA 4
+#define MTL_AMBIENT_RED 5
+#define MTL_AMBIENT_GREEN 6
+#define MTL_AMBIENT_BLUE 7
+#define MTL_AMBIENT_ALPHA 8
+#define MTL_DIFFUSE_RED 9
+#define MTL_DIFFUSE_GREEN 10
+#define MTL_DIFFUSE_BLUE 11
+#define MTL_DIFFUSE_ALPHA 12
+#define MTL_SPECULAR_RED 13
+#define MTL_SPECULAR_GREEN 14
+#define MTL_SPECULAR_BLUE 15
+#define MTL_SPECULAR_ALPHA 16
+#define MTL_SHININESS 17
+#define MTL_STATE_SIZE 18
+
+#define VTX_CMD_0 0
+#define VTX_SE_COORD_FMT 1
+#define VTX_STATE_SIZE 2
+
+#define MAT_CMD_0 0
+#define MAT_ELT_0 1
+#define MAT_STATE_SIZE 17
+
+#define GRD_CMD_0 0
+#define GRD_VERT_GUARD_CLIP_ADJ 1
+#define GRD_VERT_GUARD_DISCARD_ADJ 2
+#define GRD_HORZ_GUARD_CLIP_ADJ 3
+#define GRD_HORZ_GUARD_DISCARD_ADJ 4
+#define GRD_STATE_SIZE 5
+
+/* position changes frequently when lighting in modelpos - separate
+ * out to new state item?
+ */
+#define LIT_CMD_0 0
+#define LIT_AMBIENT_RED 1
+#define LIT_AMBIENT_GREEN 2
+#define LIT_AMBIENT_BLUE 3
+#define LIT_AMBIENT_ALPHA 4
+#define LIT_DIFFUSE_RED 5
+#define LIT_DIFFUSE_GREEN 6
+#define LIT_DIFFUSE_BLUE 7
+#define LIT_DIFFUSE_ALPHA 8
+#define LIT_SPECULAR_RED 9
+#define LIT_SPECULAR_GREEN 10
+#define LIT_SPECULAR_BLUE 11
+#define LIT_SPECULAR_ALPHA 12
+#define LIT_POSITION_X 13
+#define LIT_POSITION_Y 14
+#define LIT_POSITION_Z 15
+#define LIT_POSITION_W 16
+#define LIT_DIRECTION_X 17
+#define LIT_DIRECTION_Y 18
+#define LIT_DIRECTION_Z 19
+#define LIT_DIRECTION_W 20
+#define LIT_ATTEN_CONST 21
+#define LIT_ATTEN_LINEAR 22
+#define LIT_ATTEN_QUADRATIC 23
+#define LIT_ATTEN_XXX 24
+#define LIT_CMD_1 25
+#define LIT_SPOT_DCD 26
+#define LIT_SPOT_EXPONENT 27
+#define LIT_SPOT_CUTOFF 28
+#define LIT_SPECULAR_THRESH 29
+#define LIT_RANGE_CUTOFF 30 /* ? */
+#define LIT_RANGE_ATTEN 31 /* ? */
+#define LIT_STATE_SIZE 32
+
+/* Fog
+ */
+#define FOG_CMD_0 0
+#define FOG_R 1
+#define FOG_C 2
+#define FOG_D 3
+#define FOG_PAD 4
+#define FOG_STATE_SIZE 5
+
+/* UCP
+ */
+#define UCP_CMD_0 0
+#define UCP_X 1
+#define UCP_Y 2
+#define UCP_Z 3
+#define UCP_W 4
+#define UCP_STATE_SIZE 5
+
+/* GLT - Global ambient
+ */
+#define GLT_CMD_0 0
+#define GLT_RED 1
+#define GLT_GREEN 2
+#define GLT_BLUE 3
+#define GLT_ALPHA 4
+#define GLT_STATE_SIZE 5
+
+/* EYE
+ */
+#define EYE_CMD_0 0
+#define EYE_X 1
+#define EYE_Y 2
+#define EYE_Z 3
+#define EYE_RESCALE_FACTOR 4
+#define EYE_STATE_SIZE 5
+
+#define SHN_CMD_0 0
+#define SHN_SHININESS 1
+#define SHN_STATE_SIZE 2
+
+
+
+
+
+struct radeon_hw_state {
+ /* All state should be on one of these lists:
+ */
+ struct radeon_state_atom dirty; /* dirty list head placeholder */
+ struct radeon_state_atom clean; /* clean list head placeholder */
+
+ /* Hardware state, stored as cmdbuf commands:
+ * -- Need to doublebuffer for
+ * - reviving state after loss of context
+ * - eliding noop statechange loops? (except line stipple count)
+ */
+ struct radeon_state_atom ctx;
+ struct radeon_state_atom set;
+ struct radeon_state_atom lin;
+ struct radeon_state_atom msk;
+ struct radeon_state_atom vpt;
+ struct radeon_state_atom tcl;
+ struct radeon_state_atom msc;
+ struct radeon_state_atom tex[2];
+ struct radeon_state_atom zbs;
+ struct radeon_state_atom mtl;
+ struct radeon_state_atom mat[5];
+ struct radeon_state_atom lit[8]; /* includes vec, scl commands */
+ struct radeon_state_atom ucp[6];
+ struct radeon_state_atom eye; /* eye pos */
+ struct radeon_state_atom grd; /* guard band clipping */
+ struct radeon_state_atom fog;
+ struct radeon_state_atom glt;
+ struct radeon_state_atom txr[2]; /* for NPOT */
+};
+
+struct radeon_state {
+ /* Derived state for internal purposes:
+ */
+ struct radeon_colorbuffer_state color;
+ struct radeon_depthbuffer_state depth;
+ struct radeon_pixel_state pixel;
+ struct radeon_scissor_state scissor;
+ struct radeon_stencilbuffer_state stencil;
+ struct radeon_stipple_state stipple;
+ struct radeon_texture_state texture;
+};
+
+
+/* Need refcounting on dma buffers:
+ */
+struct radeon_dma_buffer {
+ int refcount; /* the number of retained regions in buf */
+ drmBufPtr buf;
+};
+
+#define GET_START(rvb) (rmesa->radeonScreen->agp_buffer_offset + \
+ (rvb)->address - rmesa->dma.buf0_address + \
+ (rvb)->start)
+
+/* A retained region, eg vertices for indexed vertices.
+ */
+struct radeon_dma_region {
+ struct radeon_dma_buffer *buf;
+ char *address; /* == buf->address */
+ int start, end, ptr; /* offsets from start of buf */
+ int aos_start;
+ int aos_stride;
+ int aos_size;
+};
+
+
+struct radeon_dma {
+ /* Active dma region. Allocations for vertices and retained
+ * regions come from here. Also used for emitting random vertices,
+ * these may be flushed by calling flush_current();
+ */
+ struct radeon_dma_region current;
+
+ void (*flush)( radeonContextPtr );
+
+ char *buf0_address; /* start of buf[0], for index calcs */
+ GLuint nr_released_bufs; /* flush after so many buffers released */
+};
+
+struct radeon_dri_mirror {
+ __DRIcontextPrivate *context; /* DRI context */
+ __DRIscreenPrivate *screen; /* DRI screen */
+ __DRIdrawablePrivate *drawable; /* DRI drawable bound to this ctx */
+
+ drmContext hwContext;
+ drmLock *hwLock;
+ int fd;
+ int drmMinor;
+};
+
+
+#define RADEON_CMD_BUF_SZ (8*1024)
+
+struct radeon_store {
+ GLuint statenr;
+ GLuint primnr;
+ char cmd_buf[RADEON_CMD_BUF_SZ];
+ int cmd_used;
+ int elts_start;
+};
+
+
+/* radeon_tcl.c
+ */
+struct radeon_tcl_info {
+ GLuint vertex_format;
+ GLint last_offset;
+ GLuint hw_primitive;
+
+ struct radeon_dma_region *aos_components[8];
+ GLuint nr_aos_components;
+
+ GLuint *Elts;
+
+ struct radeon_dma_region indexed_verts;
+ struct radeon_dma_region obj;
+ struct radeon_dma_region rgba;
+ struct radeon_dma_region spec;
+ struct radeon_dma_region fog;
+ struct radeon_dma_region tex[RADEON_MAX_TEXTURE_UNITS];
+ struct radeon_dma_region norm;
+};
+
+
+/* radeon_swtcl.c
+ */
+struct radeon_swtcl_info {
+ GLuint SetupIndex;
+ GLuint SetupNewInputs;
+ GLuint RenderIndex;
+ GLuint vertex_size;
+ GLuint vertex_stride_shift;
+ GLuint vertex_format;
+ GLubyte *verts;
+
+ /* Fallback rasterization functions
+ */
+ radeon_point_func draw_point;
+ radeon_line_func draw_line;
+ radeon_tri_func draw_tri;
+
+ GLuint hw_primitive;
+ GLenum render_primitive;
+ GLuint numverts;
+
+ struct radeon_dma_region indexed_verts;
+};
+
+
+struct radeon_ioctl {
+ GLuint vertex_offset;
+ GLuint vertex_size;
+};
+
+
+
+#define RADEON_MAX_PRIMS 64
+
+
+/* Want to keep a cache of these around. Each is parameterized by
+ * only a single value which has only a small range. Only expect a
+ * few, so just rescan the list each time?
+ */
+struct dynfn {
+ struct dynfn *next, *prev;
+ int key;
+ char *code;
+};
+
+struct dfn_lists {
+ struct dynfn Vertex2f;
+ struct dynfn Vertex2fv;
+ struct dynfn Vertex3f;
+ struct dynfn Vertex3fv;
+ struct dynfn Color4ub;
+ struct dynfn Color4ubv;
+ struct dynfn Color3ub;
+ struct dynfn Color3ubv;
+ struct dynfn Color4f;
+ struct dynfn Color4fv;
+ struct dynfn Color3f;
+ struct dynfn Color3fv;
+ struct dynfn SecondaryColor3ubEXT;
+ struct dynfn SecondaryColor3ubvEXT;
+ struct dynfn SecondaryColor3fEXT;
+ struct dynfn SecondaryColor3fvEXT;
+ struct dynfn Normal3f;
+ struct dynfn Normal3fv;
+ struct dynfn TexCoord2f;
+ struct dynfn TexCoord2fv;
+ struct dynfn TexCoord1f;
+ struct dynfn TexCoord1fv;
+ struct dynfn MultiTexCoord2fARB;
+ struct dynfn MultiTexCoord2fvARB;
+ struct dynfn MultiTexCoord1fARB;
+ struct dynfn MultiTexCoord1fvARB;
+};
+
+struct dfn_generators {
+ struct dynfn *(*Vertex2f)( GLcontext *, int );
+ struct dynfn *(*Vertex2fv)( GLcontext *, int );
+ struct dynfn *(*Vertex3f)( GLcontext *, int );
+ struct dynfn *(*Vertex3fv)( GLcontext *, int );
+ struct dynfn *(*Color4ub)( GLcontext *, int );
+ struct dynfn *(*Color4ubv)( GLcontext *, int );
+ struct dynfn *(*Color3ub)( GLcontext *, int );
+ struct dynfn *(*Color3ubv)( GLcontext *, int );
+ struct dynfn *(*Color4f)( GLcontext *, int );
+ struct dynfn *(*Color4fv)( GLcontext *, int );
+ struct dynfn *(*Color3f)( GLcontext *, int );
+ struct dynfn *(*Color3fv)( GLcontext *, int );
+ struct dynfn *(*SecondaryColor3ubEXT)( GLcontext *, int );
+ struct dynfn *(*SecondaryColor3ubvEXT)( GLcontext *, int );
+ struct dynfn *(*SecondaryColor3fEXT)( GLcontext *, int );
+ struct dynfn *(*SecondaryColor3fvEXT)( GLcontext *, int );
+ struct dynfn *(*Normal3f)( GLcontext *, int );
+ struct dynfn *(*Normal3fv)( GLcontext *, int );
+ struct dynfn *(*TexCoord2f)( GLcontext *, int );
+ struct dynfn *(*TexCoord2fv)( GLcontext *, int );
+ struct dynfn *(*TexCoord1f)( GLcontext *, int );
+ struct dynfn *(*TexCoord1fv)( GLcontext *, int );
+ struct dynfn *(*MultiTexCoord2fARB)( GLcontext *, int );
+ struct dynfn *(*MultiTexCoord2fvARB)( GLcontext *, int );
+ struct dynfn *(*MultiTexCoord1fARB)( GLcontext *, int );
+ struct dynfn *(*MultiTexCoord1fvARB)( GLcontext *, int );
+};
+
+
+
+struct radeon_prim {
+ GLuint start;
+ GLuint end;
+ GLuint prim;
+};
+
+struct radeon_vbinfo {
+ GLint counter, initial_counter;
+ GLint *dmaptr;
+ void (*notify)( void );
+ GLint vertex_size;
+
+ /* A maximum total of 15 elements per vertex: 3 floats for position, 3
+ * floats for normal, 4 floats for color, 4 bytes for secondary color,
+ * 2 floats for each texture unit (4 floats total).
+ *
+ * As soon as the 3rd TMU is supported or cube maps (or 3D textures) are
+ * supported, this value will grow.
+ *
+ * The position data is never actually stored here, so 3 elements could be
+ * trimmed out of the buffer.
+ */
+ union { float f; int i; radeon_color_t color; } vertex[15];
+
+ GLfloat *normalptr;
+ GLfloat *floatcolorptr;
+ radeon_color_t *colorptr;
+ GLfloat *floatspecptr;
+ radeon_color_t *specptr;
+ GLfloat *texcoordptr[2];
+
+ GLenum *prim; /* &ctx->Driver.CurrentExecPrimitive */
+ GLuint primflags;
+ GLboolean enabled; /* *_NO_VTXFMT / *_NO_TCL env vars */
+ GLboolean installed;
+ GLboolean fell_back;
+ GLboolean recheck;
+ GLint nrverts;
+ GLuint vertex_format;
+
+ GLuint installed_vertex_format;
+ GLuint installed_color_3f_sz;
+
+ struct radeon_prim primlist[RADEON_MAX_PRIMS];
+ int nrprims;
+
+ struct dfn_lists dfn_cache;
+ struct dfn_generators codegen;
+ GLvertexformat vtxfmt;
+};
+
+
+
+
+struct radeon_context {
+ GLcontext *glCtx; /* Mesa context */
+
+ /* Driver and hardware state management
+ */
+ struct radeon_hw_state hw;
+ struct radeon_state state;
+
+ /* Texture object bookkeeping
+ */
+ unsigned nr_heaps;
+ driTexHeap * texture_heaps[ RADEON_NR_TEX_HEAPS ];
+ driTextureObject swapped;
+
+
+ /* Rasterization and vertex state:
+ */
+ GLuint TclFallback;
+ GLuint Fallback;
+ GLuint NewGLState;
+
+
+ /* Temporaries for translating away float colors:
+ */
+ struct gl_client_array UbyteColor;
+ struct gl_client_array UbyteSecondaryColor;
+
+ /* Vertex buffers
+ */
+ struct radeon_ioctl ioctl;
+ struct radeon_dma dma;
+ struct radeon_store store;
+
+ /* Page flipping
+ */
+ GLuint doPageFlip;
+
+ /* Busy waiting
+ */
+ GLuint do_usleeps;
+ GLuint do_irqs;
+ GLuint irqsEmitted;
+ drmRadeonIrqWait iw;
+
+ /* Drawable, cliprect and scissor information
+ */
+ GLuint numClipRects; /* Cliprects for the draw buffer */
+ XF86DRIClipRectPtr pClipRects;
+ unsigned int lastStamp;
+ GLboolean lost_context;
+ radeonScreenPtr radeonScreen; /* Screen private DRI data */
+ RADEONSAREAPrivPtr sarea; /* Private SAREA data */
+
+ /* TCL stuff
+ */
+ GLmatrix TexGenMatrix[RADEON_MAX_TEXTURE_UNITS];
+ GLboolean recheck_texgen[RADEON_MAX_TEXTURE_UNITS];
+ GLboolean TexGenNeedNormals[RADEON_MAX_TEXTURE_UNITS];
+ GLuint TexMatEnabled;
+ GLuint TexGenEnabled;
+ GLmatrix tmpmat;
+ GLuint last_ReallyEnabled;
+
+ /* VBI
+ */
+ GLuint vbl_seq;
+ GLuint vblank_flags;
+
+ uint64_t swap_ust;
+ uint64_t swap_missed_ust;
+
+ GLuint swap_count;
+ GLuint swap_missed_count;
+
+ PFNGLXGETUSTPROC get_ust;
+
+ /* radeon_tcl.c
+ */
+ struct radeon_tcl_info tcl;
+
+ /* radeon_swtcl.c
+ */
+ struct radeon_swtcl_info swtcl;
+
+ /* radeon_vtxfmt.c
+ */
+ struct radeon_vbinfo vb;
+
+ /* Mirrors of some DRI state
+ */
+ struct radeon_dri_mirror dri;
+
+
+ /* Performance counters
+ */
+ GLuint boxes; /* Draw performance boxes */
+ GLuint hardwareWentIdle;
+ GLuint c_clears;
+ GLuint c_drawWaits;
+ GLuint c_textureSwaps;
+ GLuint c_textureBytes;
+ GLuint c_vertexBuffers;
+};
+
+#define RADEON_CONTEXT(ctx) ((radeonContextPtr)(ctx->DriverCtx))
+
+
+static __inline GLuint radeonPackColor( 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;
+ }
+}
+
+#define RADEON_OLD_PACKETS 1
+
+
+extern void radeonDestroyContext( __DRIcontextPrivate *driContextPriv );
+extern GLboolean radeonCreateContext(const __GLcontextModes *glVisual,
+ __DRIcontextPrivate *driContextPriv,
+ void *sharedContextPrivate);
+extern void radeonSwapBuffers( __DRIdrawablePrivate *dPriv );
+extern GLboolean radeonMakeCurrent( __DRIcontextPrivate *driContextPriv,
+ __DRIdrawablePrivate *driDrawPriv,
+ __DRIdrawablePrivate *driReadPriv );
+extern GLboolean radeonUnbindContext( __DRIcontextPrivate *driContextPriv );
+
+/* ================================================================
+ * Debugging:
+ */
+#define DO_DEBUG 1
+
+#if DO_DEBUG
+extern int RADEON_DEBUG;
+#else
+#define RADEON_DEBUG 0
+#endif
+
+#define DEBUG_TEXTURE 0x001
+#define DEBUG_STATE 0x002
+#define DEBUG_IOCTL 0x004
+#define DEBUG_PRIMS 0x008
+#define DEBUG_VERTS 0x010
+#define DEBUG_FALLBACKS 0x020
+#define DEBUG_VFMT 0x040
+#define DEBUG_CODEGEN 0x080
+#define DEBUG_VERBOSE 0x100
+#define DEBUG_DRI 0x200
+#define DEBUG_DMA 0x400
+#define DEBUG_SANITY 0x800
+
+#endif
+#endif /* __RADEON_CONTEXT_H__ */
diff --git a/src/mesa/drivers/dri/radeon/radeon_ioctl.c b/src/mesa/drivers/dri/radeon/radeon_ioctl.c
new file mode 100644
index 0000000000..a388720aba
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_ioctl.c
@@ -0,0 +1,1191 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_ioctl.c,v 1.11 2003/01/29 22:04:59 dawes 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 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 THE COPYRIGHT OWNER(S) 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:
+ * Kevin E. Martin <martin@valinux.com>
+ * Gareth Hughes <gareth@valinux.com>
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+#include <sched.h>
+#include <errno.h>
+
+#include "glheader.h"
+#include "imports.h"
+#include "simple_list.h"
+#include "swrast/swrast.h"
+
+#include "radeon_context.h"
+#include "radeon_state.h"
+#include "radeon_ioctl.h"
+#include "radeon_tcl.h"
+#include "radeon_sanity.h"
+
+#include "radeon_macros.h" /* for INREG() */
+
+#include "vblank.h"
+
+#define RADEON_TIMEOUT 512
+#define RADEON_IDLE_RETRY 16
+
+
+static void radeonWaitForIdle( radeonContextPtr rmesa );
+
+/* =============================================================
+ * Kernel command buffer handling
+ */
+
+static void print_state_atom( struct radeon_state_atom *state )
+{
+ int i;
+
+ fprintf(stderr, "emit %s/%d\n", state->name, state->cmd_size);
+
+ if (RADEON_DEBUG & DEBUG_VERBOSE)
+ for (i = 0 ; i < state->cmd_size ; i++)
+ fprintf(stderr, "\t%s[%d]: %x\n", state->name, i, state->cmd[i]);
+
+}
+
+static void radeon_emit_state_list( radeonContextPtr rmesa,
+ struct radeon_state_atom *list )
+{
+ struct radeon_state_atom *state, *tmp;
+ char *dest;
+
+ /* From Felix Kuhling: similar to some other lockups, glaxium will
+ * lock with what we believe to be a normal command stream, but
+ * sprinkling some magic waits arounds allows it to run
+ * uninterrupted. This has a slight effect on q3 framerates, but
+ * it might now be possible to remove the zbs hack, below.
+ *
+ * Felix reports that this can be narrowed down to just
+ * tcl,tex0,tex1 state, but that's pretty much every statechange,
+ * so let's just put the wait in always (unless Felix wants to
+ * narrow it down further...)
+ */
+ if (1) {
+ drmRadeonCmdHeader *cmd;
+ cmd = (drmRadeonCmdHeader *)radeonAllocCmdBuf( rmesa, sizeof(*cmd),
+ __FUNCTION__ );
+ cmd->wait.cmd_type = RADEON_CMD_WAIT;
+ cmd->wait.flags = RADEON_WAIT_3D;
+ }
+
+ foreach_s( state, tmp, list ) {
+ if (state->check( rmesa->glCtx )) {
+ dest = radeonAllocCmdBuf( rmesa, state->cmd_size * 4, __FUNCTION__);
+ memcpy( dest, state->cmd, state->cmd_size * 4);
+ move_to_head( &(rmesa->hw.clean), state );
+ if (RADEON_DEBUG & DEBUG_STATE)
+ print_state_atom( state );
+ }
+ else if (RADEON_DEBUG & DEBUG_STATE)
+ fprintf(stderr, "skip state %s\n", state->name);
+ }
+}
+
+
+void radeonEmitState( radeonContextPtr rmesa )
+{
+ struct radeon_state_atom *state, *tmp;
+
+ if (RADEON_DEBUG & (DEBUG_STATE|DEBUG_PRIMS))
+ fprintf(stderr, "%s\n", __FUNCTION__);
+
+ /* Somewhat overkill:
+ */
+ if (rmesa->lost_context) {
+ if (RADEON_DEBUG & (DEBUG_STATE|DEBUG_PRIMS|DEBUG_IOCTL))
+ fprintf(stderr, "%s - lost context\n", __FUNCTION__);
+
+ foreach_s( state, tmp, &(rmesa->hw.clean) )
+ move_to_tail(&(rmesa->hw.dirty), state );
+
+ rmesa->lost_context = 0;
+ }
+ else if (1) {
+ /* This is a darstardly kludge to work around a lockup that I
+ * haven't otherwise figured out.
+ */
+ move_to_tail(&(rmesa->hw.dirty), &(rmesa->hw.zbs) );
+ }
+
+ if (!(rmesa->radeonScreen->chipset & RADEON_CHIPSET_TCL)) {
+ foreach_s( state, tmp, &(rmesa->hw.dirty) ) {
+ if (state->is_tcl) {
+ move_to_head( &(rmesa->hw.clean), state );
+ }
+ }
+ }
+
+ radeon_emit_state_list( rmesa, &rmesa->hw.dirty );
+}
+
+
+
+/* Fire a section of the retained (indexed_verts) buffer as a regular
+ * primtive.
+ */
+extern void radeonEmitVbufPrim( radeonContextPtr rmesa,
+ GLuint vertex_format,
+ GLuint primitive,
+ GLuint vertex_nr )
+{
+ drmRadeonCmdHeader *cmd;
+
+
+ assert(rmesa->dri.drmMinor >= 3);
+ assert(!(primitive & RADEON_CP_VC_CNTL_PRIM_WALK_IND));
+
+ radeonEmitState( rmesa );
+
+ if (RADEON_DEBUG & DEBUG_IOCTL)
+ fprintf(stderr, "%s cmd_used/4: %d\n", __FUNCTION__,
+ rmesa->store.cmd_used/4);
+
+#if RADEON_OLD_PACKETS
+ cmd = (drmRadeonCmdHeader *)radeonAllocCmdBuf( rmesa, 6 * sizeof(*cmd),
+ __FUNCTION__ );
+ cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP;
+ cmd[1].i = RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM | (3 << 16);
+ cmd[2].i = rmesa->ioctl.vertex_offset;
+ cmd[3].i = vertex_nr;
+ cmd[4].i = vertex_format;
+ cmd[5].i = (primitive |
+ RADEON_CP_VC_CNTL_PRIM_WALK_LIST |
+ RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA |
+ RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE |
+ (vertex_nr << RADEON_CP_VC_CNTL_NUM_SHIFT));
+
+ if (RADEON_DEBUG & DEBUG_PRIMS)
+ fprintf(stderr, "%s: header 0x%x offt 0x%x vfmt 0x%x vfcntl %x \n",
+ __FUNCTION__,
+ cmd[1].i, cmd[2].i, cmd[4].i, cmd[5].i);
+#else
+ cmd = (drmRadeonCmdHeader *)radeonAllocCmdBuf( rmesa, 4 * sizeof(*cmd),
+ __FUNCTION__ );
+ cmd[0].i = 0;
+ cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP;
+ cmd[1].i = RADEON_CP_PACKET3_3D_DRAW_VBUF | (1 << 16);
+ cmd[2].i = vertex_format;
+ cmd[3].i = (primitive |
+ RADEON_CP_VC_CNTL_PRIM_WALK_LIST |
+ RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA |
+ RADEON_CP_VC_CNTL_MAOS_ENABLE |
+ RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE |
+ (vertex_nr << RADEON_CP_VC_CNTL_NUM_SHIFT));
+
+
+ if (RADEON_DEBUG & DEBUG_PRIMS)
+ fprintf(stderr, "%s: header 0x%x vfmt 0x%x vfcntl %x \n",
+ __FUNCTION__,
+ cmd[1].i, cmd[2].i, cmd[3].i);
+#endif
+}
+
+
+void radeonFlushElts( radeonContextPtr rmesa )
+{
+ int *cmd = (int *)(rmesa->store.cmd_buf + rmesa->store.elts_start);
+ int dwords;
+#if RADEON_OLD_PACKETS
+ int nr = (rmesa->store.cmd_used - (rmesa->store.elts_start + 24)) / 2;
+#else
+ int nr = (rmesa->store.cmd_used - (rmesa->store.elts_start + 16)) / 2;
+#endif
+
+ if (RADEON_DEBUG & DEBUG_IOCTL)
+ fprintf(stderr, "%s\n", __FUNCTION__);
+
+ assert( rmesa->dma.flush == radeonFlushElts );
+ rmesa->dma.flush = 0;
+
+ /* Cope with odd number of elts:
+ */
+ rmesa->store.cmd_used = (rmesa->store.cmd_used + 2) & ~2;
+ dwords = (rmesa->store.cmd_used - rmesa->store.elts_start) / 4;
+
+#if RADEON_OLD_PACKETS
+ cmd[1] |= (dwords - 3) << 16;
+ cmd[5] |= nr << RADEON_CP_VC_CNTL_NUM_SHIFT;
+#else
+ cmd[1] |= (dwords - 3) << 16;
+ cmd[3] |= nr << RADEON_CP_VC_CNTL_NUM_SHIFT;
+#endif
+}
+
+
+GLushort *radeonAllocEltsOpenEnded( radeonContextPtr rmesa,
+ GLuint vertex_format,
+ GLuint primitive,
+ GLuint min_nr )
+{
+ drmRadeonCmdHeader *cmd;
+ GLushort *retval;
+
+ if (RADEON_DEBUG & DEBUG_IOCTL)
+ fprintf(stderr, "%s %d\n", __FUNCTION__, min_nr);
+
+ assert(rmesa->dri.drmMinor >= 3);
+ assert((primitive & RADEON_CP_VC_CNTL_PRIM_WALK_IND));
+
+ radeonEmitState( rmesa );
+
+#if RADEON_OLD_PACKETS
+ cmd = (drmRadeonCmdHeader *)radeonAllocCmdBuf( rmesa,
+ 24 + min_nr*2,
+ __FUNCTION__ );
+ cmd[0].i = 0;
+ cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP;
+ cmd[1].i = RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM;
+ cmd[2].i = rmesa->ioctl.vertex_offset;
+ cmd[3].i = 0xffff;
+ cmd[4].i = vertex_format;
+ cmd[5].i = (primitive |
+ RADEON_CP_VC_CNTL_PRIM_WALK_IND |
+ RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA |
+ RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE);
+
+ retval = (GLushort *)(cmd+6);
+#else
+ cmd = (drmRadeonCmdHeader *)radeonAllocCmdBuf( rmesa,
+ 16 + min_nr*2,
+ __FUNCTION__ );
+ cmd[0].i = 0;
+ cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP;
+ cmd[1].i = RADEON_CP_PACKET3_3D_DRAW_INDX;
+ cmd[2].i = vertex_format;
+ cmd[3].i = (primitive |
+ RADEON_CP_VC_CNTL_PRIM_WALK_IND |
+ RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA |
+ RADEON_CP_VC_CNTL_MAOS_ENABLE |
+ RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE);
+
+ retval = (GLushort *)(cmd+4);
+#endif
+
+ if (RADEON_DEBUG & DEBUG_PRIMS)
+ fprintf(stderr, "%s: header 0x%x vfmt 0x%x prim %x \n",
+ __FUNCTION__,
+ cmd[1].i, vertex_format, primitive);
+
+ assert(!rmesa->dma.flush);
+ rmesa->glCtx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
+ rmesa->dma.flush = radeonFlushElts;
+
+ rmesa->store.elts_start = ((char *)cmd) - rmesa->store.cmd_buf;
+
+ return retval;
+}
+
+
+
+void radeonEmitVertexAOS( radeonContextPtr rmesa,
+ GLuint vertex_size,
+ GLuint offset )
+{
+#if RADEON_OLD_PACKETS
+ rmesa->ioctl.vertex_size = vertex_size;
+ rmesa->ioctl.vertex_offset = offset;
+#else
+ drmRadeonCmdHeader *cmd;
+ assert(rmesa->dri.drmMinor >= 3);
+
+ if (RADEON_DEBUG & (DEBUG_PRIMS|DEBUG_IOCTL))
+ fprintf(stderr, "%s: vertex_size 0x%x offset 0x%x \n",
+ __FUNCTION__, vertex_size, offset);
+
+ cmd = (drmRadeonCmdHeader *)radeonAllocCmdBuf( rmesa, 5 * sizeof(int),
+ __FUNCTION__ );
+
+ cmd[0].i = 0;
+ cmd[0].header.cmd_type = RADEON_CMD_PACKET3;
+ cmd[1].i = RADEON_CP_PACKET3_3D_LOAD_VBPNTR | (2 << 16);
+ cmd[2].i = 1;
+ cmd[3].i = vertex_size | (vertex_size << 8);
+ cmd[4].i = offset;
+#endif
+}
+
+
+void radeonEmitAOS( radeonContextPtr rmesa,
+ struct radeon_dma_region **component,
+ GLuint nr,
+ GLuint offset )
+{
+#if RADEON_OLD_PACKETS
+ assert( nr == 1 );
+ assert( component[0]->aos_size == component[0]->aos_stride );
+ rmesa->ioctl.vertex_size = component[0]->aos_size;
+ rmesa->ioctl.vertex_offset =
+ (component[0]->aos_start + offset * component[0]->aos_stride * 4);
+#else
+ drmRadeonCmdHeader *cmd;
+ int sz = 3 + (nr/2 * 3) + (nr & 1) * 2;
+ int i;
+ int *tmp;
+
+ if (RADEON_DEBUG & DEBUG_IOCTL)
+ fprintf(stderr, "%s\n", __FUNCTION__);
+
+ assert(rmesa->dri.drmMinor >= 3);
+
+ cmd = (drmRadeonCmdHeader *)radeonAllocCmdBuf( rmesa, sz * sizeof(int),
+ __FUNCTION__ );
+ cmd[0].i = 0;
+ cmd[0].header.cmd_type = RADEON_CMD_PACKET3;
+ cmd[1].i = RADEON_CP_PACKET3_3D_LOAD_VBPNTR | ((sz-3) << 16);
+ cmd[2].i = nr;
+ tmp = &cmd[0].i;
+ cmd += 3;
+
+ for (i = 0 ; i < nr ; i++) {
+ if (i & 1) {
+ cmd[0].i |= ((component[i]->aos_stride << 24) |
+ (component[i]->aos_size << 16));
+ cmd[2].i = (component[i]->aos_start +
+ offset * component[i]->aos_stride * 4);
+ cmd += 3;
+ }
+ else {
+ cmd[0].i = ((component[i]->aos_stride << 8) |
+ (component[i]->aos_size << 0));
+ cmd[1].i = (component[i]->aos_start +
+ offset * component[i]->aos_stride * 4);
+ }
+ }
+
+ if (RADEON_DEBUG & DEBUG_VERTS) {
+ fprintf(stderr, "%s:\n", __FUNCTION__);
+ for (i = 0 ; i < sz ; i++)
+ fprintf(stderr, " %d: %x\n", i, tmp[i]);
+ }
+#endif
+}
+
+/* using already shifted color_fmt! */
+void radeonEmitBlit( radeonContextPtr rmesa, /* FIXME: which drmMinor is required? */
+ GLuint color_fmt,
+ GLuint src_pitch,
+ GLuint src_offset,
+ GLuint dst_pitch,
+ GLuint dst_offset,
+ GLint srcx, GLint srcy,
+ GLint dstx, GLint dsty,
+ GLuint w, GLuint h )
+{
+ drmRadeonCmdHeader *cmd;
+
+ if (RADEON_DEBUG & DEBUG_IOCTL)
+ fprintf(stderr, "%s src %x/%x %d,%d dst: %x/%x %d,%d sz: %dx%d\n",
+ __FUNCTION__,
+ src_pitch, src_offset, srcx, srcy,
+ dst_pitch, dst_offset, dstx, dsty,
+ w, h);
+
+ assert( (src_pitch & 63) == 0 );
+ assert( (dst_pitch & 63) == 0 );
+ assert( (src_offset & 1023) == 0 );
+ assert( (dst_offset & 1023) == 0 );
+ assert( w < (1<<16) );
+ assert( h < (1<<16) );
+
+ cmd = (drmRadeonCmdHeader *)radeonAllocCmdBuf( rmesa, 8 * sizeof(int),
+ __FUNCTION__ );
+
+
+ cmd[0].i = 0;
+ cmd[0].header.cmd_type = RADEON_CMD_PACKET3;
+ cmd[1].i = RADEON_CP_PACKET3_CNTL_BITBLT_MULTI | (5 << 16);
+ cmd[2].i = (RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
+ RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+ RADEON_GMC_BRUSH_NONE |
+ color_fmt |
+ RADEON_GMC_SRC_DATATYPE_COLOR |
+ RADEON_ROP3_S |
+ RADEON_DP_SRC_SOURCE_MEMORY |
+ RADEON_GMC_CLR_CMP_CNTL_DIS |
+ RADEON_GMC_WR_MSK_DIS );
+
+ cmd[3].i = ((src_pitch/64)<<22) | (src_offset >> 10);
+ cmd[4].i = ((dst_pitch/64)<<22) | (dst_offset >> 10);
+ cmd[5].i = (srcx << 16) | srcy;
+ cmd[6].i = (dstx << 16) | dsty; /* dst */
+ cmd[7].i = (w << 16) | h;
+}
+
+
+void radeonEmitWait( radeonContextPtr rmesa, GLuint flags )
+{
+ if (rmesa->dri.drmMinor >= 6) {
+ drmRadeonCmdHeader *cmd;
+
+ assert( !(flags & ~(RADEON_WAIT_2D|RADEON_WAIT_3D)) );
+
+ cmd = (drmRadeonCmdHeader *)radeonAllocCmdBuf( rmesa, 1 * sizeof(int),
+ __FUNCTION__ );
+ cmd[0].i = 0;
+ cmd[0].wait.cmd_type = RADEON_CMD_WAIT;
+ cmd[0].wait.flags = flags;
+ }
+}
+
+
+static int radeonFlushCmdBufLocked( radeonContextPtr rmesa,
+ const char * caller )
+{
+ int ret, i;
+ drmRadeonCmdBuffer cmd;
+
+ if (RADEON_DEBUG & DEBUG_IOCTL) {
+ fprintf(stderr, "%s from %s\n", __FUNCTION__, caller);
+
+ if (RADEON_DEBUG & DEBUG_VERBOSE)
+ for (i = 0 ; i < rmesa->store.cmd_used ; i += 4 )
+ fprintf(stderr, "%d: %x\n", i/4,
+ *(int *)(&rmesa->store.cmd_buf[i]));
+ }
+
+ if (RADEON_DEBUG & DEBUG_DMA)
+ fprintf(stderr, "%s: Releasing %d buffers\n", __FUNCTION__,
+ rmesa->dma.nr_released_bufs);
+
+
+ if (RADEON_DEBUG & DEBUG_SANITY) {
+ if (rmesa->state.scissor.enabled)
+ ret = radeonSanityCmdBuffer( rmesa,
+ rmesa->state.scissor.numClipRects,
+ rmesa->state.scissor.pClipRects);
+ else
+ ret = radeonSanityCmdBuffer( rmesa,
+ rmesa->numClipRects,
+ rmesa->pClipRects);
+ if (ret) {
+ fprintf(stderr, "drmSanityCommandWrite: %d\n", ret);
+ goto out;
+ }
+ }
+
+
+ cmd.bufsz = rmesa->store.cmd_used;
+ cmd.buf = rmesa->store.cmd_buf;
+
+ if (rmesa->state.scissor.enabled) {
+ cmd.nbox = rmesa->state.scissor.numClipRects;
+ cmd.boxes = (drmClipRect *)rmesa->state.scissor.pClipRects;
+ } else {
+ cmd.nbox = rmesa->numClipRects;
+ cmd.boxes = (drmClipRect *)rmesa->pClipRects;
+ }
+
+ ret = drmCommandWrite( rmesa->dri.fd,
+ DRM_RADEON_CMDBUF,
+ &cmd, sizeof(cmd) );
+
+ if (ret)
+ fprintf(stderr, "drmCommandWrite: %d\n", ret);
+
+ out:
+ rmesa->store.primnr = 0;
+ rmesa->store.statenr = 0;
+ rmesa->store.cmd_used = 0;
+ rmesa->dma.nr_released_bufs = 0;
+ rmesa->lost_context = 1;
+ return ret;
+}
+
+
+/* Note: does not emit any commands to avoid recursion on
+ * radeonAllocCmdBuf.
+ */
+void radeonFlushCmdBuf( radeonContextPtr rmesa, const char *caller )
+{
+ int ret;
+
+
+ assert (rmesa->dri.drmMinor >= 3);
+
+ LOCK_HARDWARE( rmesa );
+
+ ret = radeonFlushCmdBufLocked( rmesa, caller );
+
+ UNLOCK_HARDWARE( rmesa );
+
+ if (ret) {
+ fprintf(stderr, "drmRadeonCmdBuffer: %d (exiting)\n", ret);
+ exit(ret);
+ }
+}
+
+/* =============================================================
+ * Hardware vertex buffer handling
+ */
+
+
+void radeonRefillCurrentDmaRegion( radeonContextPtr rmesa )
+{
+ struct radeon_dma_buffer *dmabuf;
+ int fd = rmesa->dri.fd;
+ int index = 0;
+ int size = 0;
+ drmDMAReq dma;
+ int ret;
+
+ if (RADEON_DEBUG & (DEBUG_IOCTL|DEBUG_DMA))
+ fprintf(stderr, "%s\n", __FUNCTION__);
+
+ if (rmesa->dma.flush) {
+ rmesa->dma.flush( rmesa );
+ }
+
+ if (rmesa->dma.current.buf)
+ radeonReleaseDmaRegion( rmesa, &rmesa->dma.current, __FUNCTION__ );
+
+ if (rmesa->dma.nr_released_bufs > 4)
+ radeonFlushCmdBuf( rmesa, __FUNCTION__ );
+
+ dma.context = rmesa->dri.hwContext;
+ dma.send_count = 0;
+ dma.send_list = NULL;
+ dma.send_sizes = NULL;
+ dma.flags = 0;
+ dma.request_count = 1;
+ dma.request_size = RADEON_BUFFER_SIZE;
+ dma.request_list = &index;
+ dma.request_sizes = &size;
+ dma.granted_count = 0;
+
+ LOCK_HARDWARE(rmesa); /* no need to validate */
+
+ ret = drmDMA( fd, &dma );
+
+ if (ret != 0) {
+ /* Free some up this way?
+ */
+ if (rmesa->dma.nr_released_bufs) {
+ radeonFlushCmdBufLocked( rmesa, __FUNCTION__ );
+ }
+
+ if (RADEON_DEBUG & DEBUG_DMA)
+ fprintf(stderr, "Waiting for buffers\n");
+
+ radeonWaitForIdleLocked( rmesa );
+ ret = drmDMA( fd, &dma );
+
+ if ( ret != 0 ) {
+ UNLOCK_HARDWARE( rmesa );
+ fprintf( stderr, "Error: Could not get dma buffer... exiting\n" );
+ exit( -1 );
+ }
+ }
+
+ UNLOCK_HARDWARE(rmesa);
+
+ if (RADEON_DEBUG & DEBUG_DMA)
+ fprintf(stderr, "Allocated buffer %d\n", index);
+
+ dmabuf = CALLOC_STRUCT( radeon_dma_buffer );
+ dmabuf->buf = &rmesa->radeonScreen->buffers->list[index];
+ dmabuf->refcount = 1;
+
+ rmesa->dma.current.buf = dmabuf;
+ rmesa->dma.current.address = dmabuf->buf->address;
+ rmesa->dma.current.end = dmabuf->buf->total;
+ rmesa->dma.current.start = 0;
+ rmesa->dma.current.ptr = 0;
+
+ rmesa->c_vertexBuffers++;
+}
+
+void radeonReleaseDmaRegion( radeonContextPtr rmesa,
+ struct radeon_dma_region *region,
+ const char *caller )
+{
+ if (RADEON_DEBUG & DEBUG_IOCTL)
+ fprintf(stderr, "%s from %s\n", __FUNCTION__, caller);
+
+ if (!region->buf)
+ return;
+
+ if (rmesa->dma.flush)
+ rmesa->dma.flush( rmesa );
+
+ if (--region->buf->refcount == 0) {
+ drmRadeonCmdHeader *cmd;
+
+ if (RADEON_DEBUG & (DEBUG_IOCTL|DEBUG_DMA))
+ fprintf(stderr, "%s -- DISCARD BUF %d\n", __FUNCTION__,
+ region->buf->buf->idx);
+
+ cmd = (drmRadeonCmdHeader *)radeonAllocCmdBuf( rmesa, sizeof(*cmd),
+ __FUNCTION__ );
+ cmd->dma.cmd_type = RADEON_CMD_DMA_DISCARD;
+ cmd->dma.buf_idx = region->buf->buf->idx;
+ FREE(region->buf);
+ rmesa->dma.nr_released_bufs++;
+ }
+
+ region->buf = 0;
+ region->start = 0;
+}
+
+/* Allocates a region from rmesa->dma.current. If there isn't enough
+ * space in current, grab a new buffer (and discard what was left of current)
+ */
+void radeonAllocDmaRegion( radeonContextPtr rmesa,
+ struct radeon_dma_region *region,
+ int bytes,
+ int alignment )
+{
+ if (RADEON_DEBUG & DEBUG_IOCTL)
+ fprintf(stderr, "%s %d\n", __FUNCTION__, bytes);
+
+ if (rmesa->dma.flush)
+ rmesa->dma.flush( rmesa );
+
+ if (region->buf)
+ radeonReleaseDmaRegion( rmesa, region, __FUNCTION__ );
+
+ alignment--;
+ rmesa->dma.current.start = rmesa->dma.current.ptr =
+ (rmesa->dma.current.ptr + alignment) & ~alignment;
+
+ if ( rmesa->dma.current.ptr + bytes > rmesa->dma.current.end )
+ radeonRefillCurrentDmaRegion( rmesa );
+
+ region->start = rmesa->dma.current.start;
+ region->ptr = rmesa->dma.current.start;
+ region->end = rmesa->dma.current.start + bytes;
+ region->address = rmesa->dma.current.address;
+ region->buf = rmesa->dma.current.buf;
+ region->buf->refcount++;
+
+ rmesa->dma.current.ptr += bytes; /* bug - if alignment > 7 */
+ rmesa->dma.current.start =
+ rmesa->dma.current.ptr = (rmesa->dma.current.ptr + 0x7) & ~0x7;
+
+ if ( rmesa->dri.drmMinor < 3 )
+ radeonRefillCurrentDmaRegion( rmesa );
+}
+
+void radeonAllocDmaRegionVerts( radeonContextPtr rmesa,
+ struct radeon_dma_region *region,
+ int numverts,
+ int vertsize,
+ int alignment )
+{
+ radeonAllocDmaRegion( rmesa, region, vertsize * numverts, alignment );
+}
+
+/* ================================================================
+ * SwapBuffers with client-side throttling
+ */
+
+static CARD32 radeonGetLastFrame (radeonContextPtr rmesa)
+{
+ unsigned char *RADEONMMIO = rmesa->radeonScreen->mmio.map;
+ int ret;
+ CARD32 frame;
+
+ if (rmesa->dri.screen->drmMinor >= 4) {
+ drmRadeonGetParam gp;
+
+ gp.param = RADEON_PARAM_LAST_FRAME;
+ gp.value = &frame;
+ ret = drmCommandWriteRead( rmesa->dri.fd, DRM_RADEON_GETPARAM,
+ &gp, sizeof(gp) );
+ }
+ else
+ ret = -EINVAL;
+
+#ifndef __alpha__
+ if ( ret == -EINVAL ) {
+ frame = INREG( RADEON_LAST_FRAME_REG );
+ ret = 0;
+ }
+#endif
+ if ( ret ) {
+ fprintf( stderr, "%s: drmRadeonGetParam: %d\n", __FUNCTION__, ret );
+ exit(1);
+ }
+
+ return frame;
+}
+
+static void radeonEmitIrqLocked( radeonContextPtr rmesa )
+{
+ drmRadeonIrqEmit ie;
+ int ret;
+
+ ie.irq_seq = &rmesa->iw.irq_seq;
+ ret = drmCommandWriteRead( rmesa->dri.fd, DRM_RADEON_IRQ_EMIT,
+ &ie, sizeof(ie) );
+ if ( ret ) {
+ fprintf( stderr, "%s: drmRadeonIrqEmit: %d\n", __FUNCTION__, ret );
+ exit(1);
+ }
+}
+
+
+static void radeonWaitIrq( radeonContextPtr rmesa )
+{
+ int ret;
+
+ do {
+ ret = drmCommandWrite( rmesa->dri.fd, DRM_RADEON_IRQ_WAIT,
+ &rmesa->iw, sizeof(rmesa->iw) );
+ } while (ret && (errno == EINTR || errno == EAGAIN));
+
+ if ( ret ) {
+ fprintf( stderr, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__, ret );
+ exit(1);
+ }
+}
+
+
+static void radeonWaitForFrameCompletion( radeonContextPtr rmesa )
+{
+ RADEONSAREAPrivPtr sarea = rmesa->sarea;
+
+ if (rmesa->do_irqs) {
+ if (radeonGetLastFrame(rmesa) < sarea->last_frame) {
+ if (!rmesa->irqsEmitted) {
+ while (radeonGetLastFrame (rmesa) < sarea->last_frame)
+ ;
+ }
+ else {
+ UNLOCK_HARDWARE( rmesa );
+ radeonWaitIrq( rmesa );
+ LOCK_HARDWARE( rmesa );
+ }
+ rmesa->irqsEmitted = 10;
+ }
+
+ if (rmesa->irqsEmitted) {
+ radeonEmitIrqLocked( rmesa );
+ rmesa->irqsEmitted--;
+ }
+ }
+ else {
+ while (radeonGetLastFrame (rmesa) < sarea->last_frame) {
+ UNLOCK_HARDWARE( rmesa );
+ if (rmesa->do_usleeps)
+ DO_USLEEP( 1 );
+ LOCK_HARDWARE( rmesa );
+ }
+ }
+}
+
+/* Copy the back color buffer to the front color buffer.
+ */
+void radeonCopyBuffer( const __DRIdrawablePrivate *dPriv )
+{
+ radeonContextPtr rmesa;
+ GLint nbox, i, ret;
+ GLboolean missed_target;
+ uint64_t ust;
+
+ assert(dPriv);
+ assert(dPriv->driContextPriv);
+ assert(dPriv->driContextPriv->driverPrivate);
+
+ rmesa = (radeonContextPtr) dPriv->driContextPriv->driverPrivate;
+
+ if ( RADEON_DEBUG & DEBUG_IOCTL ) {
+ fprintf( stderr, "\n%s( %p )\n\n", __FUNCTION__, rmesa->glCtx );
+ }
+
+ RADEON_FIREVERTICES( rmesa );
+ LOCK_HARDWARE( rmesa );
+
+ /* Throttle the frame rate -- only allow one pending swap buffers
+ * request at a time.
+ */
+ radeonWaitForFrameCompletion( rmesa );
+ UNLOCK_HARDWARE( rmesa );
+ driWaitForVBlank( dPriv, & rmesa->vbl_seq, rmesa->vblank_flags, & missed_target );
+ LOCK_HARDWARE( rmesa );
+
+ nbox = dPriv->numClipRects; /* must be in locked region */
+
+ for ( i = 0 ; i < nbox ; ) {
+ GLint nr = MIN2( i + RADEON_NR_SAREA_CLIPRECTS , nbox );
+ XF86DRIClipRectPtr box = dPriv->pClipRects;
+ XF86DRIClipRectPtr b = rmesa->sarea->boxes;
+ GLint n = 0;
+
+ for ( ; i < nr ; i++ ) {
+ *b++ = box[i];
+ n++;
+ }
+ rmesa->sarea->nbox = n;
+
+ ret = drmCommandNone( rmesa->dri.fd, DRM_RADEON_SWAP );
+
+ if ( ret ) {
+ fprintf( stderr, "DRM_RADEON_SWAP_BUFFERS: return = %d\n", ret );
+ UNLOCK_HARDWARE( rmesa );
+ exit( 1 );
+ }
+ }
+
+ UNLOCK_HARDWARE( rmesa );
+ rmesa->swap_count++;
+ (*rmesa->get_ust)( & ust );
+ if ( missed_target ) {
+ rmesa->swap_missed_count++;
+ rmesa->swap_missed_ust = ust - rmesa->swap_ust;
+ }
+
+ rmesa->swap_ust = ust;
+}
+
+void radeonPageFlip( const __DRIdrawablePrivate *dPriv )
+{
+ radeonContextPtr rmesa;
+ GLint ret;
+ GLboolean missed_target;
+
+ assert(dPriv);
+ assert(dPriv->driContextPriv);
+ assert(dPriv->driContextPriv->driverPrivate);
+
+ rmesa = (radeonContextPtr) dPriv->driContextPriv->driverPrivate;
+
+ if ( RADEON_DEBUG & DEBUG_IOCTL ) {
+ fprintf(stderr, "%s: pfCurrentPage: %d\n", __FUNCTION__,
+ rmesa->sarea->pfCurrentPage);
+ }
+
+ RADEON_FIREVERTICES( rmesa );
+ LOCK_HARDWARE( rmesa );
+
+ /* Need to do this for the perf box placement:
+ */
+ if (dPriv->numClipRects)
+ {
+ XF86DRIClipRectPtr box = dPriv->pClipRects;
+ XF86DRIClipRectPtr b = rmesa->sarea->boxes;
+ b[0] = box[0];
+ rmesa->sarea->nbox = 1;
+ }
+
+ /* Throttle the frame rate -- only allow a few pending swap buffers
+ * request at a time.
+ */
+ radeonWaitForFrameCompletion( rmesa );
+ UNLOCK_HARDWARE( rmesa );
+ driWaitForVBlank( dPriv, & rmesa->vbl_seq, rmesa->vblank_flags, & missed_target );
+ if ( missed_target ) {
+ rmesa->swap_missed_count++;
+ (void) (*rmesa->get_ust)( & rmesa->swap_missed_ust );
+ }
+ LOCK_HARDWARE( rmesa );
+
+ ret = drmCommandNone( rmesa->dri.fd, DRM_RADEON_FLIP );
+
+ UNLOCK_HARDWARE( rmesa );
+
+ if ( ret ) {
+ fprintf( stderr, "DRM_RADEON_FLIP: return = %d\n", ret );
+ exit( 1 );
+ }
+
+ rmesa->swap_count++;
+ (void) (*rmesa->get_ust)( & rmesa->swap_ust );
+
+ if ( rmesa->sarea->pfCurrentPage == 1 ) {
+ rmesa->state.color.drawOffset = rmesa->radeonScreen->frontOffset;
+ rmesa->state.color.drawPitch = rmesa->radeonScreen->frontPitch;
+ } else {
+ rmesa->state.color.drawOffset = rmesa->radeonScreen->backOffset;
+ rmesa->state.color.drawPitch = rmesa->radeonScreen->backPitch;
+ }
+
+ RADEON_STATECHANGE( rmesa, ctx );
+ rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = rmesa->state.color.drawOffset;
+ rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = rmesa->state.color.drawPitch;
+}
+
+
+/* ================================================================
+ * Buffer clear
+ */
+#define RADEON_MAX_CLEARS 256
+
+static void radeonClear( GLcontext *ctx, GLbitfield mask, GLboolean all,
+ GLint cx, GLint cy, GLint cw, GLint ch )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
+ RADEONSAREAPrivPtr sarea = rmesa->sarea;
+ unsigned char *RADEONMMIO = rmesa->radeonScreen->mmio.map;
+ CARD32 clear;
+ GLuint flags = 0;
+ GLuint color_mask = 0;
+ GLint ret, i;
+
+ if ( RADEON_DEBUG & DEBUG_IOCTL ) {
+ fprintf( stderr, "%s: all=%d cx=%d cy=%d cw=%d ch=%d\n",
+ __FUNCTION__, all, cx, cy, cw, ch );
+ }
+
+ radeonEmitState( rmesa );
+
+ /* Need to cope with lostcontext here as kernel relies on
+ * some residual state:
+ */
+ RADEON_FIREVERTICES( rmesa );
+
+ if ( mask & DD_FRONT_LEFT_BIT ) {
+ flags |= RADEON_FRONT;
+ color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
+ mask &= ~DD_FRONT_LEFT_BIT;
+ }
+
+ if ( mask & DD_BACK_LEFT_BIT ) {
+ flags |= RADEON_BACK;
+ color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
+ mask &= ~DD_BACK_LEFT_BIT;
+ }
+
+ if ( mask & DD_DEPTH_BIT ) {
+ if ( ctx->Depth.Mask ) flags |= RADEON_DEPTH; /* FIXME: ??? */
+ mask &= ~DD_DEPTH_BIT;
+ }
+
+ if ( (mask & DD_STENCIL_BIT) && rmesa->state.stencil.hwBuffer ) {
+ flags |= RADEON_STENCIL;
+ mask &= ~DD_STENCIL_BIT;
+ }
+
+ if ( mask ) {
+ if (RADEON_DEBUG & DEBUG_FALLBACKS)
+ fprintf(stderr, "%s: swrast clear, mask: %x\n", __FUNCTION__, mask);
+ _swrast_Clear( ctx, mask, all, cx, cy, cw, ch );
+ }
+
+ if ( !flags )
+ return;
+
+
+ /* Flip top to bottom */
+ cx += dPriv->x;
+ cy = dPriv->y + dPriv->h - cy - ch;
+
+ LOCK_HARDWARE( rmesa );
+
+ /* Throttle the number of clear ioctls we do.
+ */
+ while ( 1 ) {
+ int ret;
+
+ if (rmesa->dri.screen->drmMinor >= 4) {
+ drmRadeonGetParam gp;
+
+ gp.param = RADEON_PARAM_LAST_CLEAR;
+ gp.value = &clear;
+ ret = drmCommandWriteRead( rmesa->dri.fd,
+ DRM_RADEON_GETPARAM, &gp, sizeof(gp) );
+ } else
+ ret = -EINVAL;
+
+#ifndef __alpha__
+ if ( ret == -EINVAL ) {
+ clear = INREG( RADEON_LAST_CLEAR_REG );
+ ret = 0;
+ }
+#endif
+ if ( ret ) {
+ fprintf( stderr, "%s: drmRadeonGetParam: %d\n", __FUNCTION__, ret );
+ exit(1);
+ }
+ if ( RADEON_DEBUG & DEBUG_IOCTL ) {
+ fprintf( stderr, "%s( %d )\n", __FUNCTION__, (int)clear );
+ if ( ret ) fprintf( stderr, " ( RADEON_LAST_CLEAR register read directly )\n" );
+ }
+
+ if ( sarea->last_clear - clear <= RADEON_MAX_CLEARS ) {
+ break;
+ }
+
+ if ( rmesa->do_usleeps ) {
+ UNLOCK_HARDWARE( rmesa );
+ DO_USLEEP( 1 );
+ LOCK_HARDWARE( rmesa );
+ }
+ }
+
+ for ( i = 0 ; i < dPriv->numClipRects ; ) {
+ GLint nr = MIN2( i + RADEON_NR_SAREA_CLIPRECTS, dPriv->numClipRects );
+ XF86DRIClipRectPtr box = dPriv->pClipRects;
+ XF86DRIClipRectPtr b = rmesa->sarea->boxes;
+ drmRadeonClearType clear;
+ drmRadeonClearRect depth_boxes[RADEON_NR_SAREA_CLIPRECTS];
+ GLint n = 0;
+
+ if ( !all ) {
+ 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 {
+ for ( ; i < nr ; i++ ) {
+ *b++ = box[i];
+ n++;
+ }
+ }
+
+ rmesa->sarea->nbox = n;
+
+ clear.flags = flags;
+ clear.clear_color = rmesa->state.color.clear;
+ clear.clear_depth = rmesa->state.depth.clear;
+ clear.color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
+ clear.depth_mask = rmesa->state.stencil.clear;
+ clear.depth_boxes = depth_boxes;
+
+ n--;
+ b = rmesa->sarea->boxes;
+ for ( ; n >= 0 ; n-- ) {
+ depth_boxes[n].f[RADEON_CLEAR_X1] = (float)b[n].x1;
+ depth_boxes[n].f[RADEON_CLEAR_Y1] = (float)b[n].y1;
+ depth_boxes[n].f[RADEON_CLEAR_X2] = (float)b[n].x2;
+ depth_boxes[n].f[RADEON_CLEAR_Y2] = (float)b[n].y2;
+ depth_boxes[n].f[RADEON_CLEAR_DEPTH] =
+ (float)rmesa->state.depth.clear;
+ }
+
+ ret = drmCommandWrite( rmesa->dri.fd, DRM_RADEON_CLEAR,
+ &clear, sizeof(drmRadeonClearType));
+
+ if ( ret ) {
+ UNLOCK_HARDWARE( rmesa );
+ fprintf( stderr, "DRM_RADEON_CLEAR: return = %d\n", ret );
+ exit( 1 );
+ }
+ }
+
+ UNLOCK_HARDWARE( rmesa );
+}
+
+
+void radeonWaitForIdleLocked( radeonContextPtr rmesa )
+{
+ int fd = rmesa->dri.fd;
+ int to = 0;
+ int ret, i = 0;
+
+ rmesa->c_drawWaits++;
+
+ do {
+ do {
+ ret = drmCommandNone( fd, DRM_RADEON_CP_IDLE);
+ } while ( ret && errno == EBUSY && i++ < RADEON_IDLE_RETRY );
+ } while ( ( ret == -EBUSY ) && ( to++ < RADEON_TIMEOUT ) );
+
+ if ( ret < 0 ) {
+ UNLOCK_HARDWARE( rmesa );
+ fprintf( stderr, "Error: Radeon timed out... exiting\n" );
+ exit( -1 );
+ }
+}
+
+
+static void radeonWaitForIdle( radeonContextPtr rmesa )
+{
+ LOCK_HARDWARE(rmesa);
+ radeonWaitForIdleLocked( rmesa );
+ UNLOCK_HARDWARE(rmesa);
+}
+
+
+void radeonFlush( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+
+ if (RADEON_DEBUG & DEBUG_IOCTL)
+ fprintf(stderr, "%s\n", __FUNCTION__);
+
+ if (rmesa->dma.flush)
+ rmesa->dma.flush( rmesa );
+
+ if (rmesa->dri.drmMinor >= 3) {
+ if (!is_empty_list(&rmesa->hw.dirty))
+ radeonEmitState( rmesa );
+
+ if (rmesa->store.cmd_used)
+ radeonFlushCmdBuf( rmesa, __FUNCTION__ );
+ }
+}
+
+/* Make sure all commands have been sent to the hardware and have
+ * completed processing.
+ */
+void radeonFinish( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ radeonFlush( ctx );
+
+ if (rmesa->do_irqs) {
+ LOCK_HARDWARE( rmesa );
+ radeonEmitIrqLocked( rmesa );
+ UNLOCK_HARDWARE( rmesa );
+ radeonWaitIrq( rmesa );
+ }
+ else
+ radeonWaitForIdle( rmesa );
+}
+
+
+void radeonInitIoctlFuncs( GLcontext *ctx )
+{
+ ctx->Driver.Clear = radeonClear;
+ ctx->Driver.Finish = radeonFinish;
+ ctx->Driver.Flush = radeonFlush;
+}
+
diff --git a/src/mesa/drivers/dri/radeon/radeon_ioctl.h b/src/mesa/drivers/dri/radeon/radeon_ioctl.h
new file mode 100644
index 0000000000..3f6e1751cf
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_ioctl.h
@@ -0,0 +1,188 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_ioctl.h,v 1.6 2002/12/16 16:18:58 dawes 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 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 THE COPYRIGHT OWNER(S) 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:
+ * Kevin E. Martin <martin@valinux.com>
+ * Gareth Hughes <gareth@valinux.com>
+ */
+
+#ifndef __RADEON_IOCTL_H__
+#define __RADEON_IOCTL_H__
+
+#ifdef GLX_DIRECT_RENDERING
+
+#include "simple_list.h"
+#include "radeon_lock.h"
+
+
+extern void radeonEmitState( radeonContextPtr rmesa );
+extern void radeonEmitVertexAOS( radeonContextPtr rmesa,
+ GLuint vertex_size,
+ GLuint offset );
+
+extern void radeonEmitVbufPrim( radeonContextPtr rmesa,
+ GLuint vertex_format,
+ GLuint primitive,
+ GLuint vertex_nr );
+
+extern void radeonFlushElts( radeonContextPtr rmesa );
+
+extern GLushort *radeonAllocEltsOpenEnded( radeonContextPtr rmesa,
+ GLuint vertex_format,
+ GLuint primitive,
+ GLuint min_nr );
+
+extern void radeonEmitAOS( radeonContextPtr rmesa,
+ struct radeon_dma_region **regions,
+ GLuint n,
+ GLuint offset );
+
+extern void radeonEmitBlit( radeonContextPtr rmesa,
+ GLuint color_fmt,
+ GLuint src_pitch,
+ GLuint src_offset,
+ GLuint dst_pitch,
+ GLuint dst_offset,
+ GLint srcx, GLint srcy,
+ GLint dstx, GLint dsty,
+ GLuint w, GLuint h );
+
+extern void radeonEmitWait( radeonContextPtr rmesa, GLuint flags );
+
+extern void radeonFlushCmdBuf( radeonContextPtr rmesa, const char * );
+extern void radeonRefillCurrentDmaRegion( radeonContextPtr rmesa );
+
+extern void radeonAllocDmaRegion( radeonContextPtr rmesa,
+ struct radeon_dma_region *region,
+ int bytes,
+ int alignment );
+
+extern void radeonAllocDmaRegionVerts( radeonContextPtr rmesa,
+ struct radeon_dma_region *region,
+ int numverts,
+ int vertsize,
+ int alignment );
+
+extern void radeonReleaseDmaRegion( radeonContextPtr rmesa,
+ struct radeon_dma_region *region,
+ const char *caller );
+
+extern void radeonCopyBuffer( const __DRIdrawablePrivate *drawable );
+extern void radeonPageFlip( const __DRIdrawablePrivate *drawable );
+extern void radeonFlush( GLcontext *ctx );
+extern void radeonFinish( GLcontext *ctx );
+extern void radeonWaitForIdleLocked( radeonContextPtr rmesa );
+extern void radeonWaitForVBlank( radeonContextPtr rmesa );
+extern void radeonInitIoctlFuncs( GLcontext *ctx );
+extern void radeonGetAllParams( radeonContextPtr rmesa );
+
+/* radeon_compat.c:
+ */
+extern void radeonCompatEmitPrimitive( radeonContextPtr rmesa,
+ GLuint vertex_format,
+ GLuint hw_primitive,
+ GLuint nrverts );
+
+
+/* ================================================================
+ * Helper macros:
+ */
+
+/* Close off the last primitive, if it exists.
+ */
+#define RADEON_NEWPRIM( rmesa ) \
+do { \
+ if ( rmesa->dma.flush ) \
+ rmesa->dma.flush( rmesa ); \
+} while (0)
+
+/* Can accomodate several state changes and primitive changes without
+ * actually firing the buffer.
+ */
+#define RADEON_STATECHANGE( rmesa, ATOM ) \
+do { \
+ RADEON_NEWPRIM( rmesa ); \
+ move_to_head( &(rmesa->hw.dirty), &(rmesa->hw.ATOM)); \
+} while (0)
+
+#define RADEON_DB_STATE( ATOM ) \
+ memcpy( rmesa->hw.ATOM.lastcmd, rmesa->hw.ATOM.cmd, \
+ rmesa->hw.ATOM.cmd_size * 4)
+
+static __inline int RADEON_DB_STATECHANGE(
+ radeonContextPtr rmesa,
+ struct radeon_state_atom *atom )
+{
+ if (memcmp(atom->cmd, atom->lastcmd, atom->cmd_size*4)) {
+ int *tmp;
+ RADEON_NEWPRIM( rmesa );
+ move_to_head( &(rmesa->hw.dirty), atom );
+ tmp = atom->cmd;
+ atom->cmd = atom->lastcmd;
+ atom->lastcmd = tmp;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+
+/* Fire the buffered vertices no matter what.
+ */
+#define RADEON_FIREVERTICES( rmesa ) \
+do { \
+ if ( rmesa->store.cmd_used || rmesa->dma.flush ) { \
+ radeonFlush( rmesa->glCtx ); \
+ } \
+} while (0)
+
+/* Alloc space in the command buffer
+ */
+static __inline char *radeonAllocCmdBuf( radeonContextPtr rmesa,
+ int bytes, const char *where )
+{
+ if (rmesa->store.cmd_used + bytes > RADEON_CMD_BUF_SZ)
+ radeonFlushCmdBuf( rmesa, __FUNCTION__ );
+
+ assert(rmesa->dri.drmMinor >= 3);
+
+ {
+ char *head = rmesa->store.cmd_buf + rmesa->store.cmd_used;
+ rmesa->store.cmd_used += bytes;
+ return head;
+ }
+}
+
+
+
+
+#endif
+#endif /* __RADEON_IOCTL_H__ */
diff --git a/src/mesa/drivers/dri/radeon/radeon_lighting.c b/src/mesa/drivers/dri/radeon/radeon_lighting.c
new file mode 100644
index 0000000000..b00c9cb6de
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_lighting.c
@@ -0,0 +1,682 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_state.c,v 1.5 2002/09/16 18:05:20 eich Exp $ */
+/*
+ * Copyright 2000, 2001 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
+ * 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:
+ * Gareth Hughes <gareth@valinux.com>
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "glheader.h"
+#include "imports.h"
+#include "api_arrayelt.h"
+/* #include "mmath.h" */
+#include "enums.h"
+#include "colormac.h"
+
+
+#include "radeon_context.h"
+#include "radeon_ioctl.h"
+#include "radeon_state.h"
+#include "radeon_tcl.h"
+#include "radeon_tex.h"
+#include "radeon_vtxfmt.h"
+
+
+
+/* =============================================================
+ * Materials
+ */
+
+
+/* Update on colormaterial, material emmissive/ambient,
+ * lightmodel.globalambient
+ */
+void update_global_ambient( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ float *fcmd = (float *)RADEON_DB_STATE( glt );
+
+ /* Need to do more if both emmissive & ambient are PREMULT:
+ */
+ if ((rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &
+ ((3 << RADEON_EMISSIVE_SOURCE_SHIFT) |
+ (3 << RADEON_AMBIENT_SOURCE_SHIFT))) == 0)
+ {
+ COPY_3V( &fcmd[GLT_RED],
+ ctx->Light.Material[0].Emission);
+ ACC_SCALE_3V( &fcmd[GLT_RED],
+ ctx->Light.Model.Ambient,
+ ctx->Light.Material[0].Ambient);
+ }
+ else
+ {
+ COPY_3V( &fcmd[GLT_RED], ctx->Light.Model.Ambient );
+ }
+
+ RADEON_DB_STATECHANGE(rmesa, &rmesa->hw.glt);
+}
+
+/* Update on change to
+ * - light[p].colors
+ * - light[p].enabled
+ * - material,
+ * - colormaterial enabled
+ * - colormaterial bitmask
+ */
+void update_light_colors( GLcontext *ctx, GLuint p )
+{
+ struct gl_light *l = &ctx->Light.Light[p];
+
+/* fprintf(stderr, "%s\n", __FUNCTION__); */
+
+ if (l->Enabled) {
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ float *fcmd = (float *)RADEON_DB_STATE( lit[p] );
+ GLuint bitmask = ctx->Light.ColorMaterialBitmask;
+ struct gl_material *mat = &ctx->Light.Material[0];
+
+ COPY_4V( &fcmd[LIT_AMBIENT_RED], l->Ambient );
+ COPY_4V( &fcmd[LIT_DIFFUSE_RED], l->Diffuse );
+ COPY_4V( &fcmd[LIT_SPECULAR_RED], l->Specular );
+
+ if (!ctx->Light.ColorMaterialEnabled)
+ bitmask = 0;
+
+ if ((bitmask & FRONT_AMBIENT_BIT) == 0)
+ SELF_SCALE_3V( &fcmd[LIT_AMBIENT_RED], mat->Ambient );
+
+ if ((bitmask & FRONT_DIFFUSE_BIT) == 0)
+ SELF_SCALE_3V( &fcmd[LIT_DIFFUSE_RED], mat->Diffuse );
+
+ if ((bitmask & FRONT_SPECULAR_BIT) == 0)
+ SELF_SCALE_3V( &fcmd[LIT_SPECULAR_RED], mat->Specular );
+
+ RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
+ }
+}
+
+/* Also fallback for asym colormaterial mode in twoside lighting...
+ */
+void check_twoside_fallback( GLcontext *ctx )
+{
+ GLboolean fallback = GL_FALSE;
+
+ if (ctx->Light.Enabled && ctx->Light.Model.TwoSide) {
+ if (memcmp( &ctx->Light.Material[0],
+ &ctx->Light.Material[1],
+ sizeof(struct gl_material)) != 0)
+ fallback = GL_TRUE;
+ else if (ctx->Light.ColorMaterialEnabled &&
+ (ctx->Light.ColorMaterialBitmask & BACK_MATERIAL_BITS) !=
+ ((ctx->Light.ColorMaterialBitmask & FRONT_MATERIAL_BITS)<<1))
+ fallback = GL_TRUE;
+ }
+
+ TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_LIGHT_TWOSIDE, fallback );
+}
+
+void radeonColorMaterial( GLcontext *ctx, GLenum face, GLenum mode )
+{
+ if (ctx->Light.ColorMaterialEnabled) {
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLuint light_model_ctl = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL];
+ GLuint mask = ctx->Light.ColorMaterialBitmask;
+
+ /* Default to PREMULT:
+ */
+ light_model_ctl &= ~((3 << RADEON_EMISSIVE_SOURCE_SHIFT) |
+ (3 << RADEON_AMBIENT_SOURCE_SHIFT) |
+ (3 << RADEON_DIFFUSE_SOURCE_SHIFT) |
+ (3 << RADEON_SPECULAR_SOURCE_SHIFT));
+
+ if (mask & FRONT_EMISSION_BIT) {
+ light_model_ctl |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE <<
+ RADEON_EMISSIVE_SOURCE_SHIFT);
+ }
+
+ if (mask & FRONT_AMBIENT_BIT) {
+ light_model_ctl |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE <<
+ RADEON_AMBIENT_SOURCE_SHIFT);
+ }
+
+ if (mask & FRONT_DIFFUSE_BIT) {
+ light_model_ctl |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE <<
+ RADEON_DIFFUSE_SOURCE_SHIFT);
+ }
+
+ if (mask & FRONT_SPECULAR_BIT) {
+ light_model_ctl |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE <<
+ RADEON_SPECULAR_SOURCE_SHIFT);
+ }
+
+ if (light_model_ctl != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]) {
+ GLuint p;
+
+ RADEON_STATECHANGE( rmesa, tcl );
+ rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] = light_model_ctl;
+
+ for (p = 0 ; p < MAX_LIGHTS; p++)
+ update_light_colors( ctx, p );
+ update_global_ambient( ctx );
+ }
+ }
+
+ check_twoside_fallback( ctx );
+}
+
+void radeonUpdateMaterial( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( mtl );
+ GLuint p;
+ GLuint mask = ~0;
+
+ if (ctx->Light.ColorMaterialEnabled)
+ mask &= ~ctx->Light.ColorMaterialBitmask;
+
+ if (RADEON_DEBUG & DEBUG_STATE)
+ fprintf(stderr, "%s\n", __FUNCTION__);
+
+
+ if (mask & FRONT_EMISSION_BIT) {
+ fcmd[MTL_EMMISSIVE_RED] = ctx->Light.Material[0].Emission[0];
+ fcmd[MTL_EMMISSIVE_GREEN] = ctx->Light.Material[0].Emission[1];
+ fcmd[MTL_EMMISSIVE_BLUE] = ctx->Light.Material[0].Emission[2];
+ fcmd[MTL_EMMISSIVE_ALPHA] = ctx->Light.Material[0].Emission[3];
+ }
+ if (mask & FRONT_AMBIENT_BIT) {
+ fcmd[MTL_AMBIENT_RED] = ctx->Light.Material[0].Ambient[0];
+ fcmd[MTL_AMBIENT_GREEN] = ctx->Light.Material[0].Ambient[1];
+ fcmd[MTL_AMBIENT_BLUE] = ctx->Light.Material[0].Ambient[2];
+ fcmd[MTL_AMBIENT_ALPHA] = ctx->Light.Material[0].Ambient[3];
+ }
+ if (mask & FRONT_DIFFUSE_BIT) {
+ fcmd[MTL_DIFFUSE_RED] = ctx->Light.Material[0].Diffuse[0];
+ fcmd[MTL_DIFFUSE_GREEN] = ctx->Light.Material[0].Diffuse[1];
+ fcmd[MTL_DIFFUSE_BLUE] = ctx->Light.Material[0].Diffuse[2];
+ fcmd[MTL_DIFFUSE_ALPHA] = ctx->Light.Material[0].Diffuse[3];
+ }
+ if (mask & FRONT_SPECULAR_BIT) {
+ fcmd[MTL_SPECULAR_RED] = ctx->Light.Material[0].Specular[0];
+ fcmd[MTL_SPECULAR_GREEN] = ctx->Light.Material[0].Specular[1];
+ fcmd[MTL_SPECULAR_BLUE] = ctx->Light.Material[0].Specular[2];
+ fcmd[MTL_SPECULAR_ALPHA] = ctx->Light.Material[0].Specular[3];
+ }
+ if (mask & FRONT_SHININESS_BIT) {
+ fcmd[MTL_SHININESS] = ctx->Light.Material[0].Shininess;
+ }
+
+ if (RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mtl )) {
+ for (p = 0 ; p < MAX_LIGHTS; p++)
+ update_light_colors( ctx, p );
+
+ check_twoside_fallback( ctx );
+ update_global_ambient( ctx );
+ }
+ else if (RADEON_DEBUG & (DEBUG_PRIMS|DEBUG_STATE))
+ fprintf(stderr, "%s: Elided noop material call\n", __FUNCTION__);
+}
+
+/* _NEW_LIGHT
+ * _NEW_MODELVIEW
+ * _MESA_NEW_NEED_EYE_COORDS
+ *
+ * Uses derived state from mesa:
+ * _VP_inf_norm
+ * _h_inf_norm
+ * _Position
+ * _NormDirection
+ * _ModelViewInvScale
+ * _NeedEyeCoords
+ * _EyeZDir
+ *
+ * which are calculated in light.c and are correct for the current
+ * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
+ * and _MESA_NEW_NEED_EYE_COORDS.
+ */
+void radeonUpdateLighting( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ /* Have to check these, or have an automatic shortcircuit mechanism
+ * to remove noop statechanges. (Or just do a better job on the
+ * front end).
+ */
+ {
+ GLuint tmp = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL];
+
+ if (ctx->_NeedEyeCoords)
+ tmp &= ~RADEON_LIGHT_IN_MODELSPACE;
+ else
+ tmp |= RADEON_LIGHT_IN_MODELSPACE;
+
+
+ /* Leave this test disabled: (unexplained q3 lockup) (even with
+ new packets)
+ */
+ if (tmp != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL])
+ {
+ RADEON_STATECHANGE( rmesa, tcl );
+ rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] = tmp;
+ }
+ }
+
+ {
+ GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( eye );
+ fcmd[EYE_X] = ctx->_EyeZDir[0];
+ fcmd[EYE_Y] = ctx->_EyeZDir[1];
+ fcmd[EYE_Z] = - ctx->_EyeZDir[2];
+ fcmd[EYE_RESCALE_FACTOR] = ctx->_ModelViewInvScale;
+ RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.eye );
+ }
+
+
+/* RADEON_STATECHANGE( rmesa, glt ); */
+
+ if (ctx->Light.Enabled) {
+ GLint p;
+ for (p = 0 ; p < MAX_LIGHTS; p++) {
+ if (ctx->Light.Light[p].Enabled) {
+ struct gl_light *l = &ctx->Light.Light[p];
+ GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( lit[p] );
+
+ if (l->EyePosition[3] == 0.0) {
+ COPY_3FV( &fcmd[LIT_POSITION_X], l->_VP_inf_norm );
+ COPY_3FV( &fcmd[LIT_DIRECTION_X], l->_h_inf_norm );
+ fcmd[LIT_POSITION_W] = 0;
+ fcmd[LIT_DIRECTION_W] = 0;
+ } else {
+ COPY_4V( &fcmd[LIT_POSITION_X], l->_Position );
+ fcmd[LIT_DIRECTION_X] = -l->_NormDirection[0];
+ fcmd[LIT_DIRECTION_Y] = -l->_NormDirection[1];
+ fcmd[LIT_DIRECTION_Z] = -l->_NormDirection[2];
+ fcmd[LIT_DIRECTION_W] = 0;
+ }
+
+ RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
+ }
+ }
+ }
+}
+
+
+void radeonLightfv( GLcontext *ctx, GLenum light,
+ GLenum pname, const GLfloat *params )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLint p = light - GL_LIGHT0;
+ struct gl_light *l = &ctx->Light.Light[p];
+ GLfloat *fcmd = (GLfloat *)rmesa->hw.lit[p].cmd;
+
+
+ switch (pname) {
+ case GL_AMBIENT:
+ case GL_DIFFUSE:
+ case GL_SPECULAR:
+ update_light_colors( ctx, p );
+ break;
+
+ case GL_SPOT_DIRECTION:
+ /* picked up in update_light */
+ break;
+
+ case GL_POSITION: {
+ /* positions picked up in update_light, but can do flag here */
+ GLuint flag = (p&1)? RADEON_LIGHT_1_IS_LOCAL : RADEON_LIGHT_0_IS_LOCAL;
+ GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
+
+ RADEON_STATECHANGE(rmesa, tcl);
+ if (l->EyePosition[3] != 0.0F)
+ rmesa->hw.tcl.cmd[idx] |= flag;
+ else
+ rmesa->hw.tcl.cmd[idx] &= ~flag;
+ break;
+ }
+
+ case GL_SPOT_EXPONENT:
+ RADEON_STATECHANGE(rmesa, lit[p]);
+ fcmd[LIT_SPOT_EXPONENT] = params[0];
+ break;
+
+ case GL_SPOT_CUTOFF: {
+ GLuint flag = (p&1) ? RADEON_LIGHT_1_IS_SPOT : RADEON_LIGHT_0_IS_SPOT;
+ GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
+
+ RADEON_STATECHANGE(rmesa, lit[p]);
+ fcmd[LIT_SPOT_CUTOFF] = l->_CosCutoff;
+
+ RADEON_STATECHANGE(rmesa, tcl);
+ if (l->SpotCutoff != 180.0F)
+ rmesa->hw.tcl.cmd[idx] |= flag;
+ else
+ rmesa->hw.tcl.cmd[idx] &= ~flag;
+ break;
+ }
+
+ case GL_CONSTANT_ATTENUATION:
+ RADEON_STATECHANGE(rmesa, lit[p]);
+ fcmd[LIT_ATTEN_CONST] = params[0];
+ break;
+ case GL_LINEAR_ATTENUATION:
+ RADEON_STATECHANGE(rmesa, lit[p]);
+ fcmd[LIT_ATTEN_LINEAR] = params[0];
+ break;
+ case GL_QUADRATIC_ATTENUATION:
+ RADEON_STATECHANGE(rmesa, lit[p]);
+ fcmd[LIT_ATTEN_QUADRATIC] = params[0];
+ break;
+ default:
+ return;
+ }
+
+}
+
+
+
+
+void radeonLightModelfv( GLcontext *ctx, GLenum pname,
+ const GLfloat *param )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ switch (pname) {
+ case GL_LIGHT_MODEL_AMBIENT:
+ update_global_ambient( ctx );
+ break;
+
+ case GL_LIGHT_MODEL_LOCAL_VIEWER:
+ RADEON_STATECHANGE( rmesa, tcl );
+ if (ctx->Light.Model.LocalViewer)
+ rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LOCAL_VIEWER;
+ else
+ rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_LOCAL_VIEWER;
+ break;
+
+ case GL_LIGHT_MODEL_TWO_SIDE:
+ RADEON_STATECHANGE( rmesa, tcl );
+ if (ctx->Light.Model.TwoSide)
+ rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_LIGHT_TWOSIDE;
+ else
+ rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_LIGHT_TWOSIDE;
+
+ check_twoside_fallback( ctx );
+
+#if _HAVE_SWTNL
+ if (rmesa->TclFallback) {
+ radeonChooseRenderState( ctx );
+ radeonChooseVertexState( ctx );
+ }
+#endif
+ break;
+
+ case GL_LIGHT_MODEL_COLOR_CONTROL:
+ radeonUpdateSpecular(ctx);
+
+ RADEON_STATECHANGE( rmesa, tcl );
+ if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
+ rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &=
+ ~RADEON_DIFFUSE_SPECULAR_COMBINE;
+ else
+ rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |=
+ RADEON_DIFFUSE_SPECULAR_COMBINE;
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+/* =============================================================
+ * Fog
+ */
+
+
+static void radeonFogfv( GLcontext *ctx, GLenum pname, const GLfloat *param )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ union { int i; float f; } c, d;
+ GLchan col[4];
+
+ c.i = rmesa->hw.fog.cmd[FOG_C];
+ d.i = rmesa->hw.fog.cmd[FOG_D];
+
+ switch (pname) {
+ case GL_FOG_MODE:
+ if (!ctx->Fog.Enabled)
+ return;
+ RADEON_STATECHANGE(rmesa, tcl);
+ rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_TCL_FOG_MASK;
+ switch (ctx->Fog.Mode) {
+ case GL_LINEAR:
+ rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_LINEAR;
+ if (ctx->Fog.Start == ctx->Fog.End) {
+ c.f = 1.0F;
+ d.f = 1.0F;
+ }
+ else {
+ c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start);
+ d.f = 1.0/(ctx->Fog.End-ctx->Fog.Start);
+ }
+ break;
+ case GL_EXP:
+ rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_EXP;
+ c.f = 0.0;
+ d.f = ctx->Fog.Density;
+ break;
+ case GL_EXP2:
+ rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_EXP2;
+ c.f = 0.0;
+ d.f = -(ctx->Fog.Density * ctx->Fog.Density);
+ break;
+ default:
+ return;
+ }
+ break;
+ case GL_FOG_DENSITY:
+ switch (ctx->Fog.Mode) {
+ case GL_EXP:
+ c.f = 0.0;
+ d.f = ctx->Fog.Density;
+ break;
+ case GL_EXP2:
+ c.f = 0.0;
+ d.f = -(ctx->Fog.Density * ctx->Fog.Density);
+ break;
+ default:
+ break;
+ }
+ break;
+ case GL_FOG_START:
+ case GL_FOG_END:
+ if (ctx->Fog.Mode == GL_LINEAR) {
+ if (ctx->Fog.Start == ctx->Fog.End) {
+ c.f = 1.0F;
+ d.f = 1.0F;
+ } else {
+ c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start);
+ d.f = 1.0/(ctx->Fog.End-ctx->Fog.Start);
+ }
+ }
+ break;
+ case GL_FOG_COLOR:
+ RADEON_STATECHANGE( rmesa, ctx );
+ UNCLAMPED_FLOAT_TO_RGB_CHAN( col, ctx->Fog.Color );
+ rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] =
+ radeonPackColor( 4, col[0], col[1], col[2], 0 );
+ break;
+ case GL_FOG_COORDINATE_SOURCE_EXT:
+ /* What to do?
+ */
+ break;
+ default:
+ return;
+ }
+
+ if (c.i != rmesa->hw.fog.cmd[FOG_C] || d.i != rmesa->hw.fog.cmd[FOG_D]) {
+ RADEON_STATECHANGE( rmesa, fog );
+ rmesa->hw.fog.cmd[FOG_C] = c.i;
+ rmesa->hw.fog.cmd[FOG_D] = d.i;
+ }
+}
+
+/* Examine lighting and texture state to determine if separate specular
+ * should be enabled.
+ */
+void radeonUpdateSpecular( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLuint p = rmesa->hw.ctx.cmd[CTX_PP_CNTL];
+
+ if ( ctx->_TriangleCaps & DD_SEPARATE_SPECULAR ) {
+ p |= RADEON_SPECULAR_ENABLE;
+ } else {
+ p &= ~RADEON_SPECULAR_ENABLE;
+ }
+
+ if ( rmesa->hw.ctx.cmd[CTX_PP_CNTL] != p ) {
+ RADEON_STATECHANGE( rmesa, ctx );
+ rmesa->hw.ctx.cmd[CTX_PP_CNTL] = p;
+ }
+
+ /* Bizzare: have to leave lighting enabled to get fog.
+ */
+ RADEON_STATECHANGE( rmesa, tcl );
+ if ((ctx->Light.Enabled &&
+ ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) {
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_SPECULAR;
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_DIFFUSE;
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC;
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE;
+ rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE;
+ }
+ else if (ctx->Fog.Enabled) {
+ if (ctx->Light.Enabled) {
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_SPECULAR;
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_DIFFUSE;
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC;
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE;
+ rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE;
+ } else {
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_SPECULAR;
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_DIFFUSE;
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC;
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE;
+ rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE;
+ }
+ }
+ else if (ctx->Light.Enabled) {
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_SPECULAR;
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_DIFFUSE;
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~RADEON_TCL_VTX_PK_SPEC;
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE;
+ rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE;
+ } else if (ctx->Fog.ColorSumEnabled ) {
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_SPECULAR;
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_DIFFUSE;
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC;
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE;
+ rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_LIGHTING_ENABLE;
+ } else {
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_SPECULAR;
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_DIFFUSE;
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~RADEON_TCL_VTX_PK_SPEC;
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE;
+ rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_LIGHTING_ENABLE;
+ }
+
+#if _HAVE_SWTNL
+ /* Update vertex/render formats
+ */
+ if (rmesa->TclFallback) {
+ radeonChooseRenderState( ctx );
+ radeonChooseVertexState( ctx );
+ }
+#endif
+}
+
+
+
+static void radeonLightingSpaceChange( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLboolean tmp;
+ RADEON_STATECHANGE( rmesa, tcl );
+
+ if (RADEON_DEBUG & DEBUG_STATE)
+ fprintf(stderr, "%s %d\n", __FUNCTION__, ctx->_NeedEyeCoords);
+
+ if (ctx->_NeedEyeCoords)
+ tmp = ctx->Transform.RescaleNormals;
+ else
+ tmp = !ctx->Transform.RescaleNormals;
+
+ if ( tmp ) {
+ rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_RESCALE_NORMALS;
+ } else {
+ rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_RESCALE_NORMALS;
+ }
+}
+
+void radeonInitLightStateFuncs( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ int i;
+
+ ctx->Driver.LightModelfv = radeonLightModelfv;
+ ctx->Driver.Lightfv = radeonLightfv;
+ ctx->Driver.Fogfv = radeonFogfv;
+ ctx->Driver.LightingSpaceChange = radeonLightingSpaceChange;
+
+ for (i = 0 ; i < 8; i++) {
+ struct gl_light *l = &ctx->Light.Light[i];
+ GLenum p = GL_LIGHT0 + i;
+ *(float *)&(rmesa->hw.lit[i].cmd[LIT_RANGE_CUTOFF]) = FLT_MAX;
+
+ ctx->Driver.Lightfv( ctx, p, GL_AMBIENT, l->Ambient );
+ ctx->Driver.Lightfv( ctx, p, GL_DIFFUSE, l->Diffuse );
+ ctx->Driver.Lightfv( ctx, p, GL_SPECULAR, l->Specular );
+ ctx->Driver.Lightfv( ctx, p, GL_POSITION, 0 );
+ ctx->Driver.Lightfv( ctx, p, GL_SPOT_DIRECTION, 0 );
+ ctx->Driver.Lightfv( ctx, p, GL_SPOT_EXPONENT, &l->SpotExponent );
+ ctx->Driver.Lightfv( ctx, p, GL_SPOT_CUTOFF, &l->SpotCutoff );
+ ctx->Driver.Lightfv( ctx, p, GL_CONSTANT_ATTENUATION,
+ &l->ConstantAttenuation );
+ ctx->Driver.Lightfv( ctx, p, GL_LINEAR_ATTENUATION,
+ &l->LinearAttenuation );
+ ctx->Driver.Lightfv( ctx, p, GL_QUADRATIC_ATTENUATION,
+ &l->QuadraticAttenuation );
+ }
+
+ ctx->Driver.LightModelfv( ctx, GL_LIGHT_MODEL_AMBIENT,
+ ctx->Light.Model.Ambient );
+
+ ctx->Driver.Fogfv( ctx, GL_FOG_MODE, 0 );
+ ctx->Driver.Fogfv( ctx, GL_FOG_DENSITY, &ctx->Fog.Density );
+ ctx->Driver.Fogfv( ctx, GL_FOG_START, &ctx->Fog.Start );
+ ctx->Driver.Fogfv( ctx, GL_FOG_END, &ctx->Fog.End );
+ ctx->Driver.Fogfv( ctx, GL_FOG_COLOR, ctx->Fog.Color );
+ ctx->Driver.Fogfv( ctx, GL_FOG_COORDINATE_SOURCE_EXT, 0 );
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_lock.c b/src/mesa/drivers/dri/radeon/radeon_lock.c
new file mode 100644
index 0000000000..96a4f9d112
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_lock.c
@@ -0,0 +1,128 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_lock.c,v 1.5 2002/10/30 12:51:55 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 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 THE COPYRIGHT OWNER(S) 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:
+ * Kevin E. Martin <martin@valinux.com>
+ * Gareth Hughes <gareth@valinux.com>
+ */
+
+#include "glheader.h"
+#include "radeon_context.h"
+#include "radeon_lock.h"
+#include "radeon_tex.h"
+#include "radeon_state.h"
+#include "radeon_ioctl.h"
+
+#if DEBUG_LOCKING
+char *prevLockFile = NULL;
+int prevLockLine = 0;
+#endif
+
+/* Turn on/off page flipping according to the flags in the sarea:
+ */
+static void
+radeonUpdatePageFlipping( radeonContextPtr rmesa )
+{
+ int use_back;
+
+ if (rmesa->dri.drmMinor < 3)
+ return;
+
+ rmesa->doPageFlip = rmesa->sarea->pfAllowPageFlip;
+
+ use_back = (rmesa->glCtx->Color._DrawDestMask == BACK_LEFT_BIT);
+ use_back ^= (rmesa->sarea->pfCurrentPage == 1);
+
+ if ( RADEON_DEBUG & DEBUG_VERBOSE )
+ fprintf(stderr, "%s allow %d current %d\n", __FUNCTION__,
+ rmesa->doPageFlip,
+ rmesa->sarea->pfCurrentPage );
+
+ if ( use_back ) {
+ rmesa->state.color.drawOffset = rmesa->radeonScreen->backOffset;
+ rmesa->state.color.drawPitch = rmesa->radeonScreen->backPitch;
+ } else {
+ rmesa->state.color.drawOffset = rmesa->radeonScreen->frontOffset;
+ rmesa->state.color.drawPitch = rmesa->radeonScreen->frontPitch;
+ }
+
+ RADEON_STATECHANGE( rmesa, ctx );
+ rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = rmesa->state.color.drawOffset;
+ rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = rmesa->state.color.drawPitch;
+}
+
+
+
+/* Update the hardware state. This is called if another context has
+ * grabbed the hardware lock, which includes the X server. This
+ * function also updates the driver's window state after the X server
+ * moves, resizes or restacks a window -- the change will be reflected
+ * in the drawable position and clip rects. Since the X server grabs
+ * the hardware lock when it changes the window state, this routine will
+ * automatically be called after such a change.
+ */
+void radeonGetLock( radeonContextPtr rmesa, GLuint flags )
+{
+ __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
+ __DRIscreenPrivate *sPriv = rmesa->dri.screen;
+ RADEONSAREAPrivPtr sarea = rmesa->sarea;
+
+ drmGetLock( rmesa->dri.fd, rmesa->dri.hwContext, flags );
+
+ /* The window might have moved, so we might need to get new clip
+ * rects.
+ *
+ * NOTE: This releases and regrabs the hw lock to allow the X server
+ * to respond to the DRI protocol request for new drawable info.
+ * Since the hardware state depends on having the latest drawable
+ * clip rects, all state checking must be done _after_ this call.
+ */
+ DRI_VALIDATE_DRAWABLE_INFO( sPriv, dPriv );
+
+ if ( rmesa->lastStamp != dPriv->lastStamp ) {
+ radeonUpdatePageFlipping( rmesa );
+ if (rmesa->glCtx->Color._DrawDestMask == BACK_LEFT_BIT)
+ radeonSetCliprects( rmesa, GL_BACK_LEFT );
+ else
+ radeonSetCliprects( rmesa, GL_FRONT_LEFT );
+ radeonUpdateViewportOffset( rmesa->glCtx );
+ rmesa->lastStamp = dPriv->lastStamp;
+ }
+
+ if ( sarea->ctxOwner != rmesa->dri.hwContext ) {
+ int i;
+ sarea->ctxOwner = rmesa->dri.hwContext;
+
+ for ( i = 0 ; i < rmesa->nr_heaps ; i++ ) {
+ DRI_AGE_TEXTURES( rmesa->texture_heaps[ i ] );
+ }
+ }
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_lock.h b/src/mesa/drivers/dri/radeon/radeon_lock.h
new file mode 100644
index 0000000000..783db7e92a
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_lock.h
@@ -0,0 +1,113 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_lock.h,v 1.3 2002/10/30 12:51:55 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 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 THE COPYRIGHT OWNER(S) 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:
+ * Kevin E. Martin <martin@valinux.com>
+ * Gareth Hughes <gareth@valinux.com>
+ */
+
+#ifndef __RADEON_LOCK_H__
+#define __RADEON_LOCK_H__
+
+#ifdef GLX_DIRECT_RENDERING
+
+extern void radeonGetLock( radeonContextPtr rmesa, GLuint flags );
+
+/* Turn DEBUG_LOCKING on to find locking conflicts.
+ */
+#define DEBUG_LOCKING 0
+
+#if DEBUG_LOCKING
+extern char *prevLockFile;
+extern int prevLockLine;
+
+#define DEBUG_LOCK() \
+ do { \
+ prevLockFile = (__FILE__); \
+ prevLockLine = (__LINE__); \
+ } while (0)
+
+#define DEBUG_RESET() \
+ do { \
+ prevLockFile = 0; \
+ prevLockLine = 0; \
+ } while (0)
+
+#define DEBUG_CHECK_LOCK() \
+ do { \
+ if ( prevLockFile ) { \
+ fprintf( stderr, \
+ "LOCK SET!\n\tPrevious %s:%d\n\tCurrent: %s:%d\n", \
+ prevLockFile, prevLockLine, __FILE__, __LINE__ ); \
+ exit( 1 ); \
+ } \
+ } while (0)
+
+#else
+
+#define DEBUG_LOCK()
+#define DEBUG_RESET()
+#define DEBUG_CHECK_LOCK()
+
+#endif
+
+/*
+ * !!! We may want to separate locks from locks with validation. This
+ * could be used to improve performance for those things commands that
+ * do not do any drawing !!!
+ */
+
+
+/* Lock the hardware and validate our state.
+ */
+#define LOCK_HARDWARE( rmesa ) \
+ do { \
+ char __ret = 0; \
+ DEBUG_CHECK_LOCK(); \
+ DRM_CAS( rmesa->dri.hwLock, rmesa->dri.hwContext, \
+ (DRM_LOCK_HELD | rmesa->dri.hwContext), __ret ); \
+ if ( __ret ) \
+ radeonGetLock( rmesa, 0 ); \
+ DEBUG_LOCK(); \
+ } while (0)
+
+/* Unlock the hardware.
+ */
+#define UNLOCK_HARDWARE( rmesa ) \
+ do { \
+ DRM_UNLOCK( rmesa->dri.fd, \
+ rmesa->dri.hwLock, \
+ rmesa->dri.hwContext ); \
+ DEBUG_RESET(); \
+ } while (0)
+
+#endif
+#endif /* __RADEON_LOCK_H__ */
diff --git a/src/mesa/drivers/dri/radeon/radeon_maos.c b/src/mesa/drivers/dri/radeon/radeon_maos.c
new file mode 100644
index 0000000000..c62edd715c
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_maos.c
@@ -0,0 +1,12 @@
+
+
+/* If using new packets, can choose either verts or arrays.
+ * Otherwise, must use verts.
+ */
+#include "radeon_context.h"
+#define RADEON_MAOS_VERTS 1
+#if (RADEON_MAOS_VERTS) || (RADEON_OLD_PACKETS)
+#include "radeon_maos_verts.c"
+#else
+#include "radeon_maos_arrays.c"
+#endif
diff --git a/src/mesa/drivers/dri/radeon/radeon_maos.h b/src/mesa/drivers/dri/radeon/radeon_maos.h
new file mode 100644
index 0000000000..7e2bd643d3
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_maos.h
@@ -0,0 +1,47 @@
+/* $XFree86$ */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+ Tungsten Grahpics Inc., Austin, Texas.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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 __RADEON_MAOS_H__
+#define __RADEON_MAOS_H__
+
+#ifdef GLX_DIRECT_RENDERING
+
+#include "radeon_context.h"
+
+extern void radeonEmitArrays( GLcontext *ctx, GLuint inputs );
+extern void radeonReleaseArrays( GLcontext *ctx, GLuint newinputs );
+
+#endif
+#endif
diff --git a/src/mesa/drivers/dri/radeon/radeon_maos_arrays.c b/src/mesa/drivers/dri/radeon/radeon_maos_arrays.c
new file mode 100644
index 0000000000..cec05a89d7
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_maos_arrays.c
@@ -0,0 +1,591 @@
+/* $XFree86$ */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+ Tungsten Graphics Inc., Cedar Park, Texas.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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 "glheader.h"
+#include "imports.h"
+#include "mtypes.h"
+#include "mmath.h"
+#include "macros.h"
+
+#include "swrast_setup/swrast_setup.h"
+#include "math/m_translate.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_imm_debug.h"
+
+#include "radeon_context.h"
+#include "radeon_ioctl.h"
+#include "radeon_state.h"
+#include "radeon_swtcl.h"
+#include "radeon_maos.h"
+
+/* Usage:
+ * - from radeon_tcl_render
+ * - call radeonEmitArrays to ensure uptodate arrays in dma
+ * - emit primitives (new type?) which reference the data
+ * -- need to use elts for lineloop, quads, quadstrip/flat
+ * -- other primitives are all well-formed (need tristrip-1,fake-poly)
+ *
+ */
+static void emit_ubyte_rgba3( GLcontext *ctx,
+ struct radeon_dma_region *rvb,
+ char *data,
+ int stride,
+ int count )
+{
+ int i;
+ radeon_color_t *out = (radeon_color_t *)(rvb->start + rvb->address);
+
+ if (RADEON_DEBUG & DEBUG_VERTS)
+ fprintf(stderr, "%s count %d stride %d out %p\n",
+ __FUNCTION__, count, stride, out);
+
+ for (i = 0; i < count; i++) {
+ out->red = *data;
+ out->green = *(data+1);
+ out->blue = *(data+2);
+ out->alpha = 0xFF;
+ out++;
+ data += stride;
+ }
+}
+
+
+#if defined(USE_X86_ASM)
+#define COPY_DWORDS( dst, src, nr ) \
+do { \
+ int __tmp; \
+ __asm__ __volatile__( "rep ; movsl" \
+ : "=%c" (__tmp), "=D" (dst), "=S" (__tmp) \
+ : "0" (nr), \
+ "D" ((long)dst), \
+ "S" ((long)src) ); \
+} while (0)
+#else
+#define COPY_DWORDS( dst, src, nr ) \
+do { \
+ int j; \
+ for ( j = 0 ; j < nr ; j++ ) \
+ dst[j] = ((int *)src)[j]; \
+ dst += nr; \
+} while (0)
+#endif
+
+
+
+static void emit_ubyte_rgba4( GLcontext *ctx,
+ struct radeon_dma_region *rvb,
+ char *data,
+ int stride,
+ int count )
+{
+ int i;
+ int *out = (int *)(rvb->address + rvb->start);
+
+ if (RADEON_DEBUG & DEBUG_VERTS)
+ fprintf(stderr, "%s count %d stride %d\n",
+ __FUNCTION__, count, stride);
+
+ if (stride == 4)
+ COPY_DWORDS( out, data, count );
+ else
+ for (i = 0; i < count; i++) {
+ *out++ = LE32_TO_CPU(*(int *)data);
+ data += stride;
+ }
+}
+
+
+static void emit_ubyte_rgba( GLcontext *ctx,
+ struct radeon_dma_region *rvb,
+ char *data,
+ int size,
+ int stride,
+ int count )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ if (RADEON_DEBUG & DEBUG_VERTS)
+ fprintf(stderr, "%s %d/%d\n", __FUNCTION__, count, size);
+
+ assert (!rvb->buf);
+
+ if (stride == 0) {
+ radeonAllocDmaRegion( rmesa, rvb, 4, 4 );
+ count = 1;
+ rvb->aos_start = GET_START(rvb);
+ rvb->aos_stride = 0;
+ rvb->aos_size = 1;
+ }
+ else {
+ radeonAllocDmaRegion( rmesa, rvb, 4 * count, 4 ); /* alignment? */
+ rvb->aos_start = GET_START(rvb);
+ rvb->aos_stride = 1;
+ rvb->aos_size = 1;
+ }
+
+ /* Emit the data
+ */
+ switch (size) {
+ case 3:
+ emit_ubyte_rgba3( ctx, rvb, data, stride, count );
+ break;
+ case 4:
+ emit_ubyte_rgba4( ctx, rvb, data, stride, count );
+ break;
+ default:
+ assert(0);
+ exit(1);
+ break;
+ }
+}
+
+
+
+
+static void emit_vec8( GLcontext *ctx,
+ struct radeon_dma_region *rvb,
+ char *data,
+ int stride,
+ int count )
+{
+ int i;
+ int *out = (int *)(rvb->address + rvb->start);
+
+ if (RADEON_DEBUG & DEBUG_VERTS)
+ fprintf(stderr, "%s count %d stride %d\n",
+ __FUNCTION__, count, stride);
+
+ if (stride == 8)
+ COPY_DWORDS( out, data, count*2 );
+ else
+ for (i = 0; i < count; i++) {
+ out[0] = *(int *)data;
+ out[1] = *(int *)(data+4);
+ out += 2;
+ data += stride;
+ }
+}
+
+static void emit_vec12( GLcontext *ctx,
+ struct radeon_dma_region *rvb,
+ char *data,
+ int stride,
+ int count )
+{
+ int i;
+ int *out = (int *)(rvb->address + rvb->start);
+
+ if (RADEON_DEBUG & DEBUG_VERTS)
+ fprintf(stderr, "%s count %d stride %d out %p data %p\n",
+ __FUNCTION__, count, stride, out, data);
+
+ if (stride == 12)
+ COPY_DWORDS( out, data, count*3 );
+ else
+ for (i = 0; i < count; i++) {
+ out[0] = *(int *)data;
+ out[1] = *(int *)(data+4);
+ out[2] = *(int *)(data+8);
+ out += 3;
+ data += stride;
+ }
+}
+
+static void emit_vec16( GLcontext *ctx,
+ struct radeon_dma_region *rvb,
+ char *data,
+ int stride,
+ int count )
+{
+ int i;
+ int *out = (int *)(rvb->address + rvb->start);
+
+ if (RADEON_DEBUG & DEBUG_VERTS)
+ fprintf(stderr, "%s count %d stride %d\n",
+ __FUNCTION__, count, stride);
+
+ if (stride == 16)
+ COPY_DWORDS( out, data, count*4 );
+ else
+ for (i = 0; i < count; i++) {
+ out[0] = *(int *)data;
+ out[1] = *(int *)(data+4);
+ out[2] = *(int *)(data+8);
+ out[3] = *(int *)(data+12);
+ out += 4;
+ data += stride;
+ }
+}
+
+
+static void emit_vector( GLcontext *ctx,
+ struct radeon_dma_region *rvb,
+ char *data,
+ int size,
+ int stride,
+ int count )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ if (RADEON_DEBUG & DEBUG_VERTS)
+ fprintf(stderr, "%s count %d size %d stride %d\n",
+ __FUNCTION__, count, size, stride);
+
+ assert (!rvb->buf);
+
+ if (stride == 0) {
+ radeonAllocDmaRegion( rmesa, rvb, size * 4, 4 );
+ count = 1;
+ rvb->aos_start = GET_START(rvb);
+ rvb->aos_stride = 0;
+ rvb->aos_size = size;
+ }
+ else {
+ radeonAllocDmaRegion( rmesa, rvb, size * count * 4, 4 ); /* alignment? */
+ rvb->aos_start = GET_START(rvb);
+ rvb->aos_stride = size;
+ rvb->aos_size = size;
+ }
+
+ /* Emit the data
+ */
+ switch (size) {
+ case 2:
+ emit_vec8( ctx, rvb, data, stride, count );
+ break;
+ case 3:
+ emit_vec12( ctx, rvb, data, stride, count );
+ break;
+ case 4:
+ emit_vec16( ctx, rvb, data, stride, count );
+ break;
+ default:
+ assert(0);
+ exit(1);
+ break;
+ }
+
+}
+
+
+
+static void emit_s0_vec( GLcontext *ctx,
+ struct radeon_dma_region *rvb,
+ char *data,
+ int stride,
+ int count )
+{
+ int i;
+ int *out = (int *)(rvb->address + rvb->start);
+
+ if (RADEON_DEBUG & DEBUG_VERTS)
+ fprintf(stderr, "%s count %d stride %d\n",
+ __FUNCTION__, count, stride);
+
+ for (i = 0; i < count; i++) {
+ out[0] = *(int *)data;
+ out[1] = 0;
+ out += 2;
+ data += stride;
+ }
+}
+
+static void emit_stq_vec( GLcontext *ctx,
+ struct radeon_dma_region *rvb,
+ char *data,
+ int stride,
+ int count )
+{
+ int i;
+ int *out = (int *)(rvb->address + rvb->start);
+
+ if (RADEON_DEBUG & DEBUG_VERTS)
+ fprintf(stderr, "%s count %d stride %d\n",
+ __FUNCTION__, count, stride);
+
+ for (i = 0; i < count; i++) {
+ out[0] = *(int *)data;
+ out[1] = *(int *)(data+4);
+ out[2] = *(int *)(data+12);
+ out += 3;
+ data += stride;
+ }
+}
+
+
+
+
+static void emit_tex_vector( GLcontext *ctx,
+ struct radeon_dma_region *rvb,
+ char *data,
+ int size,
+ int stride,
+ int count )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ int emitsize;
+
+ if (RADEON_DEBUG & DEBUG_VERTS)
+ fprintf(stderr, "%s %d/%d\n", __FUNCTION__, count, size);
+
+ assert (!rvb->buf);
+
+ switch (size) {
+ case 4: emitsize = 3; break;
+ default: emitsize = 2; break;
+ }
+
+
+ if (stride == 0) {
+ radeonAllocDmaRegion( rmesa, rvb, 4 * emitsize, 4 );
+ count = 1;
+ rvb->aos_start = GET_START(rvb);
+ rvb->aos_stride = 0;
+ rvb->aos_size = emitsize;
+ }
+ else {
+ radeonAllocDmaRegion( rmesa, rvb, 4 * emitsize * count, 4 );
+ rvb->aos_start = GET_START(rvb);
+ rvb->aos_stride = emitsize;
+ rvb->aos_size = emitsize;
+ }
+
+
+ /* Emit the data
+ */
+ switch (size) {
+ case 1:
+ emit_s0_vec( ctx, rvb, data, stride, count );
+ break;
+ case 2:
+ emit_vec8( ctx, rvb, data, stride, count );
+ break;
+ case 3:
+ emit_vec8( ctx, rvb, data, stride, count );
+ break;
+ case 4:
+ emit_stq_vec( ctx, rvb, data, stride, count );
+ break;
+ default:
+ assert(0);
+ exit(1);
+ break;
+ }
+}
+
+
+
+
+/* Emit any changed arrays to new agp memory, re-emit a packet to
+ * update the arrays.
+ */
+void radeonEmitArrays( GLcontext *ctx, GLuint inputs )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+ struct vertex_buffer *VB = &TNL_CONTEXT( ctx )->vb;
+ struct radeon_dma_region **component = rmesa->tcl.aos_components;
+ GLuint nr = 0;
+ GLuint vfmt = 0;
+ GLuint count = VB->Count;
+ GLuint vtx;
+
+ if (RADEON_DEBUG & DEBUG_VERTS)
+ _tnl_print_vert_flags( __FUNCTION__, inputs );
+
+ if (1) {
+ if (!rmesa->tcl.obj.buf)
+ emit_vector( ctx,
+ &rmesa->tcl.obj,
+ (char *)VB->ObjPtr->data,
+ VB->ObjPtr->size,
+ VB->ObjPtr->stride,
+ count);
+
+ switch( VB->ObjPtr->size ) {
+ case 4: vfmt |= RADEON_CP_VC_FRMT_W0;
+ case 3: vfmt |= RADEON_CP_VC_FRMT_Z;
+ case 2: vfmt |= RADEON_CP_VC_FRMT_XY;
+ default:
+ }
+ component[nr++] = &rmesa->tcl.obj;
+ }
+
+
+ if (inputs & VERT_BIT_NORMAL) {
+ if (!rmesa->tcl.norm.buf)
+ emit_vector( ctx,
+ &(rmesa->tcl.norm),
+ (char *)VB->NormalPtr->data,
+ 3,
+ VB->NormalPtr->stride,
+ count);
+
+ vfmt |= RADEON_CP_VC_FRMT_N0;
+ component[nr++] = &rmesa->tcl.norm;
+ }
+
+ if (inputs & VERT_BIT_COLOR0) {
+ if (VB->ColorPtr[0]->Type == GL_UNSIGNED_BYTE) {
+ if (!rmesa->tcl.rgba.buf)
+ emit_ubyte_rgba( ctx,
+ &rmesa->tcl.rgba,
+ (char *)VB->ColorPtr[0]->Ptr,
+ VB->ColorPtr[0]->Size,
+ VB->ColorPtr[0]->StrideB,
+ count);
+
+ vfmt |= RADEON_CP_VC_FRMT_PKCOLOR;
+ }
+ else {
+ int emitsize;
+
+ if (VB->ColorPtr[0]->Size == 4 &&
+ (VB->ColorPtr[0]->StrideB != 0 ||
+ ((GLfloat *)VB->ColorPtr[0]->Ptr)[3] != 1.0)) {
+ vfmt |= RADEON_CP_VC_FRMT_FPCOLOR | RADEON_CP_VC_FRMT_FPALPHA;
+ emitsize = 4;
+ }
+ else {
+ vfmt |= RADEON_CP_VC_FRMT_FPCOLOR;
+ emitsize = 3;
+ }
+
+ if (!rmesa->tcl.rgba.buf)
+ emit_vector( ctx,
+ &(rmesa->tcl.rgba),
+ (char *)VB->ColorPtr[0]->Ptr,
+ emitsize,
+ VB->ColorPtr[0]->StrideB,
+ count);
+ }
+
+ component[nr++] = &rmesa->tcl.rgba;
+ }
+
+
+ if (inputs & VERT_BIT_COLOR1) {
+ if (!rmesa->tcl.spec.buf) {
+ if (VB->SecondaryColorPtr[0]->Type != GL_UNSIGNED_BYTE)
+ radeon_import_float_spec_colors( ctx );
+
+ emit_ubyte_rgba( ctx,
+ &rmesa->tcl.spec,
+ (char *)VB->SecondaryColorPtr[0]->Ptr,
+ 3,
+ VB->SecondaryColorPtr[0]->StrideB,
+ count);
+ }
+
+ vfmt |= RADEON_CP_VC_FRMT_PKSPEC;
+ component[nr++] = &rmesa->tcl.spec;
+ }
+
+ vtx = (rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &
+ ~(RADEON_TCL_VTX_Q0|RADEON_TCL_VTX_Q1));
+
+ if (inputs & VERT_BIT_TEX0) {
+ if (!rmesa->tcl.tex[0].buf)
+ emit_tex_vector( ctx,
+ &(rmesa->tcl.tex[0]),
+ (char *)VB->TexCoordPtr[0]->data,
+ VB->TexCoordPtr[0]->size,
+ VB->TexCoordPtr[0]->stride,
+ count );
+
+ switch( VB->TexCoordPtr[0]->size ) {
+ case 4:
+ vtx |= RADEON_TCL_VTX_Q0;
+ vfmt |= RADEON_CP_VC_FRMT_Q0;
+ default:
+ vfmt |= RADEON_CP_VC_FRMT_ST0;
+ }
+ component[nr++] = &rmesa->tcl.tex[0];
+ }
+
+ if (inputs & VERT_BIT_TEX1) {
+ if (!rmesa->tcl.tex[1].buf)
+ emit_tex_vector( ctx,
+ &(rmesa->tcl.tex[1]),
+ (char *)VB->TexCoordPtr[1]->data,
+ VB->TexCoordPtr[1]->size,
+ VB->TexCoordPtr[1]->stride,
+ count );
+
+ switch( VB->TexCoordPtr[1]->size ) {
+ case 4:
+ vtx |= RADEON_TCL_VTX_Q1;
+ vfmt |= RADEON_CP_VC_FRMT_Q1;
+ default:
+ vfmt |= RADEON_CP_VC_FRMT_ST1;
+ }
+ component[nr++] = &rmesa->tcl.tex[1];
+ }
+
+ if (vtx != rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT]) {
+ RADEON_STATECHANGE( rmesa, tcl );
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] = vtx;
+ }
+
+ rmesa->tcl.nr_aos_components = nr;
+ rmesa->tcl.vertex_format = vfmt;
+}
+
+
+void radeonReleaseArrays( GLcontext *ctx, GLuint newinputs )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+
+ if (RADEON_DEBUG & DEBUG_VERTS)
+ _tnl_print_vert_flags( __FUNCTION__, newinputs );
+
+ if (newinputs & VERT_BIT_POS)
+ radeonReleaseDmaRegion( rmesa, &rmesa->tcl.obj, __FUNCTION__ );
+
+ if (newinputs & VERT_BIT_NORMAL)
+ radeonReleaseDmaRegion( rmesa, &rmesa->tcl.norm, __FUNCTION__ );
+
+ if (newinputs & VERT_BIT_COLOR0)
+ radeonReleaseDmaRegion( rmesa, &rmesa->tcl.rgba, __FUNCTION__ );
+
+ if (newinputs & VERT_BIT_COLOR1)
+ radeonReleaseDmaRegion( rmesa, &rmesa->tcl.spec, __FUNCTION__ );
+
+ if (newinputs & VERT_BIT_TEX0)
+ radeonReleaseDmaRegion( rmesa, &rmesa->tcl.tex[0], __FUNCTION__ );
+
+ if (newinputs & VERT_BIT_TEX1)
+ radeonReleaseDmaRegion( rmesa, &rmesa->tcl.tex[1], __FUNCTION__ );
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_maos_vbtmp.h b/src/mesa/drivers/dri/radeon/radeon_maos_vbtmp.h
new file mode 100644
index 0000000000..b379bad985
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_maos_vbtmp.h
@@ -0,0 +1,368 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 4.1
+ *
+ * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef LOCALVARS
+#define LOCALVARS
+#endif
+
+#undef TCL_DEBUG
+#ifndef TCL_DEBUG
+#define TCL_DEBUG 0
+#endif
+
+static void TAG(emit)( GLcontext *ctx,
+ GLuint start, GLuint end,
+ void *dest )
+{
+ LOCALVARS
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ GLuint (*tc0)[4], (*tc1)[4], (*tc2)[4];
+ GLfloat (*fog)[4];
+ GLuint (*norm)[4];
+ GLubyte (*col)[4], (*spec)[4];
+ GLuint tc0_stride, tc1_stride, col_stride, spec_stride, fog_stride;
+ GLuint tc2_stride, norm_stride;
+ GLuint (*coord)[4];
+ GLuint coord_stride; /* object coordinates */
+ GLubyte dummy[4];
+ int i;
+
+ union emit_union *v = (union emit_union *)dest;
+
+ if (RADEON_DEBUG & DEBUG_VERTS)
+ fprintf(stderr, "%s\n", __FUNCTION__);
+
+ /* The vertex code expects Obj to be clean to element 3. To fix
+ * this, add more vertex code (for obj-2, obj-3) or preferably move
+ * to maos.
+ */
+ if (VB->ObjPtr->size < 3) {
+ if (VB->ObjPtr->flags & VEC_NOT_WRITEABLE) {
+ VB->import_data( ctx, VERT_BIT_POS, VEC_NOT_WRITEABLE );
+ }
+ _mesa_vector4f_clean_elem( VB->ObjPtr, VB->Count, 2 );
+ }
+
+ if (DO_W && VB->ObjPtr->size < 4) {
+ if (VB->ObjPtr->flags & VEC_NOT_WRITEABLE) {
+ VB->import_data( ctx, VERT_BIT_POS, VEC_NOT_WRITEABLE );
+ }
+ _mesa_vector4f_clean_elem( VB->ObjPtr, VB->Count, 3 );
+ }
+
+ coord = (GLuint (*)[4])VB->ObjPtr->data;
+ coord_stride = VB->ObjPtr->stride;
+
+ if (DO_TEX2) {
+ const GLuint t2 = GET_TEXSOURCE(2);
+ tc2 = (GLuint (*)[4])VB->TexCoordPtr[t2]->data;
+ tc2_stride = VB->TexCoordPtr[t2]->stride;
+ if (DO_PTEX && VB->TexCoordPtr[t2]->size < 4) {
+ if (VB->TexCoordPtr[t2]->flags & VEC_NOT_WRITEABLE) {
+ VB->import_data( ctx, VERT_BIT_TEX2, VEC_NOT_WRITEABLE );
+ }
+ _mesa_vector4f_clean_elem( VB->TexCoordPtr[t2], VB->Count, 3 );
+ }
+ }
+
+ if (DO_TEX1) {
+ if (VB->TexCoordPtr[1]) {
+ const GLuint t1 = GET_TEXSOURCE(1);
+ tc1 = (GLuint (*)[4])VB->TexCoordPtr[t1]->data;
+ tc1_stride = VB->TexCoordPtr[t1]->stride;
+ if (DO_PTEX && VB->TexCoordPtr[t1]->size < 4) {
+ if (VB->TexCoordPtr[t1]->flags & VEC_NOT_WRITEABLE) {
+ VB->import_data( ctx, VERT_BIT_TEX1, VEC_NOT_WRITEABLE );
+ }
+ _mesa_vector4f_clean_elem( VB->TexCoordPtr[t1], VB->Count, 3 );
+ }
+ } else {
+ tc1 = (GLuint (*)[4])&ctx->Current.Attrib[VERT_ATTRIB_TEX1]; /* could be anything, really */
+ tc1_stride = 0;
+ }
+ }
+
+ if (DO_TEX0) {
+ if (VB->TexCoordPtr[0]) {
+ const GLuint t0 = GET_TEXSOURCE(0);
+ tc0_stride = VB->TexCoordPtr[t0]->stride;
+ tc0 = (GLuint (*)[4])VB->TexCoordPtr[t0]->data;
+ if (DO_PTEX && VB->TexCoordPtr[t0]->size < 4) {
+ if (VB->TexCoordPtr[t0]->flags & VEC_NOT_WRITEABLE) {
+ VB->import_data( ctx, VERT_BIT_TEX0, VEC_NOT_WRITEABLE );
+ }
+ _mesa_vector4f_clean_elem( VB->TexCoordPtr[t0], VB->Count, 3 );
+ }
+ } else {
+ tc0 = (GLuint (*)[4])&ctx->Current.Attrib[VERT_ATTRIB_TEX0]; /* could be anything, really */
+ tc0_stride = 0;
+ }
+
+ }
+
+ if (DO_NORM) {
+ if (VB->NormalPtr) {
+ norm_stride = VB->NormalPtr->stride;
+ norm = (GLuint (*)[4])VB->NormalPtr->data;
+ } else {
+ norm_stride = 0;
+ norm = (GLuint (*)[4])&ctx->Current.Attrib[VERT_ATTRIB_NORMAL];
+ }
+ }
+
+ if (DO_RGBA) {
+ if (VB->ColorPtr[0]) {
+ /* This is incorrect when colormaterial is enabled:
+ */
+ if (VB->ColorPtr[0]->Type != GL_UNSIGNED_BYTE) {
+ if (0) fprintf(stderr, "IMPORTING FLOAT COLORS\n");
+ IMPORT_FLOAT_COLORS( ctx );
+ }
+ col = (GLubyte (*)[4])VB->ColorPtr[0]->Ptr;
+ col_stride = VB->ColorPtr[0]->StrideB;
+ } else {
+ col = &dummy; /* any old memory is fine */
+ col_stride = 0;
+ }
+ }
+
+ if (DO_SPEC) {
+ if (VB->SecondaryColorPtr[0]) {
+ if (VB->SecondaryColorPtr[0]->Type != GL_UNSIGNED_BYTE)
+ IMPORT_FLOAT_SPEC_COLORS( ctx );
+ spec = (GLubyte (*)[4])VB->SecondaryColorPtr[0]->Ptr;
+ spec_stride = VB->SecondaryColorPtr[0]->StrideB;
+ } else {
+ spec = &dummy;
+ spec_stride = 0;
+ }
+ }
+
+ if (DO_FOG) {
+ if (VB->FogCoordPtr) {
+ fog = VB->FogCoordPtr->data;
+ fog_stride = VB->FogCoordPtr->stride;
+ } else {
+ fog = (GLfloat (*)[4])&dummy; fog[0][0] = 0.0F;
+ fog_stride = 0;
+ }
+ }
+
+
+ if (VB->importable_data) {
+ if (start) {
+ coord = (GLuint (*)[4])((GLubyte *)coord + start * coord_stride);
+ if (DO_TEX0)
+ tc0 = (GLuint (*)[4])((GLubyte *)tc0 + start * tc0_stride);
+ if (DO_TEX1)
+ tc1 = (GLuint (*)[4])((GLubyte *)tc1 + start * tc1_stride);
+ if (DO_TEX2)
+ tc2 = (GLuint (*)[4])((GLubyte *)tc2 + start * tc2_stride);
+ if (DO_NORM)
+ norm = (GLuint (*)[4])((GLubyte *)norm + start * norm_stride);
+ if (DO_RGBA)
+ STRIDE_4UB(col, start * col_stride);
+ if (DO_SPEC)
+ STRIDE_4UB(spec, start * spec_stride);
+ if (DO_FOG)
+ fog = (GLfloat (*)[4])((GLubyte *)fog + start * fog_stride);
+ }
+
+ for (i=start; i < end; i++) {
+ v[0].ui = coord[0][0];
+ v[1].ui = coord[0][1];
+ v[2].ui = coord[0][2];
+ if (TCL_DEBUG) fprintf(stderr, "%d: %.2f %.2f %.2f ", i, v[0].f, v[1].f, v[2].f);
+ if (DO_W) {
+ v[3].ui = coord[0][3];
+ if (TCL_DEBUG) fprintf(stderr, "%.2f ", v[3].f);
+ v += 4;
+ }
+ else
+ v += 3;
+ coord = (GLuint (*)[4])((GLubyte *)coord + coord_stride);
+
+ if (DO_NORM) {
+ v[0].ui = norm[0][0];
+ v[1].ui = norm[0][1];
+ v[2].ui = norm[0][2];
+ if (TCL_DEBUG) fprintf(stderr, "norm: %.2f %.2f %.2f ", v[0].f, v[1].f, v[2].f);
+ v += 3;
+ norm = (GLuint (*)[4])((GLubyte *)norm + norm_stride);
+ }
+ if (DO_RGBA) {
+ v[0].ui = LE32_TO_CPU(*(GLuint *)&col[0]);
+ STRIDE_4UB(col, col_stride);
+ if (TCL_DEBUG) fprintf(stderr, "%x ", v[0].ui);
+ v++;
+ }
+ if (DO_SPEC || DO_FOG) {
+ if (DO_SPEC) {
+ v[0].specular.red = spec[0][0];
+ v[0].specular.green = spec[0][1];
+ v[0].specular.blue = spec[0][2];
+ STRIDE_4UB(spec, spec_stride);
+ }
+ if (DO_FOG) {
+ v[0].specular.alpha = fog[0][0] * 255.0;
+ fog = (GLfloat (*)[4])((GLubyte *)fog + fog_stride);
+ }
+ if (TCL_DEBUG) fprintf(stderr, "%x ", v[0].ui);
+ v++;
+ }
+ if (DO_TEX0) {
+ v[0].ui = tc0[0][0];
+ v[1].ui = tc0[0][1];
+ if (TCL_DEBUG) fprintf(stderr, "t0: %.2f %.2f ", v[0].f, v[1].f);
+ if (DO_PTEX) {
+ v[2].ui = tc0[0][3];
+ if (TCL_DEBUG) fprintf(stderr, "%.2f ", v[2].f);
+ v += 3;
+ }
+ else
+ v += 2;
+ tc0 = (GLuint (*)[4])((GLubyte *)tc0 + tc0_stride);
+ }
+ if (DO_TEX1) {
+ v[0].ui = tc1[0][0];
+ v[1].ui = tc1[0][1];
+ if (TCL_DEBUG) fprintf(stderr, "t1: %.2f %.2f ", v[0].f, v[1].f);
+ if (DO_PTEX) {
+ v[2].ui = tc1[0][3];
+ if (TCL_DEBUG) fprintf(stderr, "%.2f ", v[2].f);
+ v += 3;
+ }
+ else
+ v += 2;
+ tc1 = (GLuint (*)[4])((GLubyte *)tc1 + tc1_stride);
+ }
+ if (DO_TEX2) {
+ v[0].ui = tc2[0][0];
+ v[1].ui = tc2[0][1];
+ if (DO_PTEX) {
+ v[2].ui = tc2[0][3];
+ v += 3;
+ }
+ else
+ v += 2;
+ tc2 = (GLuint (*)[4])((GLubyte *)tc2 + tc2_stride);
+ }
+ if (TCL_DEBUG) fprintf(stderr, "\n");
+ }
+ } else {
+ for (i=start; i < end; i++) {
+ v[0].ui = coord[i][0];
+ v[1].ui = coord[i][1];
+ v[2].ui = coord[i][2];
+ if (DO_W) {
+ v[3].ui = coord[i][3];
+ v += 4;
+ }
+ else
+ v += 3;
+
+ if (DO_NORM) {
+ v[0].ui = norm[i][0];
+ v[1].ui = norm[i][1];
+ v[2].ui = norm[i][2];
+ v += 3;
+ }
+ if (DO_RGBA) {
+ v[0].ui = LE32_TO_CPU(*(GLuint *)&col[i]);
+ v++;
+ }
+ if (DO_SPEC || DO_FOG) {
+ if (DO_SPEC) {
+ v[0].specular.red = spec[i][0];
+ v[0].specular.green = spec[i][1];
+ v[0].specular.blue = spec[i][2];
+ }
+ if (DO_FOG) {
+ GLfloat *f = (GLfloat *) ((GLubyte *)fog + fog_stride);
+ v[0].specular.alpha = *f * 255.0;
+ }
+ v++;
+ }
+ if (DO_TEX0) {
+ v[0].ui = tc0[i][0];
+ v[1].ui = tc0[i][1];
+ if (DO_PTEX) {
+ v[2].ui = tc0[i][3];
+ v += 3;
+ }
+ else
+ v += 2;
+ }
+ if (DO_TEX1) {
+ v[0].ui = tc1[i][0];
+ v[1].ui = tc1[i][1];
+ if (DO_PTEX) {
+ v[2].ui = tc1[i][3];
+ v += 3;
+ }
+ else
+ v += 2;
+ }
+ if (DO_TEX2) {
+ v[0].ui = tc2[i][0];
+ v[1].ui = tc2[i][1];
+ if (DO_PTEX) {
+ v[2].ui = tc2[i][3];
+ v += 3;
+ }
+ else
+ v += 2;
+ }
+ }
+ }
+}
+
+
+
+static void TAG(init)( void )
+{
+ int sz = 3;
+ if (DO_W) sz++;
+ if (DO_NORM) sz += 3;
+ if (DO_RGBA) sz++;
+ if (DO_SPEC || DO_FOG) sz++;
+ if (DO_TEX0) sz += 2;
+ if (DO_TEX0 && DO_PTEX) sz++;
+ if (DO_TEX1) sz += 2;
+ if (DO_TEX1 && DO_PTEX) sz++;
+ if (DO_TEX2) sz += 2;
+ if (DO_TEX2 && DO_PTEX) sz++;
+
+ setup_tab[IDX].emit = TAG(emit);
+ setup_tab[IDX].vertex_format = IND;
+ setup_tab[IDX].vertex_size = sz;
+}
+
+
+#undef IND
+#undef TAG
+#undef IDX
diff --git a/src/mesa/drivers/dri/radeon/radeon_maos_verts.c b/src/mesa/drivers/dri/radeon/radeon_maos_verts.c
new file mode 100644
index 0000000000..39b1f57507
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_maos_verts.c
@@ -0,0 +1,335 @@
+/* $XFree86$ */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+ Tungsten Graphics Inc., Austin, Texas.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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 "glheader.h"
+#include "imports.h"
+#include "mtypes.h"
+
+#include "array_cache/acache.h"
+#include "tnl/tnl.h"
+#include "tnl/t_pipeline.h"
+#include "tnl/t_imm_debug.h"
+
+#include "radeon_context.h"
+#include "radeon_state.h"
+#include "radeon_ioctl.h"
+#include "radeon_tex.h"
+#include "radeon_tcl.h"
+#include "radeon_swtcl.h"
+#include "radeon_maos.h"
+
+
+#define RADEON_TCL_MAX_SETUP 13
+
+union emit_union { float f; GLuint ui; radeon_color_t specular; };
+
+static struct {
+ void (*emit)( GLcontext *, GLuint, GLuint, void * );
+ GLuint vertex_size;
+ GLuint vertex_format;
+} setup_tab[RADEON_TCL_MAX_SETUP];
+
+#define DO_W (IND & RADEON_CP_VC_FRMT_W0)
+#define DO_RGBA (IND & RADEON_CP_VC_FRMT_PKCOLOR)
+#define DO_SPEC (IND & RADEON_CP_VC_FRMT_PKSPEC)
+#define DO_FOG (IND & RADEON_CP_VC_FRMT_PKSPEC)
+#define DO_TEX0 (IND & RADEON_CP_VC_FRMT_ST0)
+#define DO_TEX1 (IND & RADEON_CP_VC_FRMT_ST1)
+#define DO_PTEX (IND & RADEON_CP_VC_FRMT_Q0)
+#define DO_NORM (IND & RADEON_CP_VC_FRMT_N0)
+
+#define DO_TEX2 0
+#define DO_TEX3 0
+
+#define GET_TEXSOURCE(n) n
+#define GET_UBYTE_COLOR_STORE() &RADEON_CONTEXT(ctx)->UbyteColor
+#define GET_UBYTE_SPEC_COLOR_STORE() &RADEON_CONTEXT(ctx)->UbyteSecondaryColor
+
+#define IMPORT_FLOAT_COLORS radeon_import_float_colors
+#define IMPORT_FLOAT_SPEC_COLORS radeon_import_float_spec_colors
+
+/***********************************************************************
+ * Generate vertex emit functions *
+ ***********************************************************************/
+
+
+/* Defined in order of increasing vertex size:
+ */
+#define IDX 0
+#define IND (RADEON_CP_VC_FRMT_XY| \
+ RADEON_CP_VC_FRMT_Z| \
+ RADEON_CP_VC_FRMT_PKCOLOR)
+#define TAG(x) x##_rgba
+#include "radeon_maos_vbtmp.h"
+
+#define IDX 1
+#define IND (RADEON_CP_VC_FRMT_XY| \
+ RADEON_CP_VC_FRMT_Z| \
+ RADEON_CP_VC_FRMT_N0)
+#define TAG(x) x##_n
+#include "radeon_maos_vbtmp.h"
+
+#define IDX 2
+#define IND (RADEON_CP_VC_FRMT_XY| \
+ RADEON_CP_VC_FRMT_Z| \
+ RADEON_CP_VC_FRMT_PKCOLOR| \
+ RADEON_CP_VC_FRMT_ST0)
+#define TAG(x) x##_rgba_st
+#include "radeon_maos_vbtmp.h"
+
+#define IDX 3
+#define IND (RADEON_CP_VC_FRMT_XY| \
+ RADEON_CP_VC_FRMT_Z| \
+ RADEON_CP_VC_FRMT_PKCOLOR| \
+ RADEON_CP_VC_FRMT_N0)
+#define TAG(x) x##_rgba_n
+#include "radeon_maos_vbtmp.h"
+
+#define IDX 4
+#define IND (RADEON_CP_VC_FRMT_XY| \
+ RADEON_CP_VC_FRMT_Z| \
+ RADEON_CP_VC_FRMT_ST0| \
+ RADEON_CP_VC_FRMT_N0)
+#define TAG(x) x##_st_n
+#include "radeon_maos_vbtmp.h"
+
+#define IDX 5
+#define IND (RADEON_CP_VC_FRMT_XY| \
+ RADEON_CP_VC_FRMT_Z| \
+ RADEON_CP_VC_FRMT_PKCOLOR| \
+ RADEON_CP_VC_FRMT_ST0| \
+ RADEON_CP_VC_FRMT_ST1)
+#define TAG(x) x##_rgba_st_st
+#include "radeon_maos_vbtmp.h"
+
+#define IDX 6
+#define IND (RADEON_CP_VC_FRMT_XY| \
+ RADEON_CP_VC_FRMT_Z| \
+ RADEON_CP_VC_FRMT_PKCOLOR| \
+ RADEON_CP_VC_FRMT_ST0| \
+ RADEON_CP_VC_FRMT_N0)
+#define TAG(x) x##_rgba_st_n
+#include "radeon_maos_vbtmp.h"
+
+#define IDX 7
+#define IND (RADEON_CP_VC_FRMT_XY| \
+ RADEON_CP_VC_FRMT_Z| \
+ RADEON_CP_VC_FRMT_PKCOLOR| \
+ RADEON_CP_VC_FRMT_PKSPEC| \
+ RADEON_CP_VC_FRMT_ST0| \
+ RADEON_CP_VC_FRMT_ST1)
+#define TAG(x) x##_rgba_spec_st_st
+#include "radeon_maos_vbtmp.h"
+
+#define IDX 8
+#define IND (RADEON_CP_VC_FRMT_XY| \
+ RADEON_CP_VC_FRMT_Z| \
+ RADEON_CP_VC_FRMT_ST0| \
+ RADEON_CP_VC_FRMT_ST1| \
+ RADEON_CP_VC_FRMT_N0)
+#define TAG(x) x##_st_st_n
+#include "radeon_maos_vbtmp.h"
+
+#define IDX 9
+#define IND (RADEON_CP_VC_FRMT_XY| \
+ RADEON_CP_VC_FRMT_Z| \
+ RADEON_CP_VC_FRMT_PKCOLOR| \
+ RADEON_CP_VC_FRMT_PKSPEC| \
+ RADEON_CP_VC_FRMT_ST0| \
+ RADEON_CP_VC_FRMT_ST1| \
+ RADEON_CP_VC_FRMT_N0)
+#define TAG(x) x##_rgpa_spec_st_st_n
+#include "radeon_maos_vbtmp.h"
+
+#define IDX 10
+#define IND (RADEON_CP_VC_FRMT_XY| \
+ RADEON_CP_VC_FRMT_Z| \
+ RADEON_CP_VC_FRMT_PKCOLOR| \
+ RADEON_CP_VC_FRMT_ST0| \
+ RADEON_CP_VC_FRMT_Q0)
+#define TAG(x) x##_rgba_stq
+#include "radeon_maos_vbtmp.h"
+
+#define IDX 11
+#define IND (RADEON_CP_VC_FRMT_XY| \
+ RADEON_CP_VC_FRMT_Z| \
+ RADEON_CP_VC_FRMT_PKCOLOR| \
+ RADEON_CP_VC_FRMT_ST1| \
+ RADEON_CP_VC_FRMT_Q1| \
+ RADEON_CP_VC_FRMT_ST0| \
+ RADEON_CP_VC_FRMT_Q0)
+#define TAG(x) x##_rgba_stq_stq
+#include "radeon_maos_vbtmp.h"
+
+#define IDX 12
+#define IND (RADEON_CP_VC_FRMT_XY| \
+ RADEON_CP_VC_FRMT_Z| \
+ RADEON_CP_VC_FRMT_W0| \
+ RADEON_CP_VC_FRMT_PKCOLOR| \
+ RADEON_CP_VC_FRMT_PKSPEC| \
+ RADEON_CP_VC_FRMT_ST0| \
+ RADEON_CP_VC_FRMT_Q0| \
+ RADEON_CP_VC_FRMT_ST1| \
+ RADEON_CP_VC_FRMT_Q1| \
+ RADEON_CP_VC_FRMT_N0)
+#define TAG(x) x##_w_rgpa_spec_stq_stq_n
+#include "radeon_maos_vbtmp.h"
+
+
+
+
+
+/***********************************************************************
+ * Initialization
+ ***********************************************************************/
+
+
+static void init_tcl_verts( void )
+{
+ init_rgba();
+ init_n();
+ init_rgba_n();
+ init_rgba_st();
+ init_st_n();
+ init_rgba_st_st();
+ init_rgba_st_n();
+ init_rgba_spec_st_st();
+ init_st_st_n();
+ init_rgpa_spec_st_st_n();
+ init_rgba_stq();
+ init_rgba_stq_stq();
+ init_w_rgpa_spec_stq_stq_n();
+}
+
+
+void radeonEmitArrays( GLcontext *ctx, GLuint inputs )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ GLuint req = 0;
+ GLuint vtx = (rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &
+ ~(RADEON_TCL_VTX_Q0|RADEON_TCL_VTX_Q1));
+ int i;
+ static int firsttime = 1;
+
+ if (firsttime) {
+ init_tcl_verts();
+ firsttime = 0;
+ }
+
+ if (1) {
+ req |= RADEON_CP_VC_FRMT_Z;
+ if (VB->ObjPtr->size == 4) {
+ req |= RADEON_CP_VC_FRMT_W0;
+ }
+ }
+
+ if (inputs & VERT_BIT_NORMAL) {
+ req |= RADEON_CP_VC_FRMT_N0;
+ }
+
+ if (inputs & VERT_BIT_COLOR0) {
+ req |= RADEON_CP_VC_FRMT_PKCOLOR;
+ }
+
+ if (inputs & VERT_BIT_COLOR1) {
+ req |= RADEON_CP_VC_FRMT_PKSPEC;
+ }
+
+ if (inputs & VERT_BIT_TEX0) {
+ req |= RADEON_CP_VC_FRMT_ST0;
+
+ if (VB->TexCoordPtr[0]->size == 4) {
+ req |= RADEON_CP_VC_FRMT_Q0;
+ vtx |= RADEON_TCL_VTX_Q0;
+ }
+ }
+
+ if (inputs & VERT_BIT_TEX1) {
+ req |= RADEON_CP_VC_FRMT_ST1;
+
+ if (VB->TexCoordPtr[1]->size == 4) {
+ req |= RADEON_CP_VC_FRMT_Q1;
+ vtx |= RADEON_TCL_VTX_Q1;
+ }
+ }
+
+ if (vtx != rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT]) {
+ RADEON_STATECHANGE( rmesa, tcl );
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] = vtx;
+ }
+
+ for (i = 0 ; i < RADEON_TCL_MAX_SETUP ; i++)
+ if ((setup_tab[i].vertex_format & req) == req)
+ break;
+
+ if (rmesa->tcl.vertex_format == setup_tab[i].vertex_format &&
+ rmesa->tcl.indexed_verts.buf)
+ return;
+
+ if (rmesa->tcl.indexed_verts.buf)
+ radeonReleaseArrays( ctx, ~0 );
+
+ radeonAllocDmaRegionVerts( rmesa,
+ &rmesa->tcl.indexed_verts,
+ VB->Count,
+ setup_tab[i].vertex_size * 4,
+ 4);
+
+ setup_tab[i].emit( ctx, 0, VB->Count,
+ rmesa->tcl.indexed_verts.address +
+ rmesa->tcl.indexed_verts.start );
+
+ rmesa->tcl.vertex_format = setup_tab[i].vertex_format;
+ rmesa->tcl.indexed_verts.aos_start = GET_START( &rmesa->tcl.indexed_verts );
+ rmesa->tcl.indexed_verts.aos_size = setup_tab[i].vertex_size;
+ rmesa->tcl.indexed_verts.aos_stride = setup_tab[i].vertex_size;
+
+ rmesa->tcl.aos_components[0] = &rmesa->tcl.indexed_verts;
+ rmesa->tcl.nr_aos_components = 1;
+}
+
+
+
+void radeonReleaseArrays( GLcontext *ctx, GLuint newinputs )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+
+ if (RADEON_DEBUG & DEBUG_VERTS)
+ _tnl_print_vert_flags( __FUNCTION__, newinputs );
+
+ if (newinputs)
+ radeonReleaseDmaRegion( rmesa, &rmesa->tcl.indexed_verts, __FUNCTION__ );
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_sanity.c b/src/mesa/drivers/dri/radeon/radeon_sanity.c
new file mode 100644
index 0000000000..e3b37bf3de
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_sanity.c
@@ -0,0 +1,1043 @@
+/* $XFree86$ */
+/**************************************************************************
+
+Copyright 2002 ATI Technologies Inc., Ontario, Canada, and
+ Tungsten Graphics Inc, Cedar Park, TX.
+
+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, TUNGSTEN GRAPHICS 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>
+ *
+ */
+#include <errno.h>
+
+#include "glheader.h"
+
+#include "radeon_context.h"
+#include "radeon_ioctl.h"
+#include "radeon_sanity.h"
+
+/* Set this '1' to get more verbiage.
+ */
+#define MORE_VERBOSE 1
+
+#if MORE_VERBOSE
+#define VERBOSE (RADEON_DEBUG & DEBUG_VERBOSE)
+#define NORMAL (1)
+#else
+#define VERBOSE 0
+#define NORMAL (RADEON_DEBUG & DEBUG_VERBOSE)
+#endif
+
+
+/* New (1.3) state mechanism. 3 commands (packet, scalar, vector) in
+ * 1.3 cmdbuffers allow all previous state to be updated as well as
+ * the tcl scalar and vector areas.
+ */
+static struct {
+ int start;
+ int len;
+ const char *name;
+} packet[RADEON_MAX_STATE_PACKETS] = {
+ { RADEON_PP_MISC,7,"RADEON_PP_MISC" },
+ { RADEON_PP_CNTL,3,"RADEON_PP_CNTL" },
+ { RADEON_RB3D_COLORPITCH,1,"RADEON_RB3D_COLORPITCH" },
+ { RADEON_RE_LINE_PATTERN,2,"RADEON_RE_LINE_PATTERN" },
+ { RADEON_SE_LINE_WIDTH,1,"RADEON_SE_LINE_WIDTH" },
+ { RADEON_PP_LUM_MATRIX,1,"RADEON_PP_LUM_MATRIX" },
+ { RADEON_PP_ROT_MATRIX_0,2,"RADEON_PP_ROT_MATRIX_0" },
+ { RADEON_RB3D_STENCILREFMASK,3,"RADEON_RB3D_STENCILREFMASK" },
+ { RADEON_SE_VPORT_XSCALE,6,"RADEON_SE_VPORT_XSCALE" },
+ { RADEON_SE_CNTL,2,"RADEON_SE_CNTL" },
+ { RADEON_SE_CNTL_STATUS,1,"RADEON_SE_CNTL_STATUS" },
+ { RADEON_RE_MISC,1,"RADEON_RE_MISC" },
+ { RADEON_PP_TXFILTER_0,6,"RADEON_PP_TXFILTER_0" },
+ { RADEON_PP_BORDER_COLOR_0,1,"RADEON_PP_BORDER_COLOR_0" },
+ { RADEON_PP_TXFILTER_1,6,"RADEON_PP_TXFILTER_1" },
+ { RADEON_PP_BORDER_COLOR_1,1,"RADEON_PP_BORDER_COLOR_1" },
+ { RADEON_PP_TXFILTER_2,6,"RADEON_PP_TXFILTER_2" },
+ { RADEON_PP_BORDER_COLOR_2,1,"RADEON_PP_BORDER_COLOR_2" },
+ { RADEON_SE_ZBIAS_FACTOR,2,"RADEON_SE_ZBIAS_FACTOR" },
+ { RADEON_SE_TCL_OUTPUT_VTX_FMT,11,"RADEON_SE_TCL_OUTPUT_VTX_FMT" },
+ { RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED,17,"RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED" },
+ { 0, 4, "R200_PP_TXCBLEND_0" },
+ { 0, 4, "R200_PP_TXCBLEND_1" },
+ { 0, 4, "R200_PP_TXCBLEND_2" },
+ { 0, 4, "R200_PP_TXCBLEND_3" },
+ { 0, 4, "R200_PP_TXCBLEND_4" },
+ { 0, 4, "R200_PP_TXCBLEND_5" },
+ { 0, 4, "R200_PP_TXCBLEND_6" },
+ { 0, 4, "R200_PP_TXCBLEND_7" },
+ { 0, 6, "R200_SE_TCL_LIGHT_MODEL_CTL_0" },
+ { 0, 6, "R200_PP_TFACTOR_0" },
+ { 0, 4, "R200_SE_VTX_FMT_0" },
+ { 0, 1, "R200_SE_VAP_CNTL" },
+ { 0, 5, "R200_SE_TCL_MATRIX_SEL_0" },
+ { 0, 5, "R200_SE_TCL_TEX_PROC_CTL_2" },
+ { 0, 1, "R200_SE_TCL_UCP_VERT_BLEND_CTL" },
+ { 0, 6, "R200_PP_TXFILTER_0" },
+ { 0, 6, "R200_PP_TXFILTER_1" },
+ { 0, 6, "R200_PP_TXFILTER_2" },
+ { 0, 6, "R200_PP_TXFILTER_3" },
+ { 0, 6, "R200_PP_TXFILTER_4" },
+ { 0, 6, "R200_PP_TXFILTER_5" },
+ { 0, 1, "R200_PP_TXOFFSET_0" },
+ { 0, 1, "R200_PP_TXOFFSET_1" },
+ { 0, 1, "R200_PP_TXOFFSET_2" },
+ { 0, 1, "R200_PP_TXOFFSET_3" },
+ { 0, 1, "R200_PP_TXOFFSET_4" },
+ { 0, 1, "R200_PP_TXOFFSET_5" },
+ { 0, 1, "R200_SE_VTE_CNTL" },
+ { 0, 1, "R200_SE_TCL_OUTPUT_VTX_COMP_SEL" },
+ { 0, 1, "R200_PP_TAM_DEBUG3" },
+ { 0, 1, "R200_PP_CNTL_X" },
+ { 0, 1, "R200_RB3D_DEPTHXY_OFFSET" },
+ { 0, 1, "R200_RE_AUX_SCISSOR_CNTL" },
+ { 0, 2, "R200_RE_SCISSOR_TL_0" },
+ { 0, 2, "R200_RE_SCISSOR_TL_1" },
+ { 0, 2, "R200_RE_SCISSOR_TL_2" },
+ { 0, 1, "R200_SE_VAP_CNTL_STATUS" },
+ { 0, 1, "R200_SE_VTX_STATE_CNTL" },
+ { 0, 1, "R200_RE_POINTSIZE" },
+ { 0, 4, "R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0" },
+ { 0, 1, "R200_PP_CUBIC_FACES_0" }, /* 61 */
+ { 0, 5, "R200_PP_CUBIC_OFFSET_F1_0" }, /* 62 */
+ { 0, 1, "R200_PP_CUBIC_FACES_1" },
+ { 0, 5, "R200_PP_CUBIC_OFFSET_F1_1" },
+ { 0, 1, "R200_PP_CUBIC_FACES_2" },
+ { 0, 5, "R200_PP_CUBIC_OFFSET_F1_2" },
+ { 0, 1, "R200_PP_CUBIC_FACES_3" },
+ { 0, 5, "R200_PP_CUBIC_OFFSET_F1_3" },
+ { 0, 1, "R200_PP_CUBIC_FACES_4" },
+ { 0, 5, "R200_PP_CUBIC_OFFSET_F1_4" },
+ { 0, 1, "R200_PP_CUBIC_FACES_5" },
+ { 0, 5, "R200_PP_CUBIC_OFFSET_F1_5" },
+ { RADEON_PP_TEX_SIZE_0, 2, "RADEON_PP_TEX_SIZE_0" },
+ { RADEON_PP_TEX_SIZE_1, 2, "RADEON_PP_TEX_SIZE_1" },
+ { RADEON_PP_TEX_SIZE_2, 2, "RADEON_PP_TEX_SIZE_1" },
+};
+
+struct reg_names {
+ int idx;
+ const char *name;
+};
+
+static struct reg_names reg_names[] = {
+ { RADEON_PP_MISC, "RADEON_PP_MISC" },
+ { RADEON_PP_FOG_COLOR, "RADEON_PP_FOG_COLOR" },
+ { RADEON_RE_SOLID_COLOR, "RADEON_RE_SOLID_COLOR" },
+ { RADEON_RB3D_BLENDCNTL, "RADEON_RB3D_BLENDCNTL" },
+ { RADEON_RB3D_DEPTHOFFSET, "RADEON_RB3D_DEPTHOFFSET" },
+ { RADEON_RB3D_DEPTHPITCH, "RADEON_RB3D_DEPTHPITCH" },
+ { RADEON_RB3D_ZSTENCILCNTL, "RADEON_RB3D_ZSTENCILCNTL" },
+ { RADEON_PP_CNTL, "RADEON_PP_CNTL" },
+ { RADEON_RB3D_CNTL, "RADEON_RB3D_CNTL" },
+ { RADEON_RB3D_COLOROFFSET, "RADEON_RB3D_COLOROFFSET" },
+ { RADEON_RB3D_COLORPITCH, "RADEON_RB3D_COLORPITCH" },
+ { RADEON_SE_CNTL, "RADEON_SE_CNTL" },
+ { RADEON_SE_COORD_FMT, "RADEON_SE_COORDFMT" },
+ { RADEON_SE_CNTL_STATUS, "RADEON_SE_CNTL_STATUS" },
+ { RADEON_RE_LINE_PATTERN, "RADEON_RE_LINE_PATTERN" },
+ { RADEON_RE_LINE_STATE, "RADEON_RE_LINE_STATE" },
+ { RADEON_SE_LINE_WIDTH, "RADEON_SE_LINE_WIDTH" },
+ { RADEON_RB3D_STENCILREFMASK, "RADEON_RB3D_STENCILREFMASK" },
+ { RADEON_RB3D_ROPCNTL, "RADEON_RB3D_ROPCNTL" },
+ { RADEON_RB3D_PLANEMASK, "RADEON_RB3D_PLANEMASK" },
+ { RADEON_SE_VPORT_XSCALE, "RADEON_SE_VPORT_XSCALE" },
+ { RADEON_SE_VPORT_XOFFSET, "RADEON_SE_VPORT_XOFFSET" },
+ { RADEON_SE_VPORT_YSCALE, "RADEON_SE_VPORT_YSCALE" },
+ { RADEON_SE_VPORT_YOFFSET, "RADEON_SE_VPORT_YOFFSET" },
+ { RADEON_SE_VPORT_ZSCALE, "RADEON_SE_VPORT_ZSCALE" },
+ { RADEON_SE_VPORT_ZOFFSET, "RADEON_SE_VPORT_ZOFFSET" },
+ { RADEON_RE_MISC, "RADEON_RE_MISC" },
+ { RADEON_PP_TXFILTER_0, "RADEON_PP_TXFILTER_0" },
+ { RADEON_PP_TXFILTER_1, "RADEON_PP_TXFILTER_1" },
+ { RADEON_PP_TXFILTER_2, "RADEON_PP_TXFILTER_2" },
+ { RADEON_PP_TXFORMAT_0, "RADEON_PP_TXFORMAT_0" },
+ { RADEON_PP_TXFORMAT_1, "RADEON_PP_TXFORMAT_1" },
+ { RADEON_PP_TXFORMAT_2, "RADEON_PP_TXFORMAT_3" },
+ { RADEON_PP_TXOFFSET_0, "RADEON_PP_TXOFFSET_0" },
+ { RADEON_PP_TXOFFSET_1, "RADEON_PP_TXOFFSET_1" },
+ { RADEON_PP_TXOFFSET_2, "RADEON_PP_TXOFFSET_3" },
+ { RADEON_PP_TXCBLEND_0, "RADEON_PP_TXCBLEND_0" },
+ { RADEON_PP_TXCBLEND_1, "RADEON_PP_TXCBLEND_1" },
+ { RADEON_PP_TXCBLEND_2, "RADEON_PP_TXCBLEND_3" },
+ { RADEON_PP_TXABLEND_0, "RADEON_PP_TXABLEND_0" },
+ { RADEON_PP_TXABLEND_1, "RADEON_PP_TXABLEND_1" },
+ { RADEON_PP_TXABLEND_2, "RADEON_PP_TXABLEND_3" },
+ { RADEON_PP_TFACTOR_0, "RADEON_PP_TFACTOR_0" },
+ { RADEON_PP_TFACTOR_1, "RADEON_PP_TFACTOR_1" },
+ { RADEON_PP_TFACTOR_2, "RADEON_PP_TFACTOR_3" },
+ { RADEON_PP_BORDER_COLOR_0, "RADEON_PP_BORDER_COLOR_0" },
+ { RADEON_PP_BORDER_COLOR_1, "RADEON_PP_BORDER_COLOR_1" },
+ { RADEON_PP_BORDER_COLOR_2, "RADEON_PP_BORDER_COLOR_3" },
+ { RADEON_SE_ZBIAS_FACTOR, "RADEON_SE_ZBIAS_FACTOR" },
+ { RADEON_SE_ZBIAS_CONSTANT, "RADEON_SE_ZBIAS_CONSTANT" },
+ { RADEON_SE_TCL_OUTPUT_VTX_FMT, "RADEON_SE_TCL_OUTPUT_VTXFMT" },
+ { RADEON_SE_TCL_OUTPUT_VTX_SEL, "RADEON_SE_TCL_OUTPUT_VTXSEL" },
+ { RADEON_SE_TCL_MATRIX_SELECT_0, "RADEON_SE_TCL_MATRIX_SELECT_0" },
+ { RADEON_SE_TCL_MATRIX_SELECT_1, "RADEON_SE_TCL_MATRIX_SELECT_1" },
+ { RADEON_SE_TCL_UCP_VERT_BLEND_CTL, "RADEON_SE_TCL_UCP_VERT_BLEND_CTL" },
+ { RADEON_SE_TCL_TEXTURE_PROC_CTL, "RADEON_SE_TCL_TEXTURE_PROC_CTL" },
+ { RADEON_SE_TCL_LIGHT_MODEL_CTL, "RADEON_SE_TCL_LIGHT_MODEL_CTL" },
+ { RADEON_SE_TCL_PER_LIGHT_CTL_0, "RADEON_SE_TCL_PER_LIGHT_CTL_0" },
+ { RADEON_SE_TCL_PER_LIGHT_CTL_1, "RADEON_SE_TCL_PER_LIGHT_CTL_1" },
+ { RADEON_SE_TCL_PER_LIGHT_CTL_2, "RADEON_SE_TCL_PER_LIGHT_CTL_2" },
+ { RADEON_SE_TCL_PER_LIGHT_CTL_3, "RADEON_SE_TCL_PER_LIGHT_CTL_3" },
+ { RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED, "RADEON_SE_TCL_EMMISSIVE_RED" },
+ { RADEON_SE_TCL_MATERIAL_EMMISSIVE_GREEN, "RADEON_SE_TCL_EMMISSIVE_GREEN" },
+ { RADEON_SE_TCL_MATERIAL_EMMISSIVE_BLUE, "RADEON_SE_TCL_EMMISSIVE_BLUE" },
+ { RADEON_SE_TCL_MATERIAL_EMMISSIVE_ALPHA, "RADEON_SE_TCL_EMMISSIVE_ALPHA" },
+ { RADEON_SE_TCL_MATERIAL_AMBIENT_RED, "RADEON_SE_TCL_AMBIENT_RED" },
+ { RADEON_SE_TCL_MATERIAL_AMBIENT_GREEN, "RADEON_SE_TCL_AMBIENT_GREEN" },
+ { RADEON_SE_TCL_MATERIAL_AMBIENT_BLUE, "RADEON_SE_TCL_AMBIENT_BLUE" },
+ { RADEON_SE_TCL_MATERIAL_AMBIENT_ALPHA, "RADEON_SE_TCL_AMBIENT_ALPHA" },
+ { RADEON_SE_TCL_MATERIAL_DIFFUSE_RED, "RADEON_SE_TCL_DIFFUSE_RED" },
+ { RADEON_SE_TCL_MATERIAL_DIFFUSE_GREEN, "RADEON_SE_TCL_DIFFUSE_GREEN" },
+ { RADEON_SE_TCL_MATERIAL_DIFFUSE_BLUE, "RADEON_SE_TCL_DIFFUSE_BLUE" },
+ { RADEON_SE_TCL_MATERIAL_DIFFUSE_ALPHA, "RADEON_SE_TCL_DIFFUSE_ALPHA" },
+ { RADEON_SE_TCL_MATERIAL_SPECULAR_RED, "RADEON_SE_TCL_SPECULAR_RED" },
+ { RADEON_SE_TCL_MATERIAL_SPECULAR_GREEN, "RADEON_SE_TCL_SPECULAR_GREEN" },
+ { RADEON_SE_TCL_MATERIAL_SPECULAR_BLUE, "RADEON_SE_TCL_SPECULAR_BLUE" },
+ { RADEON_SE_TCL_MATERIAL_SPECULAR_ALPHA, "RADEON_SE_TCL_SPECULAR_ALPHA" },
+ { RADEON_SE_TCL_SHININESS, "RADEON_SE_TCL_SHININESS" },
+ { RADEON_SE_COORD_FMT, "RADEON_SE_COORD_FMT" },
+ { RADEON_PP_TEX_SIZE_0, "RADEON_PP_TEX_SIZE_0" },
+ { RADEON_PP_TEX_SIZE_1, "RADEON_PP_TEX_SIZE_1" },
+ { RADEON_PP_TEX_SIZE_2, "RADEON_PP_TEX_SIZE_2" },
+ { RADEON_PP_TEX_SIZE_0+4, "RADEON_PP_TEX_PITCH_0" },
+ { RADEON_PP_TEX_SIZE_1+4, "RADEON_PP_TEX_PITCH_1" },
+ { RADEON_PP_TEX_SIZE_2+4, "RADEON_PP_TEX_PITCH_2" },
+};
+
+static struct reg_names scalar_names[] = {
+ { RADEON_SS_LIGHT_DCD_ADDR, "LIGHT_DCD" },
+ { RADEON_SS_LIGHT_SPOT_EXPONENT_ADDR, "LIGHT_SPOT_EXPONENT" },
+ { RADEON_SS_LIGHT_SPOT_CUTOFF_ADDR, "LIGHT_SPOT_CUTOFF" },
+ { RADEON_SS_LIGHT_SPECULAR_THRESH_ADDR, "LIGHT_SPECULAR_THRESH" },
+ { RADEON_SS_LIGHT_RANGE_CUTOFF_ADDR, "LIGHT_RANGE_CUTOFF" },
+ { RADEON_SS_VERT_GUARD_CLIP_ADJ_ADDR, "VERT_GUARD_CLIP" },
+ { RADEON_SS_VERT_GUARD_DISCARD_ADJ_ADDR, "VERT_GUARD_DISCARD" },
+ { RADEON_SS_HORZ_GUARD_CLIP_ADJ_ADDR, "HORZ_GUARD_CLIP" },
+ { RADEON_SS_HORZ_GUARD_DISCARD_ADJ_ADDR, "HORZ_GUARD_DISCARD" },
+ { RADEON_SS_SHININESS, "SHININESS" },
+ { 1000, "" },
+};
+
+/* Puff these out to make them look like normal (dword) registers.
+ */
+static struct reg_names vector_names[] = {
+ { RADEON_VS_MATRIX_0_ADDR * 4, "MATRIX_0" },
+ { RADEON_VS_MATRIX_1_ADDR * 4, "MATRIX_1" },
+ { RADEON_VS_MATRIX_2_ADDR * 4, "MATRIX_2" },
+ { RADEON_VS_MATRIX_3_ADDR * 4, "MATRIX_3" },
+ { RADEON_VS_MATRIX_4_ADDR * 4, "MATRIX_4" },
+ { RADEON_VS_MATRIX_5_ADDR * 4, "MATRIX_5" },
+ { RADEON_VS_MATRIX_6_ADDR * 4, "MATRIX_6" },
+ { RADEON_VS_MATRIX_7_ADDR * 4, "MATRIX_7" },
+ { RADEON_VS_MATRIX_8_ADDR * 4, "MATRIX_8" },
+ { RADEON_VS_MATRIX_9_ADDR * 4, "MATRIX_9" },
+ { RADEON_VS_MATRIX_10_ADDR * 4, "MATRIX_10" },
+ { RADEON_VS_MATRIX_11_ADDR * 4, "MATRIX_11" },
+ { RADEON_VS_MATRIX_12_ADDR * 4, "MATRIX_12" },
+ { RADEON_VS_MATRIX_13_ADDR * 4, "MATRIX_13" },
+ { RADEON_VS_MATRIX_14_ADDR * 4, "MATRIX_14" },
+ { RADEON_VS_MATRIX_15_ADDR * 4, "MATRIX_15" },
+ { RADEON_VS_LIGHT_AMBIENT_ADDR * 4, "LIGHT_AMBIENT" },
+ { RADEON_VS_LIGHT_DIFFUSE_ADDR * 4, "LIGHT_DIFFUSE" },
+ { RADEON_VS_LIGHT_SPECULAR_ADDR * 4, "LIGHT_SPECULAR" },
+ { RADEON_VS_LIGHT_DIRPOS_ADDR * 4, "LIGHT_DIRPOS" },
+ { RADEON_VS_LIGHT_HWVSPOT_ADDR * 4, "LIGHT_HWVSPOT" },
+ { RADEON_VS_LIGHT_ATTENUATION_ADDR * 4, "LIGHT_ATTENUATION" },
+ { RADEON_VS_MATRIX_EYE2CLIP_ADDR * 4, "MATRIX_EYE2CLIP" },
+ { RADEON_VS_UCP_ADDR * 4, "UCP" },
+ { RADEON_VS_GLOBAL_AMBIENT_ADDR * 4, "GLOBAL_AMBIENT" },
+ { RADEON_VS_FOG_PARAM_ADDR * 4, "FOG_PARAM" },
+ { RADEON_VS_EYE_VECTOR_ADDR * 4, "EYE_VECTOR" },
+ { 1000, "" },
+};
+
+union fi { float f; int i; };
+
+#define ISVEC 1
+#define ISFLOAT 2
+#define TOUCHED 4
+
+struct reg {
+ int idx;
+ struct reg_names *closest;
+ int flags;
+ union fi current;
+ union fi *values;
+ int nvalues;
+ int nalloc;
+ float vmin, vmax;
+};
+
+
+static struct reg regs[Elements(reg_names)+1];
+static struct reg scalars[512+1];
+static struct reg vectors[512*4+1];
+
+static int total, total_changed, bufs;
+
+static void init_regs( void )
+{
+ struct reg_names *tmp;
+ int i;
+
+ for (i = 0 ; i < Elements(regs) ; i++) {
+ regs[i].idx = reg_names[i].idx;
+ regs[i].closest = &reg_names[i];
+ regs[i].flags = 0;
+ }
+
+ for (i = 0, tmp = scalar_names ; i < Elements(scalars) ; i++) {
+ if (tmp[1].idx == i) tmp++;
+ scalars[i].idx = i;
+ scalars[i].closest = tmp;
+ scalars[i].flags = ISFLOAT;
+ }
+
+ for (i = 0, tmp = vector_names ; i < Elements(vectors) ; i++) {
+ if (tmp[1].idx*4 == i) tmp++;
+ vectors[i].idx = i;
+ vectors[i].closest = tmp;
+ vectors[i].flags = ISFLOAT|ISVEC;
+ }
+
+ regs[Elements(regs)-1].idx = -1;
+ scalars[Elements(scalars)-1].idx = -1;
+ vectors[Elements(vectors)-1].idx = -1;
+}
+
+static int find_or_add_value( struct reg *reg, int val )
+{
+ int j;
+
+ for ( j = 0 ; j < reg->nvalues ; j++)
+ if ( val == reg->values[j].i )
+ return 1;
+
+ if (j == reg->nalloc) {
+ reg->nalloc += 5;
+ reg->nalloc *= 2;
+ reg->values = (union fi *) realloc( reg->values,
+ reg->nalloc * sizeof(union fi) );
+ }
+
+ reg->values[reg->nvalues++].i = val;
+ return 0;
+}
+
+static struct reg *lookup_reg( struct reg *tab, int reg )
+{
+ int i;
+
+ for (i = 0 ; tab[i].idx != -1 ; i++) {
+ if (tab[i].idx == reg)
+ return &tab[i];
+ }
+
+ fprintf(stderr, "*** unknown reg 0x%x\n", reg);
+ return 0;
+}
+
+
+static const char *get_reg_name( struct reg *reg )
+{
+ static char tmp[80];
+
+ if (reg->idx == reg->closest->idx)
+ return reg->closest->name;
+
+
+ if (reg->flags & ISVEC) {
+ if (reg->idx/4 != reg->closest->idx)
+ sprintf(tmp, "%s+%d[%d]",
+ reg->closest->name,
+ (reg->idx/4) - reg->closest->idx,
+ reg->idx%4);
+ else
+ sprintf(tmp, "%s[%d]", reg->closest->name, reg->idx%4);
+ }
+ else {
+ if (reg->idx != reg->closest->idx)
+ sprintf(tmp, "%s+%d", reg->closest->name, reg->idx - reg->closest->idx);
+ else
+ sprintf(tmp, "%s", reg->closest->name);
+ }
+
+ return tmp;
+}
+
+static int print_int_reg_assignment( struct reg *reg, int data )
+{
+ int changed = (reg->current.i != data);
+ int ever_seen = find_or_add_value( reg, data );
+
+ if (VERBOSE || (NORMAL && (changed || !ever_seen)))
+ fprintf(stderr, " %s <-- 0x%x", get_reg_name(reg), data);
+
+ if (NORMAL) {
+ if (!ever_seen)
+ fprintf(stderr, " *** BRAND NEW VALUE");
+ else if (changed)
+ fprintf(stderr, " *** CHANGED");
+ }
+
+ reg->current.i = data;
+
+ if (VERBOSE || (NORMAL && (changed || !ever_seen)))
+ fprintf(stderr, "\n");
+
+ return changed;
+}
+
+
+static int print_float_reg_assignment( struct reg *reg, float data )
+{
+ int changed = (reg->current.f != data);
+ int newmin = (data < reg->vmin);
+ int newmax = (data > reg->vmax);
+
+ if (VERBOSE || (NORMAL && (newmin || newmax || changed)))
+ fprintf(stderr, " %s <-- %.3f", get_reg_name(reg), data);
+
+ if (NORMAL) {
+ if (newmin) {
+ fprintf(stderr, " *** NEW MIN (prev %.3f)", reg->vmin);
+ reg->vmin = data;
+ }
+ else if (newmax) {
+ fprintf(stderr, " *** NEW MAX (prev %.3f)", reg->vmax);
+ reg->vmax = data;
+ }
+ else if (changed) {
+ fprintf(stderr, " *** CHANGED");
+ }
+ }
+
+ reg->current.f = data;
+
+ if (VERBOSE || (NORMAL && (newmin || newmax || changed)))
+ fprintf(stderr, "\n");
+
+ return changed;
+}
+
+static int print_reg_assignment( struct reg *reg, int data )
+{
+ reg->flags |= TOUCHED;
+ if (reg->flags & ISFLOAT)
+ return print_float_reg_assignment( reg, *(float *)&data );
+ else
+ return print_int_reg_assignment( reg, data );
+}
+
+static void print_reg( struct reg *reg )
+{
+ if (reg->flags & TOUCHED) {
+ if (reg->flags & ISFLOAT) {
+ fprintf(stderr, " %s == %f\n", get_reg_name(reg), reg->current.f);
+ } else {
+ fprintf(stderr, " %s == 0x%x\n", get_reg_name(reg), reg->current.i);
+ }
+ }
+}
+
+
+static void dump_state( void )
+{
+ int i;
+
+ for (i = 0 ; i < Elements(regs) ; i++)
+ print_reg( &regs[i] );
+
+ for (i = 0 ; i < Elements(scalars) ; i++)
+ print_reg( &scalars[i] );
+
+ for (i = 0 ; i < Elements(vectors) ; i++)
+ print_reg( &vectors[i] );
+}
+
+
+
+static int radeon_emit_packets(
+ drmRadeonCmdHeader header,
+ drmRadeonCmdBuffer *cmdbuf )
+{
+ int id = (int)header.packet.packet_id;
+ int sz = packet[id].len;
+ int *data = (int *)cmdbuf->buf;
+ int i;
+
+ if (sz * sizeof(int) > cmdbuf->bufsz) {
+ fprintf(stderr, "Packet overflows cmdbuf\n");
+ return -EINVAL;
+ }
+
+ if (!packet[id].name) {
+ fprintf(stderr, "*** Unknown packet 0 nr %d\n", id );
+ return -EINVAL;
+ }
+
+
+ if (VERBOSE)
+ fprintf(stderr, "Packet 0 reg %s nr %d\n", packet[id].name, sz );
+
+ for ( i = 0 ; i < sz ; i++) {
+ struct reg *reg = lookup_reg( regs, packet[id].start + i*4 );
+ if (print_reg_assignment( reg, data[i] ))
+ total_changed++;
+ total++;
+ }
+
+ cmdbuf->buf += sz * sizeof(int);
+ cmdbuf->bufsz -= sz * sizeof(int);
+ return 0;
+}
+
+
+static int radeon_emit_scalars(
+ drmRadeonCmdHeader header,
+ drmRadeonCmdBuffer *cmdbuf )
+{
+ int sz = header.scalars.count;
+ int *data = (int *)cmdbuf->buf;
+ int start = header.scalars.offset;
+ int stride = header.scalars.stride;
+ int i;
+
+ if (VERBOSE)
+ fprintf(stderr, "emit scalars, start %d stride %d nr %d (end %d)\n",
+ start, stride, sz, start + stride * sz);
+
+
+ for (i = 0 ; i < sz ; i++, start += stride) {
+ struct reg *reg = lookup_reg( scalars, start );
+ if (print_reg_assignment( reg, data[i] ))
+ total_changed++;
+ total++;
+ }
+
+ cmdbuf->buf += sz * sizeof(int);
+ cmdbuf->bufsz -= sz * sizeof(int);
+ return 0;
+}
+
+
+static int radeon_emit_scalars2(
+ drmRadeonCmdHeader header,
+ drmRadeonCmdBuffer *cmdbuf )
+{
+ int sz = header.scalars.count;
+ int *data = (int *)cmdbuf->buf;
+ int start = header.scalars.offset + 0x100;
+ int stride = header.scalars.stride;
+ int i;
+
+ if (VERBOSE)
+ fprintf(stderr, "emit scalars2, start %d stride %d nr %d (end %d)\n",
+ start, stride, sz, start + stride * sz);
+
+ if (start + stride * sz > 257) {
+ fprintf(stderr, "emit scalars OVERFLOW %d/%d/%d\n", start, stride, sz);
+ return -1;
+ }
+
+ for (i = 0 ; i < sz ; i++, start += stride) {
+ struct reg *reg = lookup_reg( scalars, start );
+ if (print_reg_assignment( reg, data[i] ))
+ total_changed++;
+ total++;
+ }
+
+ cmdbuf->buf += sz * sizeof(int);
+ cmdbuf->bufsz -= sz * sizeof(int);
+ return 0;
+}
+
+/* Check: inf/nan/extreme-size?
+ * Check: table start, end, nr, etc.
+ */
+static int radeon_emit_vectors(
+ drmRadeonCmdHeader header,
+ drmRadeonCmdBuffer *cmdbuf )
+{
+ int sz = header.vectors.count;
+ int *data = (int *)cmdbuf->buf;
+ int start = header.vectors.offset;
+ int stride = header.vectors.stride;
+ int i,j;
+
+ if (VERBOSE)
+ fprintf(stderr, "emit vectors, start %d stride %d nr %d (end %d) (0x%x)\n",
+ start, stride, sz, start + stride * sz, header.i);
+
+/* if (start + stride * (sz/4) > 128) { */
+/* fprintf(stderr, "emit vectors OVERFLOW %d/%d/%d\n", start, stride, sz); */
+/* return -1; */
+/* } */
+
+ for (i = 0 ; i < sz ; start += stride) {
+ int changed = 0;
+ for (j = 0 ; j < 4 ; i++,j++) {
+ struct reg *reg = lookup_reg( vectors, start*4+j );
+ if (print_reg_assignment( reg, data[i] ))
+ changed = 1;
+ }
+ if (changed)
+ total_changed += 4;
+ total += 4;
+ }
+
+
+ cmdbuf->buf += sz * sizeof(int);
+ cmdbuf->bufsz -= sz * sizeof(int);
+ return 0;
+}
+
+
+static int print_vertex_format( int vfmt )
+{
+ if (NORMAL) {
+ fprintf(stderr, " %s(%x): %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+ "vertex format",
+ vfmt,
+ "xy,",
+ (vfmt & RADEON_CP_VC_FRMT_Z) ? "z," : "",
+ (vfmt & RADEON_CP_VC_FRMT_W0) ? "w0," : "",
+ (vfmt & RADEON_CP_VC_FRMT_FPCOLOR) ? "fpcolor," : "",
+ (vfmt & RADEON_CP_VC_FRMT_FPALPHA) ? "fpalpha," : "",
+ (vfmt & RADEON_CP_VC_FRMT_PKCOLOR) ? "pkcolor," : "",
+ (vfmt & RADEON_CP_VC_FRMT_FPSPEC) ? "fpspec," : "",
+ (vfmt & RADEON_CP_VC_FRMT_FPFOG) ? "fpfog," : "",
+ (vfmt & RADEON_CP_VC_FRMT_PKSPEC) ? "pkspec," : "",
+ (vfmt & RADEON_CP_VC_FRMT_ST0) ? "st0," : "",
+ (vfmt & RADEON_CP_VC_FRMT_ST1) ? "st1," : "",
+ (vfmt & RADEON_CP_VC_FRMT_Q1) ? "q1," : "",
+ (vfmt & RADEON_CP_VC_FRMT_ST2) ? "st2," : "",
+ (vfmt & RADEON_CP_VC_FRMT_Q2) ? "q2," : "",
+ (vfmt & RADEON_CP_VC_FRMT_ST3) ? "st3," : "",
+ (vfmt & RADEON_CP_VC_FRMT_Q3) ? "q3," : "",
+ (vfmt & RADEON_CP_VC_FRMT_Q0) ? "q0," : "",
+ (vfmt & RADEON_CP_VC_FRMT_N0) ? "n0," : "",
+ (vfmt & RADEON_CP_VC_FRMT_XY1) ? "xy1," : "",
+ (vfmt & RADEON_CP_VC_FRMT_Z1) ? "z1," : "",
+ (vfmt & RADEON_CP_VC_FRMT_W1) ? "w1," : "",
+ (vfmt & RADEON_CP_VC_FRMT_N1) ? "n1," : "");
+
+
+/* if (!find_or_add_value( &others[V_VTXFMT], vfmt )) */
+/* fprintf(stderr, " *** NEW VALUE"); */
+
+ fprintf(stderr, "\n");
+ }
+
+ return 0;
+}
+
+static char *primname[0xf] = {
+ "NONE",
+ "POINTS",
+ "LINES",
+ "LINE_STRIP",
+ "TRIANGLES",
+ "TRIANGLE_FAN",
+ "TRIANGLE_STRIP",
+ "TRI_TYPE_2",
+ "RECT_LIST",
+ "3VRT_POINTS",
+ "3VRT_LINES",
+};
+
+static int print_prim_and_flags( int prim )
+{
+ int numverts;
+
+ if (NORMAL)
+ fprintf(stderr, " %s(%x): %s%s%s%s%s%s%s\n",
+ "prim flags",
+ prim,
+ ((prim & 0x30) == RADEON_CP_VC_CNTL_PRIM_WALK_IND) ? "IND," : "",
+ ((prim & 0x30) == RADEON_CP_VC_CNTL_PRIM_WALK_LIST) ? "LIST," : "",
+ ((prim & 0x30) == RADEON_CP_VC_CNTL_PRIM_WALK_RING) ? "RING," : "",
+ (prim & RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA) ? "RGBA," : "BGRA, ",
+ (prim & RADEON_CP_VC_CNTL_MAOS_ENABLE) ? "MAOS," : "",
+ (prim & RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE) ? "RADEON," : "",
+ (prim & RADEON_CP_VC_CNTL_TCL_ENABLE) ? "TCL," : "");
+
+ if ((prim & 0xf) > RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_LINE_LIST) {
+ fprintf(stderr, " *** Bad primitive: %x\n", prim & 0xf);
+ return -1;
+ }
+
+ numverts = prim>>16;
+
+ if (NORMAL)
+ fprintf(stderr, " prim: %s numverts %d\n", primname[prim&0xf], numverts);
+
+ switch (prim & 0xf) {
+ case RADEON_CP_VC_CNTL_PRIM_TYPE_NONE:
+ case RADEON_CP_VC_CNTL_PRIM_TYPE_POINT:
+ if (numverts < 1) {
+ fprintf(stderr, "Bad nr verts for line %d\n", numverts);
+ return -1;
+ }
+ break;
+ case RADEON_CP_VC_CNTL_PRIM_TYPE_LINE:
+ if ((numverts & 1) || numverts == 0) {
+ fprintf(stderr, "Bad nr verts for line %d\n", numverts);
+ return -1;
+ }
+ break;
+ case RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP:
+ if (numverts < 2) {
+ fprintf(stderr, "Bad nr verts for line_strip %d\n", numverts);
+ return -1;
+ }
+ break;
+ case RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST:
+ case RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_POINT_LIST:
+ case RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_LINE_LIST:
+ case RADEON_CP_VC_CNTL_PRIM_TYPE_RECT_LIST:
+ if (numverts % 3 || numverts == 0) {
+ fprintf(stderr, "Bad nr verts for tri %d\n", numverts);
+ return -1;
+ }
+ break;
+ case RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN:
+ case RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP:
+ if (numverts < 3) {
+ fprintf(stderr, "Bad nr verts for strip/fan %d\n", numverts);
+ return -1;
+ }
+ break;
+ default:
+ fprintf(stderr, "Bad primitive\n");
+ return -1;
+ }
+ return 0;
+}
+
+/* build in knowledge about each packet type
+ */
+static int radeon_emit_packet3( drmRadeonCmdBuffer *cmdbuf )
+{
+ int cmdsz;
+ int *cmd = (int *)cmdbuf->buf;
+ int *tmp;
+ int i, stride, size, start;
+
+ cmdsz = 2 + ((cmd[0] & RADEON_CP_PACKET_COUNT_MASK) >> 16);
+
+ if ((cmd[0] & RADEON_CP_PACKET_MASK) != RADEON_CP_PACKET3 ||
+ cmdsz * 4 > cmdbuf->bufsz ||
+ cmdsz > RADEON_CP_PACKET_MAX_DWORDS) {
+ fprintf(stderr, "Bad packet\n");
+ return -EINVAL;
+ }
+
+ switch( cmd[0] & ~RADEON_CP_PACKET_COUNT_MASK ) {
+ case RADEON_CP_PACKET3_NOP:
+ if (NORMAL)
+ fprintf(stderr, "PACKET3_NOP, %d dwords\n", cmdsz);
+ break;
+ case RADEON_CP_PACKET3_NEXT_CHAR:
+ if (NORMAL)
+ fprintf(stderr, "PACKET3_NEXT_CHAR, %d dwords\n", cmdsz);
+ break;
+ case RADEON_CP_PACKET3_PLY_NEXTSCAN:
+ if (NORMAL)
+ fprintf(stderr, "PACKET3_PLY_NEXTSCAN, %d dwords\n", cmdsz);
+ break;
+ case RADEON_CP_PACKET3_SET_SCISSORS:
+ if (NORMAL)
+ fprintf(stderr, "PACKET3_SET_SCISSORS, %d dwords\n", cmdsz);
+ break;
+ case RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM:
+ if (NORMAL)
+ fprintf(stderr, "PACKET3_3D_RNDR_GEN_INDX_PRIM, %d dwords\n",
+ cmdsz);
+ break;
+ case RADEON_CP_PACKET3_LOAD_MICROCODE:
+ if (NORMAL)
+ fprintf(stderr, "PACKET3_LOAD_MICROCODE, %d dwords\n", cmdsz);
+ break;
+ case RADEON_CP_PACKET3_WAIT_FOR_IDLE:
+ if (NORMAL)
+ fprintf(stderr, "PACKET3_WAIT_FOR_IDLE, %d dwords\n", cmdsz);
+ break;
+
+ case RADEON_CP_PACKET3_3D_DRAW_VBUF:
+ if (NORMAL)
+ fprintf(stderr, "PACKET3_3D_DRAW_VBUF, %d dwords\n", cmdsz);
+ print_vertex_format(cmd[1]);
+ print_prim_and_flags(cmd[2]);
+ break;
+
+ case RADEON_CP_PACKET3_3D_DRAW_IMMD:
+ if (NORMAL)
+ fprintf(stderr, "PACKET3_3D_DRAW_IMMD, %d dwords\n", cmdsz);
+ break;
+ case RADEON_CP_PACKET3_3D_DRAW_INDX: {
+ int neltdwords;
+ if (NORMAL)
+ fprintf(stderr, "PACKET3_3D_DRAW_INDX, %d dwords\n", cmdsz);
+ print_vertex_format(cmd[1]);
+ print_prim_and_flags(cmd[2]);
+ neltdwords = cmd[2]>>16;
+ neltdwords += neltdwords & 1;
+ neltdwords /= 2;
+ if (neltdwords + 3 != cmdsz)
+ fprintf(stderr, "Mismatch in DRAW_INDX, %d vs cmdsz %d\n",
+ neltdwords, cmdsz);
+ break;
+ }
+ case RADEON_CP_PACKET3_LOAD_PALETTE:
+ if (NORMAL)
+ fprintf(stderr, "PACKET3_LOAD_PALETTE, %d dwords\n", cmdsz);
+ break;
+ case RADEON_CP_PACKET3_3D_LOAD_VBPNTR:
+ if (NORMAL) {
+ fprintf(stderr, "PACKET3_3D_LOAD_VBPNTR, %d dwords\n", cmdsz);
+ fprintf(stderr, " nr arrays: %d\n", cmd[1]);
+ }
+
+ if (cmd[1]/2 + cmd[1]%2 != cmdsz - 3) {
+ fprintf(stderr, " ****** MISMATCH %d/%d *******\n",
+ cmd[1]/2 + cmd[1]%2 + 3, cmdsz);
+ return -EINVAL;
+ }
+
+ if (NORMAL) {
+ tmp = cmd+2;
+ for (i = 0 ; i < cmd[1] ; i++) {
+ if (i & 1) {
+ stride = (tmp[0]>>24) & 0xff;
+ size = (tmp[0]>>16) & 0xff;
+ start = tmp[2];
+ tmp += 3;
+ }
+ else {
+ stride = (tmp[0]>>8) & 0xff;
+ size = (tmp[0]) & 0xff;
+ start = tmp[1];
+ }
+ fprintf(stderr, " array %d: start 0x%x vsize %d vstride %d\n",
+ i, start, size, stride );
+ }
+ }
+ break;
+ case RADEON_CP_PACKET3_CNTL_PAINT:
+ if (NORMAL)
+ fprintf(stderr, "PACKET3_CNTL_PAINT, %d dwords\n", cmdsz);
+ break;
+ case RADEON_CP_PACKET3_CNTL_BITBLT:
+ if (NORMAL)
+ fprintf(stderr, "PACKET3_CNTL_BITBLT, %d dwords\n", cmdsz);
+ break;
+ case RADEON_CP_PACKET3_CNTL_SMALLTEXT:
+ if (NORMAL)
+ fprintf(stderr, "PACKET3_CNTL_SMALLTEXT, %d dwords\n", cmdsz);
+ break;
+ case RADEON_CP_PACKET3_CNTL_HOSTDATA_BLT:
+ if (NORMAL)
+ fprintf(stderr, "PACKET3_CNTL_HOSTDATA_BLT, %d dwords\n",
+ cmdsz);
+ break;
+ case RADEON_CP_PACKET3_CNTL_POLYLINE:
+ if (NORMAL)
+ fprintf(stderr, "PACKET3_CNTL_POLYLINE, %d dwords\n", cmdsz);
+ break;
+ case RADEON_CP_PACKET3_CNTL_POLYSCANLINES:
+ if (NORMAL)
+ fprintf(stderr, "PACKET3_CNTL_POLYSCANLINES, %d dwords\n",
+ cmdsz);
+ break;
+ case RADEON_CP_PACKET3_CNTL_PAINT_MULTI:
+ if (NORMAL)
+ fprintf(stderr, "PACKET3_CNTL_PAINT_MULTI, %d dwords\n",
+ cmdsz);
+ break;
+ case RADEON_CP_PACKET3_CNTL_BITBLT_MULTI:
+ if (NORMAL)
+ fprintf(stderr, "PACKET3_CNTL_BITBLT_MULTI, %d dwords\n",
+ cmdsz);
+ break;
+ case RADEON_CP_PACKET3_CNTL_TRANS_BITBLT:
+ if (NORMAL)
+ fprintf(stderr, "PACKET3_CNTL_TRANS_BITBLT, %d dwords\n",
+ cmdsz);
+ break;
+ default:
+ fprintf(stderr, "UNKNOWN PACKET, %d dwords\n", cmdsz);
+ break;
+ }
+
+ cmdbuf->buf += cmdsz * 4;
+ cmdbuf->bufsz -= cmdsz * 4;
+ return 0;
+}
+
+
+/* Check cliprects for bounds, then pass on to above:
+ */
+static int radeon_emit_packet3_cliprect( drmRadeonCmdBuffer *cmdbuf )
+{
+ XF86DRIClipRectRec *boxes = (XF86DRIClipRectRec *)cmdbuf->boxes;
+ int i = 0;
+
+ if (VERBOSE && total_changed) {
+ dump_state();
+ total_changed = 0;
+ }
+ else fprintf(stderr, "total_changed zero\n");
+
+ if (NORMAL) {
+ do {
+ if ( i < cmdbuf->nbox ) {
+ fprintf(stderr, "Emit box %d/%d %d,%d %d,%d\n",
+ i, cmdbuf->nbox,
+ boxes[i].x1, boxes[i].y1, boxes[i].x2, boxes[i].y2);
+ }
+ } while ( ++i < cmdbuf->nbox );
+ }
+
+ if (cmdbuf->nbox == 1)
+ cmdbuf->nbox = 0;
+
+ return radeon_emit_packet3( cmdbuf );
+}
+
+
+int radeonSanityCmdBuffer( radeonContextPtr rmesa,
+ int nbox,
+ XF86DRIClipRectRec *boxes )
+{
+ int idx;
+ drmRadeonCmdBuffer cmdbuf;
+ drmRadeonCmdHeader header;
+ static int inited = 0;
+
+ if (!inited) {
+ init_regs();
+ inited = 1;
+ }
+
+ cmdbuf.buf = rmesa->store.cmd_buf;
+ cmdbuf.bufsz = rmesa->store.cmd_used;
+ cmdbuf.boxes = (drmClipRect *)boxes;
+ cmdbuf.nbox = nbox;
+
+ while ( cmdbuf.bufsz >= sizeof(header) ) {
+
+ header.i = *(int *)cmdbuf.buf;
+ cmdbuf.buf += sizeof(header);
+ cmdbuf.bufsz -= sizeof(header);
+
+ switch (header.header.cmd_type) {
+ case RADEON_CMD_PACKET:
+ if (radeon_emit_packets( header, &cmdbuf )) {
+ fprintf(stderr,"radeon_emit_packets failed\n");
+ return -EINVAL;
+ }
+ break;
+
+ case RADEON_CMD_SCALARS:
+ if (radeon_emit_scalars( header, &cmdbuf )) {
+ fprintf(stderr,"radeon_emit_scalars failed\n");
+ return -EINVAL;
+ }
+ break;
+
+ case RADEON_CMD_SCALARS2:
+ if (radeon_emit_scalars2( header, &cmdbuf )) {
+ fprintf(stderr,"radeon_emit_scalars failed\n");
+ return -EINVAL;
+ }
+ break;
+
+ case RADEON_CMD_VECTORS:
+ if (radeon_emit_vectors( header, &cmdbuf )) {
+ fprintf(stderr,"radeon_emit_vectors failed\n");
+ return -EINVAL;
+ }
+ break;
+
+ case RADEON_CMD_DMA_DISCARD:
+ idx = header.dma.buf_idx;
+ if (NORMAL)
+ fprintf(stderr, "RADEON_CMD_DMA_DISCARD buf %d\n", idx);
+ bufs++;
+ break;
+
+ case RADEON_CMD_PACKET3:
+ if (radeon_emit_packet3( &cmdbuf )) {
+ fprintf(stderr,"radeon_emit_packet3 failed\n");
+ return -EINVAL;
+ }
+ break;
+
+ case RADEON_CMD_PACKET3_CLIP:
+ if (radeon_emit_packet3_cliprect( &cmdbuf )) {
+ fprintf(stderr,"radeon_emit_packet3_clip failed\n");
+ return -EINVAL;
+ }
+ break;
+
+ case RADEON_CMD_WAIT:
+ break;
+
+ default:
+ fprintf(stderr,"bad cmd_type %d at %p\n",
+ header.header.cmd_type,
+ cmdbuf.buf - sizeof(header));
+ return -EINVAL;
+ }
+ }
+
+ if (0)
+ {
+ static int n = 0;
+ n++;
+ if (n == 10) {
+ fprintf(stderr, "Bufs %d Total emitted %d real changes %d (%.2f%%)\n",
+ bufs,
+ total, total_changed,
+ ((float)total_changed/(float)total*100.0));
+ fprintf(stderr, "Total emitted per buf: %.2f\n",
+ (float)total/(float)bufs);
+ fprintf(stderr, "Real changes per buf: %.2f\n",
+ (float)total_changed/(float)bufs);
+
+ bufs = n = total = total_changed = 0;
+ }
+ }
+
+ return 0;
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_sanity.h b/src/mesa/drivers/dri/radeon/radeon_sanity.h
new file mode 100644
index 0000000000..58e8335dd6
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_sanity.h
@@ -0,0 +1,8 @@
+#ifndef RADEON_SANITY_H
+#define RADEON_SANITY_H
+
+extern int radeonSanityCmdBuffer( radeonContextPtr rmesa,
+ int nbox,
+ XF86DRIClipRectRec *boxes );
+
+#endif
diff --git a/src/mesa/drivers/dri/radeon/radeon_screen.c b/src/mesa/drivers/dri/radeon/radeon_screen.c
new file mode 100644
index 0000000000..ec8ed42d64
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_screen.c
@@ -0,0 +1,421 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_screen.c,v 1.6 2002/12/16 16:18:58 dawes 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 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 THE COPYRIGHT OWNER(S) 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:
+ * Kevin E. Martin <martin@valinux.com>
+ * Gareth Hughes <gareth@valinux.com>
+ *
+ */
+
+#include "glheader.h"
+#include "imports.h"
+
+#include "radeon_context.h"
+#include "radeon_screen.h"
+#include "radeon_macros.h"
+
+#include "utils.h"
+#include "context.h"
+#include "vblank.h"
+
+#ifndef _SOLO
+#include "glxextensions.h"
+#endif
+
+#if 1
+/* Including xf86PciInfo.h introduces a bunch of errors...
+ */
+#define PCI_CHIP_RADEON_QD 0x5144
+#define PCI_CHIP_RADEON_QE 0x5145
+#define PCI_CHIP_RADEON_QF 0x5146
+#define PCI_CHIP_RADEON_QG 0x5147
+
+#define PCI_CHIP_RADEON_QY 0x5159
+#define PCI_CHIP_RADEON_QZ 0x515A
+
+#define PCI_CHIP_RADEON_LW 0x4C57 /* mobility 7 - has tcl */
+
+#define PCI_CHIP_RADEON_LY 0x4C59
+#define PCI_CHIP_RADEON_LZ 0x4C5A
+
+#define PCI_CHIP_RV200_QW 0x5157 /* Radeon 7500 - not an R200 at all */
+#endif
+
+static int getSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo );
+
+/* Create the device specific screen private data struct.
+ */
+radeonScreenPtr radeonCreateScreen( __DRIscreenPrivate *sPriv )
+{
+ radeonScreenPtr screen;
+ RADEONDRIPtr dri_priv = (RADEONDRIPtr)sPriv->pDevPriv;
+
+ if ( ! driCheckDriDdxDrmVersions( sPriv, "Radeon", 4, 0, 4, 0, 1, 3 ) )
+ return NULL;
+
+ /* Allocate the private area */
+ screen = (radeonScreenPtr) CALLOC( sizeof(*screen) );
+ if ( !screen ) {
+ __driUtilMessage("%s: Could not allocate memory for screen structure",
+ __FUNCTION__);
+ return NULL;
+ }
+
+ if ( sPriv->drmMinor < 3 ||
+ getenv("RADEON_COMPAT")) {
+ fprintf( stderr, "Radeon DRI driver:\n\t"
+ "Compatibility mode for DRM driver version %d.%d.%d\n\t"
+ "TCL will be disabled, expect reduced performance\n\t"
+ "(prefer DRM radeon.o 1.3.x or newer)\n\t",
+ sPriv->drmMajor, sPriv->drmMinor, sPriv->drmPatch );
+ }
+
+
+ /* This is first since which regions we map depends on whether or
+ * not we are using a PCI card.
+ */
+ screen->IsPCI = dri_priv->IsPCI;
+
+ if (sPriv->drmMinor >= 3) {
+ int ret;
+ drmRadeonGetParam gp;
+
+ gp.param = RADEON_PARAM_AGP_BUFFER_OFFSET;
+ gp.value = &screen->agp_buffer_offset;
+
+ ret = drmCommandWriteRead( sPriv->fd, DRM_RADEON_GETPARAM,
+ &gp, sizeof(gp));
+ if (ret) {
+ fprintf(stderr, "drmRadeonGetParam (RADEON_PARAM_AGP_BUFFER_OFFSET): %d\n", ret);
+ return NULL;
+ }
+
+ if (sPriv->drmMinor >= 6) {
+ gp.param = RADEON_PARAM_IRQ_NR;
+ gp.value = &screen->irq;
+
+ ret = drmCommandWriteRead( sPriv->fd, DRM_RADEON_GETPARAM,
+ &gp, sizeof(gp));
+ if (ret) {
+ FREE( screen );
+ fprintf(stderr, "drmRadeonGetParam (RADEON_PARAM_IRQ_NR): %d\n", ret);
+ return NULL;
+ }
+ }
+ }
+
+ screen->mmio.handle = dri_priv->registerHandle;
+ screen->mmio.size = dri_priv->registerSize;
+ if ( drmMap( sPriv->fd,
+ screen->mmio.handle,
+ screen->mmio.size,
+ &screen->mmio.map ) ) {
+ FREE( screen );
+ __driUtilMessage("%s: drmMap failed\n", __FUNCTION__ );
+ return NULL;
+ }
+
+ screen->status.handle = dri_priv->statusHandle;
+ screen->status.size = dri_priv->statusSize;
+ if ( drmMap( sPriv->fd,
+ screen->status.handle,
+ screen->status.size,
+ &screen->status.map ) ) {
+ drmUnmap( screen->mmio.map, screen->mmio.size );
+ FREE( screen );
+ __driUtilMessage("%s: drmMap (2) failed\n", __FUNCTION__ );
+ return NULL;
+ }
+ screen->scratch = (__volatile__ CARD32 *)
+ ((GLubyte *)screen->status.map + RADEON_SCRATCH_REG_OFFSET);
+
+ screen->buffers = drmMapBufs( sPriv->fd );
+ if ( !screen->buffers ) {
+ drmUnmap( screen->status.map, screen->status.size );
+ drmUnmap( screen->mmio.map, screen->mmio.size );
+ FREE( screen );
+ __driUtilMessage("%s: drmMapBufs failed\n", __FUNCTION__ );
+ return NULL;
+ }
+
+ if ( !screen->IsPCI ) {
+ screen->agpTextures.handle = dri_priv->agpTexHandle;
+ screen->agpTextures.size = dri_priv->agpTexMapSize;
+ if ( drmMap( sPriv->fd,
+ screen->agpTextures.handle,
+ screen->agpTextures.size,
+ (drmAddressPtr)&screen->agpTextures.map ) ) {
+ drmUnmapBufs( screen->buffers );
+ drmUnmap( screen->status.map, screen->status.size );
+ drmUnmap( screen->mmio.map, screen->mmio.size );
+ FREE( screen );
+ __driUtilMessage("%s: IsPCI failed\n", __FUNCTION__);
+ return NULL;
+ }
+ }
+
+ screen->chipset = 0;
+ switch ( dri_priv->deviceID ) {
+ default:
+ fprintf(stderr, "unknown chip id, assuming full radeon support\n");
+ case PCI_CHIP_RADEON_QD:
+ case PCI_CHIP_RADEON_QE:
+ case PCI_CHIP_RADEON_QF:
+ case PCI_CHIP_RADEON_QG:
+ case PCI_CHIP_RV200_QW:
+ case PCI_CHIP_RADEON_LW:
+ screen->chipset |= RADEON_CHIPSET_TCL;
+ case PCI_CHIP_RADEON_QY:
+ case PCI_CHIP_RADEON_QZ:
+ case PCI_CHIP_RADEON_LY:
+ case PCI_CHIP_RADEON_LZ:
+ break;
+ }
+
+ screen->cpp = dri_priv->bpp / 8;
+ screen->AGPMode = dri_priv->AGPMode;
+
+ screen->frontOffset = dri_priv->frontOffset;
+ screen->frontPitch = dri_priv->frontPitch;
+ screen->backOffset = dri_priv->backOffset;
+ screen->backPitch = dri_priv->backPitch;
+ screen->depthOffset = dri_priv->depthOffset;
+ screen->depthPitch = dri_priv->depthPitch;
+
+ screen->texOffset[RADEON_CARD_HEAP] = dri_priv->textureOffset;
+ screen->texSize[RADEON_CARD_HEAP] = dri_priv->textureSize;
+ screen->logTexGranularity[RADEON_CARD_HEAP] =
+ dri_priv->log2TexGran;
+
+ if ( screen->IsPCI
+ || getenv( "RADEON_AGPTEXTURING_FORCE_DISABLE" ) ) {
+ screen->numTexHeaps = RADEON_NR_TEX_HEAPS - 1;
+ screen->texOffset[RADEON_AGP_HEAP] = 0;
+ screen->texSize[RADEON_AGP_HEAP] = 0;
+ screen->logTexGranularity[RADEON_AGP_HEAP] = 0;
+ } else {
+ screen->numTexHeaps = RADEON_NR_TEX_HEAPS;
+ screen->texOffset[RADEON_AGP_HEAP] =
+ dri_priv->agpTexOffset + RADEON_AGP_TEX_OFFSET;
+ screen->texSize[RADEON_AGP_HEAP] = dri_priv->agpTexMapSize;
+ screen->logTexGranularity[RADEON_AGP_HEAP] =
+ dri_priv->log2AGPTexGran;
+ }
+
+ screen->driScreen = sPriv;
+ screen->sarea_priv_offset = dri_priv->sarea_priv_offset;
+ return screen;
+}
+
+/* Destroy the device specific screen private data struct.
+ */
+void radeonDestroyScreen( __DRIscreenPrivate *sPriv )
+{
+ radeonScreenPtr screen = (radeonScreenPtr)sPriv->private;
+
+ if (!screen)
+ return;
+
+ if ( !screen->IsPCI ) {
+ drmUnmap( screen->agpTextures.map,
+ screen->agpTextures.size );
+ }
+ drmUnmapBufs( screen->buffers );
+ drmUnmap( screen->status.map, screen->status.size );
+ drmUnmap( screen->mmio.map, screen->mmio.size );
+
+ FREE( screen );
+ sPriv->private = NULL;
+}
+
+
+/* Initialize the driver specific screen private data.
+ */
+static GLboolean
+radeonInitDriver( __DRIscreenPrivate *sPriv )
+{
+ sPriv->private = (void *) radeonCreateScreen( sPriv );
+ if ( !sPriv->private ) {
+ radeonDestroyScreen( sPriv );
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+
+
+/* Create and initialize the Mesa and driver specific pixmap buffer
+ * data.
+ */
+static GLboolean
+radeonCreateBuffer( __DRIscreenPrivate *driScrnPriv,
+ __DRIdrawablePrivate *driDrawPriv,
+ const __GLcontextModes *mesaVis,
+ GLboolean isPixmap )
+{
+ if (isPixmap) {
+ return GL_FALSE; /* not implemented */
+ }
+ else {
+ const GLboolean swDepth = GL_FALSE;
+ const GLboolean swAlpha = GL_FALSE;
+ const GLboolean swAccum = mesaVis->accumRedBits > 0;
+ const GLboolean swStencil = mesaVis->stencilBits > 0 &&
+ mesaVis->depthBits != 24;
+ driDrawPriv->driverPrivate = (void *)
+ _mesa_create_framebuffer( mesaVis,
+ swDepth,
+ swStencil,
+ swAccum,
+ swAlpha );
+ return (driDrawPriv->driverPrivate != NULL);
+ }
+}
+
+
+static void
+radeonDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
+{
+ _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
+}
+
+
+
+
+/* Fullscreen mode isn't used for much -- could be a way to shrink
+ * front/back buffers & get more texture memory if the client has
+ * changed the video resolution.
+ *
+ * Pageflipping is now done automatically whenever there is a single
+ * 3d client.
+ */
+static GLboolean
+radeonOpenCloseFullScreen( __DRIcontextPrivate *driContextPriv )
+{
+ return GL_TRUE;
+}
+
+static struct __DriverAPIRec radeonAPI = {
+ .InitDriver = radeonInitDriver,
+ .DestroyScreen = radeonDestroyScreen,
+ .CreateContext = radeonCreateContext,
+ .DestroyContext = radeonDestroyContext,
+ .CreateBuffer = radeonCreateBuffer,
+ .DestroyBuffer = radeonDestroyBuffer,
+ .SwapBuffers = radeonSwapBuffers,
+ .MakeCurrent = radeonMakeCurrent,
+ .UnbindContext = radeonUnbindContext,
+ .OpenFullScreen = radeonOpenCloseFullScreen,
+ .CloseFullScreen = radeonOpenCloseFullScreen,
+ .GetSwapInfo = getSwapInfo,
+ .GetMSC = driGetMSC32,
+ .WaitForMSC = driWaitForMSC32,
+ .WaitForSBC = NULL,
+ .SwapBuffersMSC = NULL
+};
+
+
+
+/*
+ * This is the bootstrap function for the driver.
+ * The __driCreateScreen name is the symbol that libGL.so fetches.
+ * Return: pointer to a __DRIscreenPrivate.
+ */
+#ifndef _SOLO
+void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
+ int numConfigs, __GLXvisualConfig *config)
+{
+ __DRIscreenPrivate *psp;
+ psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &radeonAPI);
+ return (void *) psp;
+}
+#else
+void *__driCreateScreen(struct DRIDriverRec *driver,
+ struct DRIDriverContextRec *driverContext)
+{
+ __DRIscreenPrivate *psp;
+ psp = __driUtilCreateScreen(driver, driverContext, &radeonAPI);
+ return (void *) psp;
+}
+#endif
+
+
+#ifndef _SOLO
+/* This function is called by libGL.so as soon as libGL.so is loaded.
+ * This is where we'd register new extension functions with the dispatcher.
+ */
+void
+__driRegisterExtensions( void )
+{
+ PFNGLXENABLEEXTENSIONPROC glx_enable_extension;
+
+
+ if ( driCompareGLXAPIVersion( 20030317 ) >= 0 ) {
+ glx_enable_extension = (PFNGLXENABLEEXTENSIONPROC)
+ glXGetProcAddress( "__glXEnableExtension" );
+
+ if ( glx_enable_extension != NULL ) {
+ glx_enable_extension( "GLX_SGI_swap_control", GL_FALSE );
+ glx_enable_extension( "GLX_SGI_video_sync", GL_FALSE );
+ glx_enable_extension( "GLX_MESA_swap_control", GL_FALSE );
+ glx_enable_extension( "GLX_MESA_swap_frame_usage", GL_FALSE );
+ }
+ }
+}
+#endif
+
+
+/**
+ * Get information about previous buffer swaps.
+ */
+static int
+getSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo )
+{
+ radeonContextPtr rmesa;
+
+ if ( (dPriv == NULL) || (dPriv->driContextPriv == NULL)
+ || (dPriv->driContextPriv->driverPrivate == NULL)
+ || (sInfo == NULL) ) {
+ return -1;
+ }
+
+ rmesa = (radeonContextPtr) dPriv->driContextPriv->driverPrivate;
+ sInfo->swap_count = rmesa->swap_count;
+ sInfo->swap_ust = rmesa->swap_ust;
+ sInfo->swap_missed_count = rmesa->swap_missed_count;
+
+ sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0)
+ ? driCalculateSwapUsage( dPriv, 0, rmesa->swap_missed_ust )
+ : 0.0;
+
+ return 0;
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_screen.h b/src/mesa/drivers/dri/radeon/radeon_screen.h
new file mode 100644
index 0000000000..2c69d8657a
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_screen.h
@@ -0,0 +1,101 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_screen.h,v 1.5 2002/12/16 16:18:58 dawes 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 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 THE COPYRIGHT OWNER(S) 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:
+ * Kevin E. Martin <martin@valinux.com>
+ * Gareth Hughes <gareth@valinux.com>
+ */
+
+#ifndef __RADEON_SCREEN_H__
+#define __RADEON_SCREEN_H__
+
+#ifdef GLX_DIRECT_RENDERING
+
+/*
+ * IMPORTS: these headers contain all the DRI, X and kernel-related
+ * definitions that we need.
+ */
+#include "dri_util.h"
+#include "radeon_common.h"
+#include "radeon_dri.h"
+#include "radeon_reg.h"
+#include "radeon_sarea.h"
+
+
+typedef struct {
+ drmHandle handle; /* Handle to the DRM region */
+ drmSize size; /* Size of the DRM region */
+ drmAddress map; /* Mapping of the DRM region */
+} radeonRegionRec, *radeonRegionPtr;
+
+/* chipset features */
+#define RADEON_CHIPSET_TCL (1 << 0)
+
+typedef struct {
+
+ int chipset;
+ int cpp;
+ int IsPCI; /* Current card is a PCI card */
+ int 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;
+
+ /* Shared texture data */
+ int numTexHeaps;
+ int texOffset[RADEON_NR_TEX_HEAPS];
+ int texSize[RADEON_NR_TEX_HEAPS];
+ int logTexGranularity[RADEON_NR_TEX_HEAPS];
+
+ radeonRegionRec mmio;
+ radeonRegionRec status;
+ radeonRegionRec agpTextures;
+
+ drmBufMapPtr buffers;
+
+ __volatile__ CARD32 *scratch;
+
+ __DRIscreenPrivate *driScreen;
+ unsigned int sarea_priv_offset;
+ unsigned int agp_buffer_offset; /* offset in card memory space */
+} radeonScreenRec, *radeonScreenPtr;
+
+extern radeonScreenPtr radeonCreateScreen( __DRIscreenPrivate *sPriv );
+extern void radeonDestroyScreen( __DRIscreenPrivate *sPriv );
+
+#endif
+#endif /* __RADEON_SCREEN_H__ */
diff --git a/src/mesa/drivers/dri/radeon/radeon_span.c b/src/mesa/drivers/dri/radeon/radeon_span.c
new file mode 100644
index 0000000000..029d7cd8ee
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_span.c
@@ -0,0 +1,415 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_span.c,v 1.6 2002/10/30 12:51:56 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 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 THE COPYRIGHT OWNER(S) 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:
+ * Kevin E. Martin <martin@valinux.com>
+ * Gareth Hughes <gareth@valinux.com>
+ * Keith Whitwell <keith@tungstengraphics.com>
+ *
+ */
+
+#include "glheader.h"
+#include "swrast/swrast.h"
+
+#include "radeon_context.h"
+#include "radeon_ioctl.h"
+#include "radeon_state.h"
+#include "radeon_span.h"
+#include "radeon_tex.h"
+
+#define DBG 0
+
+#define LOCAL_VARS \
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \
+ radeonScreenPtr radeonScreen = rmesa->radeonScreen; \
+ __DRIscreenPrivate *sPriv = rmesa->dri.screen; \
+ __DRIdrawablePrivate *dPriv = rmesa->dri.drawable; \
+ GLuint pitch = radeonScreen->frontPitch * radeonScreen->cpp; \
+ GLuint height = dPriv->h; \
+ char *buf = (char *)(sPriv->pFB + \
+ rmesa->state.color.drawOffset + \
+ (dPriv->x * radeonScreen->cpp) + \
+ (dPriv->y * pitch)); \
+ char *read_buf = (char *)(sPriv->pFB + \
+ rmesa->state.pixel.readOffset + \
+ (dPriv->x * radeonScreen->cpp) + \
+ (dPriv->y * pitch)); \
+ GLuint p; \
+ (void) read_buf; (void) buf; (void) p
+
+#define LOCAL_DEPTH_VARS \
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \
+ radeonScreenPtr radeonScreen = rmesa->radeonScreen; \
+ __DRIscreenPrivate *sPriv = rmesa->dri.screen; \
+ __DRIdrawablePrivate *dPriv = rmesa->dri.drawable; \
+ GLuint height = dPriv->h; \
+ GLuint xo = dPriv->x; \
+ GLuint yo = dPriv->y; \
+ char *buf = (char *)(sPriv->pFB + radeonScreen->depthOffset); \
+ (void) buf
+
+#define LOCAL_STENCIL_VARS LOCAL_DEPTH_VARS
+
+
+#define CLIPPIXEL( _x, _y ) \
+ ((_x >= minx) && (_x < maxx) && (_y >= miny) && (_y < maxy))
+
+
+#define CLIPSPAN( _x, _y, _n, _x1, _n1, _i ) \
+ if ( _y < miny || _y >= maxy ) { \
+ _n1 = 0, _x1 = x; \
+ } else { \
+ _n1 = _n; \
+ _x1 = _x; \
+ if ( _x1 < minx ) _i += (minx-_x1), n1 -= (minx-_x1), _x1 = minx; \
+ if ( _x1 + _n1 >= maxx ) n1 -= (_x1 + n1 - maxx); \
+ }
+
+#define Y_FLIP( _y ) (height - _y - 1)
+
+
+#define HW_LOCK()
+
+#define HW_CLIPLOOP() \
+ do { \
+ __DRIdrawablePrivate *dPriv = rmesa->dri.drawable; \
+ int _nc = dPriv->numClipRects; \
+ \
+ while ( _nc-- ) { \
+ int minx = dPriv->pClipRects[_nc].x1 - dPriv->x; \
+ int miny = dPriv->pClipRects[_nc].y1 - dPriv->y; \
+ int maxx = dPriv->pClipRects[_nc].x2 - dPriv->x; \
+ int maxy = dPriv->pClipRects[_nc].y2 - dPriv->y;
+
+#define HW_ENDCLIPLOOP() \
+ } \
+ } while (0)
+
+#define HW_UNLOCK()
+
+
+
+/* ================================================================
+ * Color buffer
+ */
+
+/* 16 bit, RGB565 color spanline and pixel functions
+ */
+#define INIT_MONO_PIXEL(p, color) \
+ p = PACK_COLOR_565( color[0], color[1], color[2] )
+
+#define WRITE_RGBA( _x, _y, r, g, b, a ) \
+ *(GLushort *)(buf + _x*2 + _y*pitch) = ((((int)r & 0xf8) << 8) | \
+ (((int)g & 0xfc) << 3) | \
+ (((int)b & 0xf8) >> 3))
+
+#define WRITE_PIXEL( _x, _y, p ) \
+ *(GLushort *)(buf + _x*2 + _y*pitch) = p
+
+#define READ_RGBA( rgba, _x, _y ) \
+ do { \
+ GLushort p = *(GLushort *)(read_buf + _x*2 + _y*pitch); \
+ rgba[0] = ((p >> 8) & 0xf8) * 255 / 0xf8; \
+ rgba[1] = ((p >> 3) & 0xfc) * 255 / 0xfc; \
+ rgba[2] = ((p << 3) & 0xf8) * 255 / 0xf8; \
+ rgba[3] = 0xff; \
+ } while (0)
+
+#define TAG(x) radeon##x##_RGB565
+#include "spantmp.h"
+
+/* 32 bit, ARGB8888 color spanline and pixel functions
+ */
+#undef INIT_MONO_PIXEL
+#define INIT_MONO_PIXEL(p, color) \
+ p = PACK_COLOR_8888( color[3], color[0], color[1], color[2] )
+
+#define WRITE_RGBA( _x, _y, r, g, b, a ) \
+do { \
+ *(GLuint *)(buf + _x*4 + _y*pitch) = ((b << 0) | \
+ (g << 8) | \
+ (r << 16) | \
+ (a << 24) ); \
+} while (0)
+
+#define WRITE_PIXEL( _x, _y, p ) \
+do { \
+ *(GLuint *)(buf + _x*4 + _y*pitch) = p; \
+} while (0)
+
+#define READ_RGBA( rgba, _x, _y ) \
+do { \
+ volatile GLuint *ptr = (volatile GLuint *)(read_buf + _x*4 + _y*pitch); \
+ GLuint p = *ptr; \
+ rgba[0] = (p >> 16) & 0xff; \
+ rgba[1] = (p >> 8) & 0xff; \
+ rgba[2] = (p >> 0) & 0xff; \
+ rgba[3] = (p >> 24) & 0xff; \
+} while (0)
+
+#define TAG(x) radeon##x##_ARGB8888
+#include "spantmp.h"
+
+
+
+/* ================================================================
+ * Depth buffer
+ */
+
+/* The Radeon family has depth tiling on all the time, so we have to convert
+ * the x,y coordinates into the memory bus address (mba) in the same
+ * manner as the engine. In each case, the linear block address (ba)
+ * is calculated, and then wired with x and y to produce the final
+ * memory address.
+ */
+
+static GLuint radeon_mba_z32( radeonContextPtr rmesa,
+ GLint x, GLint y )
+{
+ GLuint pitch = rmesa->radeonScreen->frontPitch;
+ GLuint ba, address = 0; /* a[0..1] = 0 */
+
+ ba = (y / 16) * (pitch / 16) + (x / 16);
+
+ address |= (x & 0x7) << 2; /* a[2..4] = x[0..2] */
+ address |= (y & 0x3) << 5; /* a[5..6] = y[0..1] */
+ address |=
+ (((x & 0x10) >> 2) ^ (y & 0x4)) << 5; /* a[7] = x[4] ^ y[2] */
+ address |= (ba & 0x3) << 8; /* a[8..9] = ba[0..1] */
+
+ address |= (y & 0x8) << 7; /* a[10] = y[3] */
+ address |=
+ (((x & 0x8) << 1) ^ (y & 0x10)) << 7; /* a[11] = x[3] ^ y[4] */
+ address |= (ba & ~0x3) << 10; /* a[12..] = ba[2..] */
+
+ return address;
+}
+
+static __inline GLuint radeon_mba_z16( radeonContextPtr rmesa, GLint x, GLint y )
+{
+ GLuint pitch = rmesa->radeonScreen->frontPitch;
+ GLuint ba, address = 0; /* a[0] = 0 */
+
+ ba = (y / 16) * (pitch / 32) + (x / 32);
+
+ address |= (x & 0x7) << 1; /* a[1..3] = x[0..2] */
+ address |= (y & 0x7) << 4; /* a[4..6] = y[0..2] */
+ address |= (x & 0x8) << 4; /* a[7] = x[3] */
+ address |= (ba & 0x3) << 8; /* a[8..9] = ba[0..1] */
+ address |= (y & 0x8) << 7; /* a[10] = y[3] */
+ address |= ((x & 0x10) ^ (y & 0x10)) << 7; /* a[11] = x[4] ^ y[4] */
+ address |= (ba & ~0x3) << 10; /* a[12..] = ba[2..] */
+
+ return address;
+}
+
+
+/* 16-bit depth buffer functions
+ */
+#define WRITE_DEPTH( _x, _y, d ) \
+ *(GLushort *)(buf + radeon_mba_z16( rmesa, _x + xo, _y + yo )) = d;
+
+#define READ_DEPTH( d, _x, _y ) \
+ d = *(GLushort *)(buf + radeon_mba_z16( rmesa, _x + xo, _y + yo ));
+
+#define TAG(x) radeon##x##_16
+#include "depthtmp.h"
+
+/* 24 bit depth, 8 bit stencil depthbuffer functions
+ */
+#define WRITE_DEPTH( _x, _y, d ) \
+do { \
+ GLuint offset = radeon_mba_z32( rmesa, _x + xo, _y + yo ); \
+ GLuint tmp = *(GLuint *)(buf + offset); \
+ tmp &= 0xff000000; \
+ tmp |= ((d) & 0x00ffffff); \
+ *(GLuint *)(buf + offset) = tmp; \
+} while (0)
+
+#define READ_DEPTH( d, _x, _y ) \
+ d = *(GLuint *)(buf + radeon_mba_z32( rmesa, _x + xo, \
+ _y + yo )) & 0x00ffffff;
+
+#define TAG(x) radeon##x##_24_8
+#include "depthtmp.h"
+
+
+/* ================================================================
+ * Stencil buffer
+ */
+
+/* 24 bit depth, 8 bit stencil depthbuffer functions
+ */
+#define WRITE_STENCIL( _x, _y, d ) \
+do { \
+ GLuint offset = radeon_mba_z32( rmesa, _x + xo, _y + yo ); \
+ GLuint tmp = *(GLuint *)(buf + offset); \
+ tmp &= 0x00ffffff; \
+ tmp |= (((d) & 0xff) << 24); \
+ *(GLuint *)(buf + offset) = tmp; \
+} while (0)
+
+#define READ_STENCIL( d, _x, _y ) \
+do { \
+ GLuint offset = radeon_mba_z32( rmesa, _x + xo, _y + yo ); \
+ GLuint tmp = *(GLuint *)(buf + offset); \
+ tmp &= 0xff000000; \
+ d = tmp >> 24; \
+} while (0)
+
+#define TAG(x) radeon##x##_24_8
+#include "stenciltmp.h"
+
+
+/*
+ * This function is called to specify which buffer to read and write
+ * for software rasterization (swrast) fallbacks. This doesn't necessarily
+ * correspond to glDrawBuffer() or glReadBuffer() calls.
+ */
+static void radeonSetBuffer( GLcontext *ctx,
+ GLframebuffer *colorBuffer,
+ GLuint bufferBit )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ switch ( bufferBit ) {
+ case FRONT_LEFT_BIT:
+ if ( rmesa->sarea->pfCurrentPage == 1 ) {
+ rmesa->state.pixel.readOffset = rmesa->radeonScreen->backOffset;
+ rmesa->state.pixel.readPitch = rmesa->radeonScreen->backPitch;
+ rmesa->state.color.drawOffset = rmesa->radeonScreen->backOffset;
+ rmesa->state.color.drawPitch = rmesa->radeonScreen->backPitch;
+ } else {
+ rmesa->state.pixel.readOffset = rmesa->radeonScreen->frontOffset;
+ rmesa->state.pixel.readPitch = rmesa->radeonScreen->frontPitch;
+ rmesa->state.color.drawOffset = rmesa->radeonScreen->frontOffset;
+ rmesa->state.color.drawPitch = rmesa->radeonScreen->frontPitch;
+ }
+ break;
+ case BACK_LEFT_BIT:
+ if ( rmesa->sarea->pfCurrentPage == 1 ) {
+ rmesa->state.pixel.readOffset = rmesa->radeonScreen->frontOffset;
+ rmesa->state.pixel.readPitch = rmesa->radeonScreen->frontPitch;
+ rmesa->state.color.drawOffset = rmesa->radeonScreen->frontOffset;
+ rmesa->state.color.drawPitch = rmesa->radeonScreen->frontPitch;
+ } else {
+ rmesa->state.pixel.readOffset = rmesa->radeonScreen->backOffset;
+ rmesa->state.pixel.readPitch = rmesa->radeonScreen->backPitch;
+ rmesa->state.color.drawOffset = rmesa->radeonScreen->backOffset;
+ rmesa->state.color.drawPitch = rmesa->radeonScreen->backPitch;
+ }
+ break;
+ default:
+ assert(0);
+ break;
+ }
+}
+
+/* Move locking out to get reasonable span performance (10x better
+ * than doing this in HW_LOCK above). WaitForIdle() is the main
+ * culprit.
+ */
+
+static void radeonSpanRenderStart( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+
+ RADEON_FIREVERTICES( rmesa );
+ LOCK_HARDWARE( rmesa );
+ radeonWaitForIdleLocked( rmesa );
+}
+
+static void radeonSpanRenderFinish( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+ _swrast_flush( ctx );
+ UNLOCK_HARDWARE( rmesa );
+}
+
+void radeonInitSpanFuncs( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx);
+
+ swdd->SetBuffer = radeonSetBuffer;
+
+ switch ( rmesa->radeonScreen->cpp ) {
+ case 2:
+ swdd->WriteRGBASpan = radeonWriteRGBASpan_RGB565;
+ swdd->WriteRGBSpan = radeonWriteRGBSpan_RGB565;
+ swdd->WriteMonoRGBASpan = radeonWriteMonoRGBASpan_RGB565;
+ swdd->WriteRGBAPixels = radeonWriteRGBAPixels_RGB565;
+ swdd->WriteMonoRGBAPixels = radeonWriteMonoRGBAPixels_RGB565;
+ swdd->ReadRGBASpan = radeonReadRGBASpan_RGB565;
+ swdd->ReadRGBAPixels = radeonReadRGBAPixels_RGB565;
+ break;
+
+ case 4:
+ swdd->WriteRGBASpan = radeonWriteRGBASpan_ARGB8888;
+ swdd->WriteRGBSpan = radeonWriteRGBSpan_ARGB8888;
+ swdd->WriteMonoRGBASpan = radeonWriteMonoRGBASpan_ARGB8888;
+ swdd->WriteRGBAPixels = radeonWriteRGBAPixels_ARGB8888;
+ swdd->WriteMonoRGBAPixels = radeonWriteMonoRGBAPixels_ARGB8888;
+ swdd->ReadRGBASpan = radeonReadRGBASpan_ARGB8888;
+ swdd->ReadRGBAPixels = radeonReadRGBAPixels_ARGB8888;
+ break;
+
+ default:
+ break;
+ }
+
+ switch ( rmesa->glCtx->Visual.depthBits ) {
+ case 16:
+ swdd->ReadDepthSpan = radeonReadDepthSpan_16;
+ swdd->WriteDepthSpan = radeonWriteDepthSpan_16;
+ swdd->ReadDepthPixels = radeonReadDepthPixels_16;
+ swdd->WriteDepthPixels = radeonWriteDepthPixels_16;
+ break;
+
+ case 24:
+ swdd->ReadDepthSpan = radeonReadDepthSpan_24_8;
+ swdd->WriteDepthSpan = radeonWriteDepthSpan_24_8;
+ swdd->ReadDepthPixels = radeonReadDepthPixels_24_8;
+ swdd->WriteDepthPixels = radeonWriteDepthPixels_24_8;
+
+ swdd->ReadStencilSpan = radeonReadStencilSpan_24_8;
+ swdd->WriteStencilSpan = radeonWriteStencilSpan_24_8;
+ swdd->ReadStencilPixels = radeonReadStencilPixels_24_8;
+ swdd->WriteStencilPixels = radeonWriteStencilPixels_24_8;
+ break;
+
+ default:
+ break;
+ }
+
+ swdd->SpanRenderStart = radeonSpanRenderStart;
+ swdd->SpanRenderFinish = radeonSpanRenderFinish;
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_span.h b/src/mesa/drivers/dri/radeon/radeon_span.h
new file mode 100644
index 0000000000..011e8eff57
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_span.h
@@ -0,0 +1,45 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_span.h,v 1.2 2002/02/22 21:45:01 dawes 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 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 THE COPYRIGHT OWNER(S) 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:
+ * Kevin E. Martin <martin@valinux.com>
+ * Gareth Hughes <gareth@valinux.com>
+ */
+
+#ifndef __RADEON_SPAN_H__
+#define __RADEON_SPAN_H__
+
+#ifdef GLX_DIRECT_RENDERING
+
+extern void radeonInitSpanFuncs( GLcontext *ctx );
+
+#endif
+#endif
diff --git a/src/mesa/drivers/dri/radeon/radeon_state.c b/src/mesa/drivers/dri/radeon/radeon_state.c
new file mode 100644
index 0000000000..7b1bbe75fd
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_state.c
@@ -0,0 +1,2211 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_state.c,v 1.8 2002/12/16 16:18:58 dawes Exp $ */
+/**************************************************************************
+
+Copyright 2000, 2001 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 THE COPYRIGHT OWNER(S) 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:
+ * Gareth Hughes <gareth@valinux.com>
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "glheader.h"
+#include "imports.h"
+#include "api_arrayelt.h"
+#include "enums.h"
+#include "colormac.h"
+#include "state.h"
+
+#include "swrast/swrast.h"
+#include "array_cache/acache.h"
+#include "tnl/tnl.h"
+#include "tnl/t_pipeline.h"
+#include "main/light.h"
+#include "swrast_setup/swrast_setup.h"
+
+#include "radeon_context.h"
+#include "radeon_ioctl.h"
+#include "radeon_state.h"
+#include "radeon_tcl.h"
+#include "radeon_tex.h"
+#include "radeon_swtcl.h"
+#include "radeon_vtxfmt.h"
+
+/* =============================================================
+ * Alpha blending
+ */
+
+static void radeonAlphaFunc( GLcontext *ctx, GLenum func, GLfloat ref )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ int pp_misc = rmesa->hw.ctx.cmd[CTX_PP_MISC];
+ GLubyte refByte;
+
+ CLAMPED_FLOAT_TO_UBYTE(refByte, ref);
+
+ RADEON_STATECHANGE( rmesa, ctx );
+
+ pp_misc &= ~(RADEON_ALPHA_TEST_OP_MASK | RADEON_REF_ALPHA_MASK);
+ pp_misc |= (refByte & RADEON_REF_ALPHA_MASK);
+
+ switch ( func ) {
+ case GL_NEVER:
+ pp_misc |= RADEON_ALPHA_TEST_FAIL;
+ break;
+ case GL_LESS:
+ pp_misc |= RADEON_ALPHA_TEST_LESS;
+ break;
+ case GL_EQUAL:
+ pp_misc |= RADEON_ALPHA_TEST_EQUAL;
+ break;
+ case GL_LEQUAL:
+ pp_misc |= RADEON_ALPHA_TEST_LEQUAL;
+ break;
+ case GL_GREATER:
+ pp_misc |= RADEON_ALPHA_TEST_GREATER;
+ break;
+ case GL_NOTEQUAL:
+ pp_misc |= RADEON_ALPHA_TEST_NEQUAL;
+ break;
+ case GL_GEQUAL:
+ pp_misc |= RADEON_ALPHA_TEST_GEQUAL;
+ break;
+ case GL_ALWAYS:
+ pp_misc |= RADEON_ALPHA_TEST_PASS;
+ break;
+ }
+
+ rmesa->hw.ctx.cmd[CTX_PP_MISC] = pp_misc;
+}
+
+static void radeonBlendEquation( GLcontext *ctx, GLenum mode )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLuint b = rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] & ~RADEON_COMB_FCN_MASK;
+ GLboolean fallback = GL_FALSE;
+
+ switch ( mode ) {
+ case GL_FUNC_ADD:
+ case GL_LOGIC_OP:
+ b |= RADEON_COMB_FCN_ADD_CLAMP;
+ break;
+
+ case GL_FUNC_SUBTRACT:
+ b |= RADEON_COMB_FCN_SUB_CLAMP;
+ break;
+
+ default:
+ if (ctx->Color.BlendEnabled)
+ fallback = GL_TRUE;
+ else
+ b |= RADEON_COMB_FCN_ADD_CLAMP;
+ break;
+ }
+
+ FALLBACK( rmesa, RADEON_FALLBACK_BLEND_EQ, fallback );
+ if ( !fallback ) {
+ RADEON_STATECHANGE( rmesa, ctx );
+ rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = b;
+ if ( ctx->Color.ColorLogicOpEnabled ) {
+ rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_ROP_ENABLE;
+ } else {
+ rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ROP_ENABLE;
+ }
+ }
+}
+
+static void radeonBlendFunc( GLcontext *ctx, GLenum sfactor, GLenum dfactor )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLuint b = rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] &
+ ~(RADEON_SRC_BLEND_MASK | RADEON_DST_BLEND_MASK);
+ GLboolean fallback = GL_FALSE;
+
+ switch ( ctx->Color.BlendSrcRGB ) {
+ case GL_ZERO:
+ b |= RADEON_SRC_BLEND_GL_ZERO;
+ break;
+ case GL_ONE:
+ b |= RADEON_SRC_BLEND_GL_ONE;
+ break;
+ case GL_DST_COLOR:
+ b |= RADEON_SRC_BLEND_GL_DST_COLOR;
+ break;
+ case GL_ONE_MINUS_DST_COLOR:
+ b |= RADEON_SRC_BLEND_GL_ONE_MINUS_DST_COLOR;
+ break;
+ case GL_SRC_COLOR:
+ b |= RADEON_SRC_BLEND_GL_SRC_COLOR;
+ break;
+ case GL_ONE_MINUS_SRC_COLOR:
+ b |= RADEON_SRC_BLEND_GL_ONE_MINUS_SRC_COLOR;
+ break;
+ case GL_SRC_ALPHA:
+ b |= RADEON_SRC_BLEND_GL_SRC_ALPHA;
+ break;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ b |= RADEON_SRC_BLEND_GL_ONE_MINUS_SRC_ALPHA;
+ break;
+ case GL_DST_ALPHA:
+ b |= RADEON_SRC_BLEND_GL_DST_ALPHA;
+ break;
+ case GL_ONE_MINUS_DST_ALPHA:
+ b |= RADEON_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA;
+ break;
+ case GL_SRC_ALPHA_SATURATE:
+ b |= RADEON_SRC_BLEND_GL_SRC_ALPHA_SATURATE;
+ break;
+ case GL_CONSTANT_COLOR:
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ case GL_CONSTANT_ALPHA:
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ if (ctx->Color.BlendEnabled)
+ fallback = GL_TRUE;
+ else
+ b |= RADEON_SRC_BLEND_GL_ONE;
+ break;
+ default:
+ break;
+ }
+
+ switch ( ctx->Color.BlendDstRGB ) {
+ case GL_ZERO:
+ b |= RADEON_DST_BLEND_GL_ZERO;
+ break;
+ case GL_ONE:
+ b |= RADEON_DST_BLEND_GL_ONE;
+ break;
+ case GL_SRC_COLOR:
+ b |= RADEON_DST_BLEND_GL_SRC_COLOR;
+ break;
+ case GL_ONE_MINUS_SRC_COLOR:
+ b |= RADEON_DST_BLEND_GL_ONE_MINUS_SRC_COLOR;
+ break;
+ case GL_SRC_ALPHA:
+ b |= RADEON_DST_BLEND_GL_SRC_ALPHA;
+ break;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ b |= RADEON_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA;
+ break;
+ case GL_DST_COLOR:
+ b |= RADEON_DST_BLEND_GL_DST_COLOR;
+ break;
+ case GL_ONE_MINUS_DST_COLOR:
+ b |= RADEON_DST_BLEND_GL_ONE_MINUS_DST_COLOR;
+ break;
+ case GL_DST_ALPHA:
+ b |= RADEON_DST_BLEND_GL_DST_ALPHA;
+ break;
+ case GL_ONE_MINUS_DST_ALPHA:
+ b |= RADEON_DST_BLEND_GL_ONE_MINUS_DST_ALPHA;
+ break;
+ case GL_CONSTANT_COLOR:
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ case GL_CONSTANT_ALPHA:
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ if (ctx->Color.BlendEnabled)
+ fallback = GL_TRUE;
+ else
+ b |= RADEON_DST_BLEND_GL_ZERO;
+ break;
+ default:
+ break;
+ }
+
+ FALLBACK( rmesa, RADEON_FALLBACK_BLEND_FUNC, fallback );
+ if ( !fallback ) {
+ RADEON_STATECHANGE( rmesa, ctx );
+ rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = b;
+ }
+}
+
+static void radeonBlendFuncSeparate( GLcontext *ctx,
+ GLenum sfactorRGB, GLenum dfactorRGB,
+ GLenum sfactorA, GLenum dfactorA )
+{
+ radeonBlendFunc( ctx, sfactorRGB, dfactorRGB );
+}
+
+
+/* =============================================================
+ * Depth testing
+ */
+
+static void radeonDepthFunc( GLcontext *ctx, GLenum func )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ RADEON_STATECHANGE( rmesa, ctx );
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~RADEON_Z_TEST_MASK;
+
+ switch ( ctx->Depth.Func ) {
+ case GL_NEVER:
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_NEVER;
+ break;
+ case GL_LESS:
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_LESS;
+ break;
+ case GL_EQUAL:
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_EQUAL;
+ break;
+ case GL_LEQUAL:
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_LEQUAL;
+ break;
+ case GL_GREATER:
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_GREATER;
+ break;
+ case GL_NOTEQUAL:
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_NEQUAL;
+ break;
+ case GL_GEQUAL:
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_GEQUAL;
+ break;
+ case GL_ALWAYS:
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_ALWAYS;
+ break;
+ }
+}
+
+
+static void radeonDepthMask( GLcontext *ctx, GLboolean flag )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ RADEON_STATECHANGE( rmesa, ctx );
+
+ if ( ctx->Depth.Mask ) {
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_WRITE_ENABLE;
+ } else {
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~RADEON_Z_WRITE_ENABLE;
+ }
+}
+
+static void radeonClearDepth( GLcontext *ctx, GLclampd d )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLuint format = (rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &
+ RADEON_DEPTH_FORMAT_MASK);
+
+ switch ( format ) {
+ case RADEON_DEPTH_FORMAT_16BIT_INT_Z:
+ rmesa->state.depth.clear = d * 0x0000ffff;
+ break;
+ case RADEON_DEPTH_FORMAT_24BIT_INT_Z:
+ rmesa->state.depth.clear = d * 0x00ffffff;
+ break;
+ }
+}
+
+
+/* =============================================================
+ * Fog
+ */
+
+
+static void radeonFogfv( GLcontext *ctx, GLenum pname, const GLfloat *param )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ union { int i; float f; } c, d;
+ GLchan col[4];
+
+ c.i = rmesa->hw.fog.cmd[FOG_C];
+ d.i = rmesa->hw.fog.cmd[FOG_D];
+
+ switch (pname) {
+ case GL_FOG_MODE:
+ if (!ctx->Fog.Enabled)
+ return;
+ RADEON_STATECHANGE(rmesa, tcl);
+ rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_TCL_FOG_MASK;
+ switch (ctx->Fog.Mode) {
+ case GL_LINEAR:
+ rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_LINEAR;
+ if (ctx->Fog.Start == ctx->Fog.End) {
+ c.f = 1.0F;
+ d.f = 1.0F;
+ }
+ else {
+ c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start);
+ d.f = 1.0/(ctx->Fog.End-ctx->Fog.Start);
+ }
+ break;
+ case GL_EXP:
+ rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_EXP;
+ c.f = 0.0;
+ d.f = ctx->Fog.Density;
+ break;
+ case GL_EXP2:
+ rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_EXP2;
+ c.f = 0.0;
+ d.f = -(ctx->Fog.Density * ctx->Fog.Density);
+ break;
+ default:
+ return;
+ }
+ break;
+ case GL_FOG_DENSITY:
+ switch (ctx->Fog.Mode) {
+ case GL_EXP:
+ c.f = 0.0;
+ d.f = ctx->Fog.Density;
+ break;
+ case GL_EXP2:
+ c.f = 0.0;
+ d.f = -(ctx->Fog.Density * ctx->Fog.Density);
+ break;
+ default:
+ break;
+ }
+ break;
+ case GL_FOG_START:
+ case GL_FOG_END:
+ if (ctx->Fog.Mode == GL_LINEAR) {
+ if (ctx->Fog.Start == ctx->Fog.End) {
+ c.f = 1.0F;
+ d.f = 1.0F;
+ } else {
+ c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start);
+ d.f = 1.0/(ctx->Fog.End-ctx->Fog.Start);
+ }
+ }
+ break;
+ case GL_FOG_COLOR:
+ RADEON_STATECHANGE( rmesa, ctx );
+ UNCLAMPED_FLOAT_TO_RGB_CHAN( col, ctx->Fog.Color );
+ rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] =
+ radeonPackColor( 4, col[0], col[1], col[2], 0 );
+ break;
+ case GL_FOG_COORDINATE_SOURCE_EXT:
+ /* What to do?
+ */
+ break;
+ default:
+ return;
+ }
+
+ if (c.i != rmesa->hw.fog.cmd[FOG_C] || d.i != rmesa->hw.fog.cmd[FOG_D]) {
+ RADEON_STATECHANGE( rmesa, fog );
+ rmesa->hw.fog.cmd[FOG_C] = c.i;
+ rmesa->hw.fog.cmd[FOG_D] = d.i;
+ }
+}
+
+
+/* =============================================================
+ * Scissoring
+ */
+
+
+static GLboolean intersect_rect( XF86DRIClipRectPtr out,
+ XF86DRIClipRectPtr a,
+ XF86DRIClipRectPtr 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;
+ if ( out->x1 >= out->x2 ) return GL_FALSE;
+ if ( out->y1 >= out->y2 ) return GL_FALSE;
+ return GL_TRUE;
+}
+
+
+void radeonRecalcScissorRects( radeonContextPtr rmesa )
+{
+ XF86DRIClipRectPtr out;
+ int i;
+
+ /* Grow cliprect store?
+ */
+ if (rmesa->state.scissor.numAllocedClipRects < rmesa->numClipRects) {
+ while (rmesa->state.scissor.numAllocedClipRects < rmesa->numClipRects) {
+ rmesa->state.scissor.numAllocedClipRects += 1; /* zero case */
+ rmesa->state.scissor.numAllocedClipRects *= 2;
+ }
+
+ if (rmesa->state.scissor.pClipRects)
+ FREE(rmesa->state.scissor.pClipRects);
+
+ rmesa->state.scissor.pClipRects =
+ MALLOC( rmesa->state.scissor.numAllocedClipRects *
+ sizeof(XF86DRIClipRectRec) );
+
+ if ( rmesa->state.scissor.pClipRects == NULL ) {
+ rmesa->state.scissor.numAllocedClipRects = 0;
+ return;
+ }
+ }
+
+ out = rmesa->state.scissor.pClipRects;
+ rmesa->state.scissor.numClipRects = 0;
+
+ for ( i = 0 ; i < rmesa->numClipRects ; i++ ) {
+ if ( intersect_rect( out,
+ &rmesa->pClipRects[i],
+ &rmesa->state.scissor.rect ) ) {
+ rmesa->state.scissor.numClipRects++;
+ out++;
+ }
+ }
+}
+
+
+static void radeonUpdateScissor( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ if ( rmesa->dri.drawable ) {
+ __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
+
+ int x = ctx->Scissor.X;
+ int y = dPriv->h - ctx->Scissor.Y - ctx->Scissor.Height;
+ int w = ctx->Scissor.X + ctx->Scissor.Width - 1;
+ int h = dPriv->h - ctx->Scissor.Y - 1;
+
+ rmesa->state.scissor.rect.x1 = x + dPriv->x;
+ rmesa->state.scissor.rect.y1 = y + dPriv->y;
+ rmesa->state.scissor.rect.x2 = w + dPriv->x + 1;
+ rmesa->state.scissor.rect.y2 = h + dPriv->y + 1;
+
+ radeonRecalcScissorRects( rmesa );
+ }
+}
+
+
+static void radeonScissor( GLcontext *ctx,
+ GLint x, GLint y, GLsizei w, GLsizei h )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ if ( ctx->Scissor.Enabled ) {
+ RADEON_FIREVERTICES( rmesa ); /* don't pipeline cliprect changes */
+ radeonUpdateScissor( ctx );
+ }
+
+}
+
+
+/* =============================================================
+ * Culling
+ */
+
+static void radeonCullFace( GLcontext *ctx, GLenum unused )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
+ GLuint t = rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL];
+
+ s |= RADEON_FFACE_SOLID | RADEON_BFACE_SOLID;
+ t &= ~(RADEON_CULL_FRONT | RADEON_CULL_BACK);
+
+ if ( ctx->Polygon.CullFlag ) {
+ switch ( ctx->Polygon.CullFaceMode ) {
+ case GL_FRONT:
+ s &= ~RADEON_FFACE_SOLID;
+ t |= RADEON_CULL_FRONT;
+ break;
+ case GL_BACK:
+ s &= ~RADEON_BFACE_SOLID;
+ t |= RADEON_CULL_BACK;
+ break;
+ case GL_FRONT_AND_BACK:
+ s &= ~(RADEON_FFACE_SOLID | RADEON_BFACE_SOLID);
+ t |= (RADEON_CULL_FRONT | RADEON_CULL_BACK);
+ break;
+ }
+ }
+
+ if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) {
+ RADEON_STATECHANGE(rmesa, set );
+ rmesa->hw.set.cmd[SET_SE_CNTL] = s;
+ }
+
+ if ( rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] != t ) {
+ RADEON_STATECHANGE(rmesa, tcl );
+ rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] = t;
+ }
+}
+
+static void radeonFrontFace( GLcontext *ctx, GLenum mode )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ RADEON_STATECHANGE( rmesa, set );
+ rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_FFACE_CULL_DIR_MASK;
+
+ RADEON_STATECHANGE( rmesa, tcl );
+ rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_CULL_FRONT_IS_CCW;
+
+ switch ( mode ) {
+ case GL_CW:
+ rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_FFACE_CULL_CW;
+ break;
+ case GL_CCW:
+ rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_FFACE_CULL_CCW;
+ rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_CULL_FRONT_IS_CCW;
+ break;
+ }
+}
+
+
+/* =============================================================
+ * Line state
+ */
+static void radeonLineWidth( GLcontext *ctx, GLfloat widthf )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ RADEON_STATECHANGE( rmesa, lin );
+ RADEON_STATECHANGE( rmesa, set );
+
+ /* Line width is stored in U6.4 format.
+ */
+ rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] = (GLuint)(widthf * 16.0);
+ if ( widthf > 1.0 ) {
+ rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_WIDELINE_ENABLE;
+ } else {
+ rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_WIDELINE_ENABLE;
+ }
+}
+
+static void radeonLineStipple( GLcontext *ctx, GLint factor, GLushort pattern )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ RADEON_STATECHANGE( rmesa, lin );
+ rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] =
+ ((((GLuint)factor & 0xff) << 16) | ((GLuint)pattern));
+}
+
+
+/* =============================================================
+ * Masks
+ */
+static void radeonColorMask( GLcontext *ctx,
+ GLboolean r, GLboolean g,
+ GLboolean b, GLboolean a )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLuint mask = radeonPackColor( rmesa->radeonScreen->cpp,
+ ctx->Color.ColorMask[RCOMP],
+ ctx->Color.ColorMask[GCOMP],
+ ctx->Color.ColorMask[BCOMP],
+ ctx->Color.ColorMask[ACOMP] );
+
+ if ( rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] != mask ) {
+ RADEON_STATECHANGE( rmesa, msk );
+ rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] = mask;
+ }
+}
+
+
+/* =============================================================
+ * Polygon state
+ */
+
+static void radeonPolygonOffset( GLcontext *ctx,
+ GLfloat factor, GLfloat units )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLfloat constant = units * rmesa->state.depth.scale;
+
+ RADEON_STATECHANGE( rmesa, zbs );
+ rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_FACTOR] = *(GLuint *)&factor;
+ rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_CONSTANT] = *(GLuint *)&constant;
+}
+
+static void radeonPolygonStipple( GLcontext *ctx, const GLubyte *mask )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLuint i;
+ drmRadeonStipple stipple;
+
+ /* Must flip pattern upside down.
+ */
+ for ( i = 0 ; i < 32 ; i++ ) {
+ rmesa->state.stipple.mask[31 - i] = ((GLuint *) mask)[i];
+ }
+
+ /* TODO: push this into cmd mechanism
+ */
+ RADEON_FIREVERTICES( rmesa );
+ LOCK_HARDWARE( rmesa );
+
+ /* FIXME: Use window x,y offsets into stipple RAM.
+ */
+ stipple.mask = rmesa->state.stipple.mask;
+ drmCommandWrite( rmesa->dri.fd, DRM_RADEON_STIPPLE,
+ &stipple, sizeof(drmRadeonStipple) );
+ UNLOCK_HARDWARE( rmesa );
+}
+
+static void radeonPolygonMode( GLcontext *ctx, GLenum face, GLenum mode )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLboolean flag = (ctx->_TriangleCaps & DD_TRI_UNFILLED) != 0;
+
+ /* Can't generally do unfilled via tcl, but some good special
+ * cases work.
+ */
+ TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_UNFILLED, flag);
+ if (rmesa->TclFallback) {
+ radeonChooseRenderState( ctx );
+ radeonChooseVertexState( ctx );
+ }
+}
+
+
+/* =============================================================
+ * 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.
+ */
+
+/* Examine lighting and texture state to determine if separate specular
+ * should be enabled.
+ */
+static void radeonUpdateSpecular( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ CARD32 p = rmesa->hw.ctx.cmd[CTX_PP_CNTL];
+
+ RADEON_STATECHANGE( rmesa, tcl );
+
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_SPECULAR;
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_DIFFUSE;
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~RADEON_TCL_VTX_PK_SPEC;
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~RADEON_TCL_VTX_PK_DIFFUSE;
+ rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_LIGHTING_ENABLE;
+
+ p &= ~RADEON_SPECULAR_ENABLE;
+
+ rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_DIFFUSE_SPECULAR_COMBINE;
+
+
+ if (ctx->Light.Enabled &&
+ ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) {
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_SPECULAR;
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_DIFFUSE;
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC;
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE;
+ rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE;
+ p |= RADEON_SPECULAR_ENABLE;
+ rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &=
+ ~RADEON_DIFFUSE_SPECULAR_COMBINE;
+ }
+ else if (ctx->Light.Enabled) {
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_DIFFUSE;
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE;
+ rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE;
+ } else if (ctx->Fog.ColorSumEnabled ) {
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC;
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE;
+ p |= RADEON_SPECULAR_ENABLE;
+ } else {
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE;
+ }
+
+ if (ctx->Fog.Enabled) {
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_SPECULAR;
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC;
+
+ /* Bizzare: have to leave lighting enabled to get fog.
+ */
+ rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE;
+ }
+
+ if ( ctx->_TriangleCaps & DD_SEPARATE_SPECULAR ) {
+ assert( (p & RADEON_SPECULAR_ENABLE) != 0 );
+ } else {
+ assert( (p & RADEON_SPECULAR_ENABLE) == 0 );
+ }
+
+ if ( rmesa->hw.ctx.cmd[CTX_PP_CNTL] != p ) {
+ RADEON_STATECHANGE( rmesa, ctx );
+ rmesa->hw.ctx.cmd[CTX_PP_CNTL] = p;
+ }
+
+ /* Update vertex/render formats
+ */
+ if (rmesa->TclFallback) {
+ radeonChooseRenderState( ctx );
+ radeonChooseVertexState( ctx );
+ }
+}
+
+
+/* =============================================================
+ * Materials
+ */
+
+
+/* Update on colormaterial, material emmissive/ambient,
+ * lightmodel.globalambient
+ */
+static void update_global_ambient( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ float *fcmd = (float *)RADEON_DB_STATE( glt );
+
+ /* Need to do more if both emmissive & ambient are PREMULT:
+ */
+ if ((rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &
+ ((3 << RADEON_EMISSIVE_SOURCE_SHIFT) |
+ (3 << RADEON_AMBIENT_SOURCE_SHIFT))) == 0)
+ {
+ COPY_3V( &fcmd[GLT_RED],
+ ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION]);
+ ACC_SCALE_3V( &fcmd[GLT_RED],
+ ctx->Light.Model.Ambient,
+ ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT]);
+ }
+ else
+ {
+ COPY_3V( &fcmd[GLT_RED], ctx->Light.Model.Ambient );
+ }
+
+ RADEON_DB_STATECHANGE(rmesa, &rmesa->hw.glt);
+}
+
+/* Update on change to
+ * - light[p].colors
+ * - light[p].enabled
+ * - material,
+ * - colormaterial enabled
+ * - colormaterial bitmask
+ */
+static void update_light_colors( GLcontext *ctx, GLuint p )
+{
+ struct gl_light *l = &ctx->Light.Light[p];
+
+/* fprintf(stderr, "%s\n", __FUNCTION__); */
+
+ if (l->Enabled) {
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ float *fcmd = (float *)RADEON_DB_STATE( lit[p] );
+ GLuint bitmask = ctx->Light.ColorMaterialBitmask;
+ GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
+
+ COPY_4V( &fcmd[LIT_AMBIENT_RED], l->Ambient );
+ COPY_4V( &fcmd[LIT_DIFFUSE_RED], l->Diffuse );
+ COPY_4V( &fcmd[LIT_SPECULAR_RED], l->Specular );
+
+ if (!ctx->Light.ColorMaterialEnabled)
+ bitmask = 0;
+
+ if ((bitmask & MAT_BIT_FRONT_AMBIENT) == 0)
+ SELF_SCALE_3V( &fcmd[LIT_AMBIENT_RED], mat[MAT_ATTRIB_FRONT_AMBIENT] );
+
+ if ((bitmask & MAT_BIT_FRONT_DIFFUSE) == 0)
+ SELF_SCALE_3V( &fcmd[LIT_DIFFUSE_RED], mat[MAT_ATTRIB_FRONT_DIFFUSE] );
+
+ if ((bitmask & MAT_BIT_FRONT_SPECULAR) == 0)
+ SELF_SCALE_3V( &fcmd[LIT_SPECULAR_RED], mat[MAT_ATTRIB_FRONT_SPECULAR] );
+
+ RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
+ }
+}
+
+/* Also fallback for asym colormaterial mode in twoside lighting...
+ */
+static void check_twoside_fallback( GLcontext *ctx )
+{
+ GLboolean fallback = GL_FALSE;
+ GLint i;
+
+ if (ctx->Light.Enabled && ctx->Light.Model.TwoSide) {
+ if (ctx->Light.ColorMaterialEnabled &&
+ (ctx->Light.ColorMaterialBitmask & BACK_MATERIAL_BITS) !=
+ ((ctx->Light.ColorMaterialBitmask & FRONT_MATERIAL_BITS)<<1))
+ fallback = GL_TRUE;
+ else {
+ for (i = MAT_ATTRIB_FRONT_AMBIENT; i < MAT_ATTRIB_FRONT_INDEXES; i+=2)
+ if (memcmp( ctx->Light.Material.Attrib[i],
+ ctx->Light.Material.Attrib[i+1],
+ sizeof(GLfloat)*4) != 0) {
+ fallback = GL_TRUE;
+ break;
+ }
+ }
+ }
+
+ TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_LIGHT_TWOSIDE, fallback );
+}
+
+
+static void radeonColorMaterial( GLcontext *ctx, GLenum face, GLenum mode )
+{
+ if (ctx->Light.ColorMaterialEnabled) {
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLuint light_model_ctl1 = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL];
+ GLuint mask = ctx->Light.ColorMaterialBitmask;
+
+ /* Default to PREMULT:
+ */
+ light_model_ctl1 &= ~((0xf << RADEON_EMISSIVE_SOURCE_SHIFT) |
+ (0xf << RADEON_AMBIENT_SOURCE_SHIFT) |
+ (0xf << RADEON_DIFFUSE_SOURCE_SHIFT) |
+ (0xf << RADEON_SPECULAR_SOURCE_SHIFT));
+
+ if (mask & MAT_BIT_FRONT_EMISSION) {
+ light_model_ctl1 |= (3 <<
+ RADEON_EMISSIVE_SOURCE_SHIFT);
+ }
+
+ if (mask & MAT_BIT_FRONT_AMBIENT) {
+ light_model_ctl1 |= (3 <<
+ RADEON_AMBIENT_SOURCE_SHIFT);
+ }
+
+ if (mask & MAT_BIT_FRONT_DIFFUSE) {
+ light_model_ctl1 |= (3 <<
+ RADEON_DIFFUSE_SOURCE_SHIFT);
+ }
+
+ if (mask & MAT_BIT_FRONT_SPECULAR) {
+ light_model_ctl1 |= (3 <<
+ RADEON_SPECULAR_SOURCE_SHIFT);
+ }
+
+ if (light_model_ctl1 != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]) {
+ GLuint p;
+
+ RADEON_STATECHANGE( rmesa, tcl );
+ rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] = light_model_ctl1;
+
+ for (p = 0 ; p < MAX_LIGHTS; p++)
+ update_light_colors( ctx, p );
+ update_global_ambient( ctx );
+ }
+ }
+
+ check_twoside_fallback( ctx );
+}
+
+void radeonUpdateMaterial( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
+ GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( mtl );
+ GLuint p;
+ GLuint mask = ~0;
+
+ if (ctx->Light.ColorMaterialEnabled)
+ mask &= ~ctx->Light.ColorMaterialBitmask;
+
+ if (RADEON_DEBUG & DEBUG_STATE)
+ fprintf(stderr, "%s\n", __FUNCTION__);
+
+
+ if (mask & MAT_BIT_FRONT_EMISSION) {
+ fcmd[MTL_EMMISSIVE_RED] = mat[MAT_ATTRIB_FRONT_EMISSION][0];
+ fcmd[MTL_EMMISSIVE_GREEN] = mat[MAT_ATTRIB_FRONT_EMISSION][1];
+ fcmd[MTL_EMMISSIVE_BLUE] = mat[MAT_ATTRIB_FRONT_EMISSION][2];
+ fcmd[MTL_EMMISSIVE_ALPHA] = mat[MAT_ATTRIB_FRONT_EMISSION][3];
+ }
+ if (mask & MAT_BIT_FRONT_AMBIENT) {
+ fcmd[MTL_AMBIENT_RED] = mat[MAT_ATTRIB_FRONT_AMBIENT][0];
+ fcmd[MTL_AMBIENT_GREEN] = mat[MAT_ATTRIB_FRONT_AMBIENT][1];
+ fcmd[MTL_AMBIENT_BLUE] = mat[MAT_ATTRIB_FRONT_AMBIENT][2];
+ fcmd[MTL_AMBIENT_ALPHA] = mat[MAT_ATTRIB_FRONT_AMBIENT][3];
+ }
+ if (mask & MAT_BIT_FRONT_DIFFUSE) {
+ fcmd[MTL_DIFFUSE_RED] = mat[MAT_ATTRIB_FRONT_DIFFUSE][0];
+ fcmd[MTL_DIFFUSE_GREEN] = mat[MAT_ATTRIB_FRONT_DIFFUSE][1];
+ fcmd[MTL_DIFFUSE_BLUE] = mat[MAT_ATTRIB_FRONT_DIFFUSE][2];
+ fcmd[MTL_DIFFUSE_ALPHA] = mat[MAT_ATTRIB_FRONT_DIFFUSE][3];
+ }
+ if (mask & MAT_BIT_FRONT_SPECULAR) {
+ fcmd[MTL_SPECULAR_RED] = mat[MAT_ATTRIB_FRONT_SPECULAR][0];
+ fcmd[MTL_SPECULAR_GREEN] = mat[MAT_ATTRIB_FRONT_SPECULAR][1];
+ fcmd[MTL_SPECULAR_BLUE] = mat[MAT_ATTRIB_FRONT_SPECULAR][2];
+ fcmd[MTL_SPECULAR_ALPHA] = mat[MAT_ATTRIB_FRONT_SPECULAR][3];
+ }
+ if (mask & MAT_BIT_FRONT_SHININESS) {
+ fcmd[MTL_SHININESS] = mat[MAT_ATTRIB_FRONT_SHININESS][0];
+ }
+
+ if (RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mtl )) {
+ for (p = 0 ; p < MAX_LIGHTS; p++)
+ update_light_colors( ctx, p );
+
+ check_twoside_fallback( ctx );
+ update_global_ambient( ctx );
+ }
+ else if (RADEON_DEBUG & (DEBUG_PRIMS|DEBUG_STATE))
+ fprintf(stderr, "%s: Elided noop material call\n", __FUNCTION__);
+}
+
+/* _NEW_LIGHT
+ * _NEW_MODELVIEW
+ * _MESA_NEW_NEED_EYE_COORDS
+ *
+ * Uses derived state from mesa:
+ * _VP_inf_norm
+ * _h_inf_norm
+ * _Position
+ * _NormDirection
+ * _ModelViewInvScale
+ * _NeedEyeCoords
+ * _EyeZDir
+ *
+ * which are calculated in light.c and are correct for the current
+ * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
+ * and _MESA_NEW_NEED_EYE_COORDS.
+ */
+static void update_light( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ /* Have to check these, or have an automatic shortcircuit mechanism
+ * to remove noop statechanges. (Or just do a better job on the
+ * front end).
+ */
+ {
+ GLuint tmp = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL];
+
+ if (ctx->_NeedEyeCoords)
+ tmp &= ~RADEON_LIGHT_IN_MODELSPACE;
+ else
+ tmp |= RADEON_LIGHT_IN_MODELSPACE;
+
+
+ /* Leave this test disabled: (unexplained q3 lockup) (even with
+ new packets)
+ */
+ if (tmp != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL])
+ {
+ RADEON_STATECHANGE( rmesa, tcl );
+ rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] = tmp;
+ }
+ }
+
+ {
+ GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( eye );
+ fcmd[EYE_X] = ctx->_EyeZDir[0];
+ fcmd[EYE_Y] = ctx->_EyeZDir[1];
+ fcmd[EYE_Z] = - ctx->_EyeZDir[2];
+ fcmd[EYE_RESCALE_FACTOR] = ctx->_ModelViewInvScale;
+ RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.eye );
+ }
+
+
+
+ if (ctx->Light.Enabled) {
+ GLint p;
+ for (p = 0 ; p < MAX_LIGHTS; p++) {
+ if (ctx->Light.Light[p].Enabled) {
+ struct gl_light *l = &ctx->Light.Light[p];
+ GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( lit[p] );
+
+ if (l->EyePosition[3] == 0.0) {
+ COPY_3FV( &fcmd[LIT_POSITION_X], l->_VP_inf_norm );
+ COPY_3FV( &fcmd[LIT_DIRECTION_X], l->_h_inf_norm );
+ fcmd[LIT_POSITION_W] = 0;
+ fcmd[LIT_DIRECTION_W] = 0;
+ } else {
+ COPY_4V( &fcmd[LIT_POSITION_X], l->_Position );
+ fcmd[LIT_DIRECTION_X] = -l->_NormDirection[0];
+ fcmd[LIT_DIRECTION_Y] = -l->_NormDirection[1];
+ fcmd[LIT_DIRECTION_Z] = -l->_NormDirection[2];
+ fcmd[LIT_DIRECTION_W] = 0;
+ }
+
+ RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
+ }
+ }
+ }
+}
+
+static void radeonLightfv( GLcontext *ctx, GLenum light,
+ GLenum pname, const GLfloat *params )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLint p = light - GL_LIGHT0;
+ struct gl_light *l = &ctx->Light.Light[p];
+ GLfloat *fcmd = (GLfloat *)rmesa->hw.lit[p].cmd;
+
+
+ switch (pname) {
+ case GL_AMBIENT:
+ case GL_DIFFUSE:
+ case GL_SPECULAR:
+ update_light_colors( ctx, p );
+ break;
+
+ case GL_SPOT_DIRECTION:
+ /* picked up in update_light */
+ break;
+
+ case GL_POSITION: {
+ /* positions picked up in update_light, but can do flag here */
+ GLuint flag;
+ GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
+
+ /* FIXME: Set RANGE_ATTEN only when needed */
+ if (p&1)
+ flag = RADEON_LIGHT_1_IS_LOCAL;
+ else
+ flag = RADEON_LIGHT_0_IS_LOCAL;
+
+ RADEON_STATECHANGE(rmesa, tcl);
+ if (l->EyePosition[3] != 0.0F)
+ rmesa->hw.tcl.cmd[idx] |= flag;
+ else
+ rmesa->hw.tcl.cmd[idx] &= ~flag;
+ break;
+ }
+
+ case GL_SPOT_EXPONENT:
+ RADEON_STATECHANGE(rmesa, lit[p]);
+ fcmd[LIT_SPOT_EXPONENT] = params[0];
+ break;
+
+ case GL_SPOT_CUTOFF: {
+ GLuint flag = (p&1) ? RADEON_LIGHT_1_IS_SPOT : RADEON_LIGHT_0_IS_SPOT;
+ GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
+
+ RADEON_STATECHANGE(rmesa, lit[p]);
+ fcmd[LIT_SPOT_CUTOFF] = l->_CosCutoff;
+
+ RADEON_STATECHANGE(rmesa, tcl);
+ if (l->SpotCutoff != 180.0F)
+ rmesa->hw.tcl.cmd[idx] |= flag;
+ else
+ rmesa->hw.tcl.cmd[idx] &= ~flag;
+
+ break;
+ }
+
+ case GL_CONSTANT_ATTENUATION:
+ RADEON_STATECHANGE(rmesa, lit[p]);
+ fcmd[LIT_ATTEN_CONST] = params[0];
+ break;
+ case GL_LINEAR_ATTENUATION:
+ RADEON_STATECHANGE(rmesa, lit[p]);
+ fcmd[LIT_ATTEN_LINEAR] = params[0];
+ break;
+ case GL_QUADRATIC_ATTENUATION:
+ RADEON_STATECHANGE(rmesa, lit[p]);
+ fcmd[LIT_ATTEN_QUADRATIC] = params[0];
+ break;
+ default:
+ return;
+ }
+
+ /* Set RANGE_ATTEN only when needed */
+ switch (pname) {
+ case GL_POSITION:
+ case GL_LINEAR_ATTENUATION:
+ case GL_QUADRATIC_ATTENUATION:
+ {
+ GLuint flag;
+ GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
+
+ if (p&1)
+ flag = RADEON_LIGHT_1_ENABLE_RANGE_ATTEN;
+ else
+ flag = RADEON_LIGHT_0_ENABLE_RANGE_ATTEN;
+
+ RADEON_STATECHANGE(rmesa, tcl);
+ if (l->EyePosition[3] != 0.0F &&
+ (l->LinearAttenuation != 0.0F || l->QuadraticAttenuation != 0.0F))
+ rmesa->hw.tcl.cmd[idx] |= flag;
+ else
+ rmesa->hw.tcl.cmd[idx] &= ~flag;
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+
+
+
+static void radeonLightModelfv( GLcontext *ctx, GLenum pname,
+ const GLfloat *param )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ switch (pname) {
+ case GL_LIGHT_MODEL_AMBIENT:
+ update_global_ambient( ctx );
+ break;
+
+ case GL_LIGHT_MODEL_LOCAL_VIEWER:
+ RADEON_STATECHANGE( rmesa, tcl );
+ if (ctx->Light.Model.LocalViewer)
+ rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LOCAL_VIEWER;
+ else
+ rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_LOCAL_VIEWER;
+ break;
+
+ case GL_LIGHT_MODEL_TWO_SIDE:
+ RADEON_STATECHANGE( rmesa, tcl );
+ if (ctx->Light.Model.TwoSide)
+ rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_LIGHT_TWOSIDE;
+ else
+ rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_LIGHT_TWOSIDE;
+
+ check_twoside_fallback( ctx );
+
+ if (rmesa->TclFallback) {
+ radeonChooseRenderState( ctx );
+ radeonChooseVertexState( ctx );
+ }
+ break;
+
+ case GL_LIGHT_MODEL_COLOR_CONTROL:
+ radeonUpdateSpecular(ctx);
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void radeonShadeModel( GLcontext *ctx, GLenum mode )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
+
+ s &= ~(RADEON_DIFFUSE_SHADE_MASK |
+ RADEON_ALPHA_SHADE_MASK |
+ RADEON_SPECULAR_SHADE_MASK |
+ RADEON_FOG_SHADE_MASK);
+
+ switch ( mode ) {
+ case GL_FLAT:
+ s |= (RADEON_DIFFUSE_SHADE_FLAT |
+ RADEON_ALPHA_SHADE_FLAT |
+ RADEON_SPECULAR_SHADE_FLAT |
+ RADEON_FOG_SHADE_FLAT);
+ break;
+ case GL_SMOOTH:
+ s |= (RADEON_DIFFUSE_SHADE_GOURAUD |
+ RADEON_ALPHA_SHADE_GOURAUD |
+ RADEON_SPECULAR_SHADE_GOURAUD |
+ RADEON_FOG_SHADE_GOURAUD);
+ break;
+ default:
+ return;
+ }
+
+ if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) {
+ RADEON_STATECHANGE( rmesa, set );
+ rmesa->hw.set.cmd[SET_SE_CNTL] = s;
+ }
+}
+
+
+/* =============================================================
+ * User clip planes
+ */
+
+static void radeonClipPlane( GLcontext *ctx, GLenum plane, const GLfloat *eq )
+{
+ GLint p = (GLint) plane - (GLint) GL_CLIP_PLANE0;
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
+
+ RADEON_STATECHANGE( rmesa, ucp[p] );
+ rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
+ rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
+ rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
+ rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
+}
+
+static void radeonUpdateClipPlanes( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLuint p;
+
+ for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
+ if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
+ GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
+
+ RADEON_STATECHANGE( rmesa, ucp[p] );
+ rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
+ rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
+ rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
+ rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
+ }
+ }
+}
+
+
+/* =============================================================
+ * Stencil
+ */
+
+static void radeonStencilFunc( GLcontext *ctx, GLenum func,
+ GLint ref, GLuint mask )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLuint refmask = ((ctx->Stencil.Ref[0] << RADEON_STENCIL_REF_SHIFT) |
+ (ctx->Stencil.ValueMask[0] << RADEON_STENCIL_MASK_SHIFT));
+
+ RADEON_STATECHANGE( rmesa, ctx );
+ RADEON_STATECHANGE( rmesa, msk );
+
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~RADEON_STENCIL_TEST_MASK;
+ rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~(RADEON_STENCIL_REF_MASK|
+ RADEON_STENCIL_VALUE_MASK);
+
+ switch ( ctx->Stencil.Function[0] ) {
+ case GL_NEVER:
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_NEVER;
+ break;
+ case GL_LESS:
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_LESS;
+ break;
+ case GL_EQUAL:
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_EQUAL;
+ break;
+ case GL_LEQUAL:
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_LEQUAL;
+ break;
+ case GL_GREATER:
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_GREATER;
+ break;
+ case GL_NOTEQUAL:
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_NEQUAL;
+ break;
+ case GL_GEQUAL:
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_GEQUAL;
+ break;
+ case GL_ALWAYS:
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_ALWAYS;
+ break;
+ }
+
+ rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= refmask;
+}
+
+static void radeonStencilMask( GLcontext *ctx, GLuint mask )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ RADEON_STATECHANGE( rmesa, msk );
+ rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~RADEON_STENCIL_WRITE_MASK;
+ rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |=
+ (ctx->Stencil.WriteMask[0] << RADEON_STENCIL_WRITEMASK_SHIFT);
+}
+
+static void radeonStencilOp( GLcontext *ctx, GLenum fail,
+ GLenum zfail, GLenum zpass )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ RADEON_STATECHANGE( rmesa, ctx );
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~(RADEON_STENCIL_FAIL_MASK |
+ RADEON_STENCIL_ZFAIL_MASK |
+ RADEON_STENCIL_ZPASS_MASK);
+
+ switch ( ctx->Stencil.FailFunc[0] ) {
+ case GL_KEEP:
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_KEEP;
+ break;
+ case GL_ZERO:
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_ZERO;
+ break;
+ case GL_REPLACE:
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_REPLACE;
+ break;
+ case GL_INCR:
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_INC;
+ break;
+ case GL_DECR:
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_DEC;
+ break;
+ case GL_INVERT:
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_INVERT;
+ break;
+ }
+
+ switch ( ctx->Stencil.ZFailFunc[0] ) {
+ case GL_KEEP:
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_KEEP;
+ break;
+ case GL_ZERO:
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_ZERO;
+ break;
+ case GL_REPLACE:
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_REPLACE;
+ break;
+ case GL_INCR:
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_INC;
+ break;
+ case GL_DECR:
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_DEC;
+ break;
+ case GL_INVERT:
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_INVERT;
+ break;
+ }
+
+ switch ( ctx->Stencil.ZPassFunc[0] ) {
+ case GL_KEEP:
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_KEEP;
+ break;
+ case GL_ZERO:
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_ZERO;
+ break;
+ case GL_REPLACE:
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_REPLACE;
+ break;
+ case GL_INCR:
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_INC;
+ break;
+ case GL_DECR:
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_DEC;
+ break;
+ case GL_INVERT:
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_INVERT;
+ break;
+ }
+}
+
+static void radeonClearStencil( GLcontext *ctx, GLint s )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ rmesa->state.stencil.clear =
+ ((GLuint) ctx->Stencil.Clear |
+ (0xff << RADEON_STENCIL_MASK_SHIFT) |
+ (ctx->Stencil.WriteMask[0] << RADEON_STENCIL_WRITEMASK_SHIFT));
+}
+
+
+/* =============================================================
+ * Window position and viewport transformation
+ */
+
+/*
+ * To correctly position primitives:
+ */
+#define SUBPIXEL_X 0.125
+#define SUBPIXEL_Y 0.125
+
+void radeonUpdateWindow( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
+ GLfloat xoffset = (GLfloat)dPriv->x;
+ GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
+ const GLfloat *v = ctx->Viewport._WindowMap.m;
+
+ GLfloat sx = v[MAT_SX];
+ GLfloat tx = v[MAT_TX] + xoffset + SUBPIXEL_X;
+ GLfloat sy = - v[MAT_SY];
+ GLfloat ty = (- v[MAT_TY]) + yoffset + SUBPIXEL_Y;
+ GLfloat sz = v[MAT_SZ] * rmesa->state.depth.scale;
+ GLfloat tz = v[MAT_TZ] * rmesa->state.depth.scale;
+ RADEON_FIREVERTICES( rmesa );
+ RADEON_STATECHANGE( rmesa, vpt );
+
+ rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE] = *(GLuint *)&sx;
+ rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = *(GLuint *)&tx;
+ rmesa->hw.vpt.cmd[VPT_SE_VPORT_YSCALE] = *(GLuint *)&sy;
+ rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = *(GLuint *)&ty;
+ rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE] = *(GLuint *)&sz;
+ rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = *(GLuint *)&tz;
+}
+
+
+
+static void radeonViewport( GLcontext *ctx, GLint x, GLint y,
+ GLsizei width, GLsizei height )
+{
+ /* Don't pipeline viewport changes, conflict with window offset
+ * setting below. Could apply deltas to rescue pipelined viewport
+ * values, or keep the originals hanging around.
+ */
+ RADEON_FIREVERTICES( RADEON_CONTEXT(ctx) );
+ radeonUpdateWindow( ctx );
+}
+
+static void radeonDepthRange( GLcontext *ctx, GLclampd nearval,
+ GLclampd farval )
+{
+ radeonUpdateWindow( ctx );
+}
+
+void radeonUpdateViewportOffset( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
+ GLfloat xoffset = (GLfloat)dPriv->x;
+ GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
+ const GLfloat *v = ctx->Viewport._WindowMap.m;
+
+ GLfloat tx = v[MAT_TX] + xoffset;
+ GLfloat ty = (- v[MAT_TY]) + yoffset;
+
+ if ( rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] != *(GLuint *)&tx ||
+ rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] != *(GLuint *)&ty )
+ {
+ /* Note: this should also modify whatever data the context reset
+ * code uses...
+ */
+ rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = *(GLuint *)&tx;
+ rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = *(GLuint *)&ty;
+
+ /* update polygon stipple x/y screen offset */
+ {
+ GLuint stx, sty;
+ GLuint m = rmesa->hw.msc.cmd[MSC_RE_MISC];
+
+ m &= ~(RADEON_STIPPLE_X_OFFSET_MASK |
+ RADEON_STIPPLE_Y_OFFSET_MASK);
+
+ /* add magic offsets, then invert */
+ stx = 31 - ((rmesa->dri.drawable->x - 1) & RADEON_STIPPLE_COORD_MASK);
+ sty = 31 - ((rmesa->dri.drawable->y + rmesa->dri.drawable->h - 1)
+ & RADEON_STIPPLE_COORD_MASK);
+
+ m |= ((stx << RADEON_STIPPLE_X_OFFSET_SHIFT) |
+ (sty << RADEON_STIPPLE_Y_OFFSET_SHIFT));
+
+ if ( rmesa->hw.msc.cmd[MSC_RE_MISC] != m ) {
+ RADEON_STATECHANGE( rmesa, msc );
+ rmesa->hw.msc.cmd[MSC_RE_MISC] = m;
+ }
+ }
+ }
+
+ radeonUpdateScissor( ctx );
+}
+
+
+
+/* =============================================================
+ * Miscellaneous
+ */
+
+static void radeonClearColor( GLcontext *ctx, const GLfloat color[4] )
+{
+ radeonContextPtr rmesa = RADEON_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]);
+ rmesa->state.color.clear = radeonPackColor( rmesa->radeonScreen->cpp,
+ c[0], c[1], c[2], c[3] );
+}
+
+
+static void radeonRenderMode( GLcontext *ctx, GLenum mode )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ FALLBACK( rmesa, RADEON_FALLBACK_RENDER_MODE, (mode != GL_RENDER) );
+}
+
+
+static GLuint radeon_rop_tab[] = {
+ RADEON_ROP_CLEAR,
+ RADEON_ROP_AND,
+ RADEON_ROP_AND_REVERSE,
+ RADEON_ROP_COPY,
+ RADEON_ROP_AND_INVERTED,
+ RADEON_ROP_NOOP,
+ RADEON_ROP_XOR,
+ RADEON_ROP_OR,
+ RADEON_ROP_NOR,
+ RADEON_ROP_EQUIV,
+ RADEON_ROP_INVERT,
+ RADEON_ROP_OR_REVERSE,
+ RADEON_ROP_COPY_INVERTED,
+ RADEON_ROP_OR_INVERTED,
+ RADEON_ROP_NAND,
+ RADEON_ROP_SET,
+};
+
+static void radeonLogicOpCode( GLcontext *ctx, GLenum opcode )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLuint rop = (GLuint)opcode - GL_CLEAR;
+
+ ASSERT( rop < 16 );
+
+ RADEON_STATECHANGE( rmesa, msk );
+ rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = radeon_rop_tab[rop];
+}
+
+
+void radeonSetCliprects( radeonContextPtr rmesa, GLenum mode )
+{
+ __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
+
+ switch ( mode ) {
+ case GL_FRONT_LEFT:
+ rmesa->numClipRects = dPriv->numClipRects;
+ rmesa->pClipRects = (XF86DRIClipRectPtr)dPriv->pClipRects;
+ break;
+ case GL_BACK_LEFT:
+ /* Can't ignore 2d windows if we are page flipping.
+ */
+ if ( dPriv->numBackClipRects == 0 || rmesa->doPageFlip ) {
+ rmesa->numClipRects = dPriv->numClipRects;
+ rmesa->pClipRects = (XF86DRIClipRectPtr)dPriv->pClipRects;
+ }
+ else {
+ rmesa->numClipRects = dPriv->numBackClipRects;
+ rmesa->pClipRects = (XF86DRIClipRectPtr)dPriv->pBackClipRects;
+ }
+ break;
+ default:
+ fprintf(stderr, "bad mode in radeonSetCliprects\n");
+ return;
+ }
+
+ if (rmesa->state.scissor.enabled)
+ radeonRecalcScissorRects( rmesa );
+}
+
+
+static void radeonDrawBuffer( GLcontext *ctx, GLenum mode )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ if (RADEON_DEBUG & DEBUG_DRI)
+ fprintf(stderr, "%s %s\n", __FUNCTION__,
+ _mesa_lookup_enum_by_nr( mode ));
+
+ RADEON_FIREVERTICES(rmesa); /* don't pipeline cliprect changes */
+
+ /*
+ * _DrawDestMask is easier to cope with than <mode>.
+ */
+ switch ( ctx->Color._DrawDestMask ) {
+ case FRONT_LEFT_BIT:
+ FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_FALSE );
+ radeonSetCliprects( rmesa, GL_FRONT_LEFT );
+ break;
+ case BACK_LEFT_BIT:
+ FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_FALSE );
+ radeonSetCliprects( rmesa, GL_BACK_LEFT );
+ break;
+ default:
+ /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
+ FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_TRUE );
+ return;
+ }
+
+ /* We want to update the s/w rast state too so that r200SetBuffer()
+ * gets called.
+ */
+ _swrast_DrawBuffer(ctx, mode);
+
+ RADEON_STATECHANGE( rmesa, ctx );
+ rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = (rmesa->state.color.drawOffset &
+ RADEON_COLOROFFSET_MASK);
+ rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = rmesa->state.color.drawPitch;
+}
+
+static void radeonReadBuffer( GLcontext *ctx, GLenum mode )
+{
+ /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
+}
+
+
+/* =============================================================
+ * State enable/disable
+ */
+
+static void radeonEnable( GLcontext *ctx, GLenum cap, GLboolean state )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLuint p, flag;
+
+ if ( RADEON_DEBUG & DEBUG_STATE )
+ fprintf( stderr, "%s( %s = %s )\n", __FUNCTION__,
+ _mesa_lookup_enum_by_nr( cap ),
+ state ? "GL_TRUE" : "GL_FALSE" );
+
+ switch ( cap ) {
+ /* Fast track this one...
+ */
+ case GL_TEXTURE_1D:
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_3D:
+ break;
+
+ case GL_ALPHA_TEST:
+ RADEON_STATECHANGE( rmesa, ctx );
+ if (state) {
+ rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_ALPHA_TEST_ENABLE;
+ } else {
+ rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_ALPHA_TEST_ENABLE;
+ }
+ break;
+
+ case GL_BLEND:
+ RADEON_STATECHANGE( rmesa, ctx );
+ if (state) {
+ rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_ALPHA_BLEND_ENABLE;
+ } else {
+ rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ALPHA_BLEND_ENABLE;
+ }
+ if ( ctx->Color.ColorLogicOpEnabled ) {
+ rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_ROP_ENABLE;
+ } else {
+ rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ROP_ENABLE;
+ }
+
+ /* Catch a possible fallback:
+ */
+ if (state) {
+ ctx->Driver.BlendEquation( ctx, ctx->Color.BlendEquation );
+ ctx->Driver.BlendFunc( ctx, ctx->Color.BlendSrcRGB,
+ ctx->Color.BlendDstRGB );
+ }
+ else {
+ FALLBACK( rmesa, RADEON_FALLBACK_BLEND_FUNC, GL_FALSE );
+ FALLBACK( rmesa, RADEON_FALLBACK_BLEND_EQ, GL_FALSE );
+ }
+ break;
+
+ case GL_CLIP_PLANE0:
+ case GL_CLIP_PLANE1:
+ case GL_CLIP_PLANE2:
+ case GL_CLIP_PLANE3:
+ case GL_CLIP_PLANE4:
+ case GL_CLIP_PLANE5:
+ p = cap-GL_CLIP_PLANE0;
+ RADEON_STATECHANGE( rmesa, tcl );
+ if (state) {
+ rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (RADEON_UCP_ENABLE_0<<p);
+ radeonClipPlane( ctx, cap, NULL );
+ }
+ else {
+ rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(RADEON_UCP_ENABLE_0<<p);
+ }
+ break;
+
+ case GL_COLOR_MATERIAL:
+ radeonColorMaterial( ctx, 0, 0 );
+ if (!state)
+ radeonUpdateMaterial( ctx );
+ break;
+
+ case GL_CULL_FACE:
+ radeonCullFace( ctx, 0 );
+ break;
+
+ case GL_DEPTH_TEST:
+ RADEON_STATECHANGE(rmesa, ctx );
+ if ( state ) {
+ rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_Z_ENABLE;
+ } else {
+ rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_Z_ENABLE;
+ }
+ break;
+
+ case GL_DITHER:
+ RADEON_STATECHANGE(rmesa, ctx );
+ if ( state ) {
+ rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_DITHER_ENABLE;
+ } else {
+ rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_DITHER_ENABLE;
+ }
+ break;
+
+ case GL_FOG:
+ RADEON_STATECHANGE(rmesa, ctx );
+ if ( state ) {
+ rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_FOG_ENABLE;
+ radeonFogfv( ctx, GL_FOG_MODE, 0 );
+ } else {
+ rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_FOG_ENABLE;
+ RADEON_STATECHANGE(rmesa, tcl);
+ rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_TCL_FOG_MASK;
+ }
+ radeonUpdateSpecular( ctx ); /* for PK_SPEC */
+ if (rmesa->TclFallback)
+ radeonChooseVertexState( ctx );
+ _mesa_allow_light_in_model( ctx, !state );
+ break;
+
+ case GL_LIGHT0:
+ case GL_LIGHT1:
+ case GL_LIGHT2:
+ case GL_LIGHT3:
+ case GL_LIGHT4:
+ case GL_LIGHT5:
+ case GL_LIGHT6:
+ case GL_LIGHT7:
+ RADEON_STATECHANGE(rmesa, tcl);
+ p = cap - GL_LIGHT0;
+ if (p&1)
+ flag = (RADEON_LIGHT_1_ENABLE |
+ RADEON_LIGHT_1_ENABLE_AMBIENT |
+ RADEON_LIGHT_1_ENABLE_SPECULAR);
+ else
+ flag = (RADEON_LIGHT_0_ENABLE |
+ RADEON_LIGHT_0_ENABLE_AMBIENT |
+ RADEON_LIGHT_0_ENABLE_SPECULAR);
+
+ if (state)
+ rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] |= flag;
+ else
+ rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] &= ~flag;
+
+ /*
+ */
+ update_light_colors( ctx, p );
+ break;
+
+ case GL_LIGHTING:
+ RADEON_STATECHANGE(rmesa, tcl);
+ radeonUpdateSpecular(ctx);
+ check_twoside_fallback( ctx );
+ break;
+
+ case GL_LINE_SMOOTH:
+ RADEON_STATECHANGE( rmesa, ctx );
+ if ( state ) {
+ rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_ANTI_ALIAS_LINE;
+ } else {
+ rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_ANTI_ALIAS_LINE;
+ }
+ break;
+
+ case GL_LINE_STIPPLE:
+ RADEON_STATECHANGE( rmesa, ctx );
+ if ( state ) {
+ rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_PATTERN_ENABLE;
+ } else {
+ rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_PATTERN_ENABLE;
+ }
+ break;
+
+ case GL_COLOR_LOGIC_OP:
+ RADEON_STATECHANGE( rmesa, ctx );
+ if ( state ) {
+ rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_ROP_ENABLE;
+ } else {
+ rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ROP_ENABLE;
+ }
+ break;
+
+ case GL_NORMALIZE:
+ RADEON_STATECHANGE( rmesa, tcl );
+ if ( state ) {
+ rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_NORMALIZE_NORMALS;
+ } else {
+ rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_NORMALIZE_NORMALS;
+ }
+ break;
+
+ case GL_POLYGON_OFFSET_POINT:
+ if (rmesa->dri.drmMinor == 1) {
+ radeonChooseRenderState( ctx );
+ }
+ else {
+ RADEON_STATECHANGE( rmesa, set );
+ if ( state ) {
+ rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_ZBIAS_ENABLE_POINT;
+ } else {
+ rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_ZBIAS_ENABLE_POINT;
+ }
+ }
+ break;
+
+ case GL_POLYGON_OFFSET_LINE:
+ if (rmesa->dri.drmMinor == 1) {
+ radeonChooseRenderState( ctx );
+ }
+ else {
+ RADEON_STATECHANGE( rmesa, set );
+ if ( state ) {
+ rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_ZBIAS_ENABLE_LINE;
+ } else {
+ rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_ZBIAS_ENABLE_LINE;
+ }
+ }
+ break;
+
+ case GL_POLYGON_OFFSET_FILL:
+ if (rmesa->dri.drmMinor == 1) {
+ radeonChooseRenderState( ctx );
+ }
+ else {
+ RADEON_STATECHANGE( rmesa, set );
+ if ( state ) {
+ rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_ZBIAS_ENABLE_TRI;
+ } else {
+ rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_ZBIAS_ENABLE_TRI;
+ }
+ }
+ break;
+
+ case GL_POLYGON_SMOOTH:
+ RADEON_STATECHANGE( rmesa, ctx );
+ if ( state ) {
+ rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_ANTI_ALIAS_POLY;
+ } else {
+ rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_ANTI_ALIAS_POLY;
+ }
+ break;
+
+ case GL_POLYGON_STIPPLE:
+ RADEON_STATECHANGE(rmesa, ctx );
+ if ( state ) {
+ rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_STIPPLE_ENABLE;
+ } else {
+ rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_STIPPLE_ENABLE;
+ }
+ break;
+
+ case GL_RESCALE_NORMAL_EXT: {
+ GLboolean tmp = ctx->_NeedEyeCoords ? state : !state;
+ RADEON_STATECHANGE( rmesa, tcl );
+ if ( tmp ) {
+ rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_RESCALE_NORMALS;
+ } else {
+ rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_RESCALE_NORMALS;
+ }
+ break;
+ }
+
+ case GL_SCISSOR_TEST:
+ RADEON_FIREVERTICES( rmesa );
+ rmesa->state.scissor.enabled = state;
+ radeonUpdateScissor( ctx );
+ break;
+
+ case GL_STENCIL_TEST:
+ if ( rmesa->state.stencil.hwBuffer ) {
+ RADEON_STATECHANGE( rmesa, ctx );
+ if ( state ) {
+ rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_STENCIL_ENABLE;
+ } else {
+ rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_STENCIL_ENABLE;
+ }
+ } else {
+ FALLBACK( rmesa, RADEON_FALLBACK_STENCIL, state );
+ }
+ break;
+
+ case GL_TEXTURE_GEN_Q:
+ case GL_TEXTURE_GEN_R:
+ case GL_TEXTURE_GEN_S:
+ case GL_TEXTURE_GEN_T:
+ /* Picked up in radeonUpdateTextureState.
+ */
+ rmesa->recheck_texgen[ctx->Texture.CurrentUnit] = GL_TRUE;
+ break;
+
+ case GL_COLOR_SUM_EXT:
+ radeonUpdateSpecular ( ctx );
+ break;
+
+ default:
+ return;
+ }
+}
+
+
+static void radeonLightingSpaceChange( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLboolean tmp;
+ RADEON_STATECHANGE( rmesa, tcl );
+
+ if (RADEON_DEBUG & DEBUG_STATE)
+ fprintf(stderr, "%s %d BEFORE %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
+ rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]);
+
+ if (ctx->_NeedEyeCoords)
+ tmp = ctx->Transform.RescaleNormals;
+ else
+ tmp = !ctx->Transform.RescaleNormals;
+
+ if ( tmp ) {
+ rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_RESCALE_NORMALS;
+ } else {
+ rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_RESCALE_NORMALS;
+ }
+
+ if (RADEON_DEBUG & DEBUG_STATE)
+ fprintf(stderr, "%s %d AFTER %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
+ rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]);
+}
+
+/* =============================================================
+ * Deferred state management - matrices, textures, other?
+ */
+
+
+
+
+static void upload_matrix( radeonContextPtr rmesa, GLfloat *src, int idx )
+{
+ float *dest = ((float *)RADEON_DB_STATE( mat[idx] ))+MAT_ELT_0;
+ int i;
+
+
+ for (i = 0 ; i < 4 ; i++) {
+ *dest++ = src[i];
+ *dest++ = src[i+4];
+ *dest++ = src[i+8];
+ *dest++ = src[i+12];
+ }
+
+ RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
+}
+
+static void upload_matrix_t( radeonContextPtr rmesa, GLfloat *src, int idx )
+{
+ float *dest = ((float *)RADEON_DB_STATE( mat[idx] ))+MAT_ELT_0;
+ memcpy(dest, src, 16*sizeof(float));
+ RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
+}
+
+
+static void update_texturematrix( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+ GLuint tpc = rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL];
+ GLuint vs = rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL];
+ int unit;
+
+ rmesa->TexMatEnabled = 0;
+
+ for (unit = 0 ; unit < 2; unit++) {
+ if (!ctx->Texture.Unit[unit]._ReallyEnabled) {
+ }
+ else if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY) {
+ GLuint inputshift = RADEON_TEXGEN_0_INPUT_SHIFT + unit*4;
+
+ rmesa->TexMatEnabled |= (RADEON_TEXGEN_TEXMAT_0_ENABLE|
+ RADEON_TEXMAT_0_ENABLE) << unit;
+
+ if (rmesa->TexGenEnabled & (RADEON_TEXMAT_0_ENABLE << unit)) {
+ /* Need to preconcatenate any active texgen
+ * obj/eyeplane matrices:
+ */
+ _math_matrix_mul_matrix( &rmesa->tmpmat,
+ &rmesa->TexGenMatrix[unit],
+ ctx->TextureMatrixStack[unit].Top );
+ upload_matrix( rmesa, rmesa->tmpmat.m, TEXMAT_0+unit );
+ }
+ else {
+ rmesa->TexMatEnabled |=
+ (RADEON_TEXGEN_INPUT_TEXCOORD_0+unit) << inputshift;
+ upload_matrix( rmesa, ctx->TextureMatrixStack[unit].Top->m,
+ TEXMAT_0+unit );
+ }
+ }
+ else if (rmesa->TexGenEnabled & (RADEON_TEXMAT_0_ENABLE << unit)) {
+ upload_matrix( rmesa, rmesa->TexGenMatrix[unit].m,
+ TEXMAT_0+unit );
+ }
+ }
+
+
+ tpc = (rmesa->TexMatEnabled | rmesa->TexGenEnabled);
+
+ vs &= ~((0xf << RADEON_TCL_TEX_0_OUTPUT_SHIFT) |
+ (0xf << RADEON_TCL_TEX_1_OUTPUT_SHIFT));
+
+ if (tpc & RADEON_TEXGEN_TEXMAT_0_ENABLE)
+ vs |= RADEON_TCL_TEX_COMPUTED_TEX_0 << RADEON_TCL_TEX_0_OUTPUT_SHIFT;
+ else
+ vs |= RADEON_TCL_TEX_INPUT_TEX_0 << RADEON_TCL_TEX_0_OUTPUT_SHIFT;
+
+ if (tpc & RADEON_TEXGEN_TEXMAT_1_ENABLE)
+ vs |= RADEON_TCL_TEX_COMPUTED_TEX_1 << RADEON_TCL_TEX_1_OUTPUT_SHIFT;
+ else
+ vs |= RADEON_TCL_TEX_INPUT_TEX_1 << RADEON_TCL_TEX_1_OUTPUT_SHIFT;
+
+ if (tpc != rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL] ||
+ vs != rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL]) {
+
+ RADEON_STATECHANGE(rmesa, tcl);
+ rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL] = tpc;
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] = vs;
+ }
+}
+
+
+
+void radeonValidateState( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLuint new_state = rmesa->NewGLState;
+
+ if (new_state & _NEW_TEXTURE) {
+ radeonUpdateTextureState( ctx );
+ new_state |= rmesa->NewGLState; /* may add TEXTURE_MATRIX */
+ }
+
+ /* Need an event driven matrix update?
+ */
+ if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION))
+ upload_matrix( rmesa, ctx->_ModelProjectMatrix.m, MODEL_PROJ );
+
+ /* Need these for lighting (shouldn't upload otherwise)
+ */
+ if (new_state & (_NEW_MODELVIEW)) {
+ upload_matrix( rmesa, ctx->ModelviewMatrixStack.Top->m, MODEL );
+ upload_matrix_t( rmesa, ctx->ModelviewMatrixStack.Top->inv, MODEL_IT );
+ }
+
+ /* Does this need to be triggered on eg. modelview for
+ * texgen-derived objplane/eyeplane matrices?
+ */
+ if (new_state & _NEW_TEXTURE_MATRIX) {
+ update_texturematrix( ctx );
+ }
+
+ if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW|_MESA_NEW_NEED_EYE_COORDS)) {
+ update_light( ctx );
+ }
+
+ /* emit all active clip planes if projection matrix changes.
+ */
+ if (new_state & (_NEW_PROJECTION)) {
+ if (ctx->Transform.ClipPlanesEnabled)
+ radeonUpdateClipPlanes( ctx );
+ }
+
+
+ rmesa->NewGLState = 0;
+}
+
+
+static void radeonInvalidateState( GLcontext *ctx, GLuint new_state )
+{
+ _swrast_InvalidateState( ctx, new_state );
+ _swsetup_InvalidateState( ctx, new_state );
+ _ac_InvalidateState( ctx, new_state );
+ _tnl_InvalidateState( ctx, new_state );
+ _ae_invalidate_state( ctx, new_state );
+ RADEON_CONTEXT(ctx)->NewGLState |= new_state;
+ radeonVtxfmtInvalidate( ctx );
+}
+
+static void radeonWrapRunPipeline( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+ if (0)
+ fprintf(stderr, "%s, newstate: %x\n", __FUNCTION__, rmesa->NewGLState);
+
+ /* Validate state:
+ */
+ if (rmesa->NewGLState)
+ radeonValidateState( ctx );
+
+ if (tnl->vb.Material) {
+ TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_MATERIAL, GL_TRUE );
+ }
+
+ /* Run the pipeline.
+ */
+ _tnl_run_pipeline( ctx );
+
+ if (tnl->vb.Material) {
+ TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_MATERIAL, GL_FALSE );
+ radeonUpdateMaterial( ctx ); /* not needed any more? */
+ }
+}
+
+
+/* Initialize the driver's state functions.
+ */
+void radeonInitStateFuncs( GLcontext *ctx )
+{
+ ctx->Driver.UpdateState = radeonInvalidateState;
+ ctx->Driver.LightingSpaceChange = radeonLightingSpaceChange;
+
+ ctx->Driver.DrawBuffer = radeonDrawBuffer;
+ ctx->Driver.ReadBuffer = radeonReadBuffer;
+
+ ctx->Driver.AlphaFunc = radeonAlphaFunc;
+ ctx->Driver.BlendEquation = radeonBlendEquation;
+ ctx->Driver.BlendFunc = radeonBlendFunc;
+ ctx->Driver.BlendFuncSeparate = radeonBlendFuncSeparate;
+ ctx->Driver.ClearColor = radeonClearColor;
+ ctx->Driver.ClearDepth = radeonClearDepth;
+ ctx->Driver.ClearIndex = NULL;
+ ctx->Driver.ClearStencil = radeonClearStencil;
+ ctx->Driver.ClipPlane = radeonClipPlane;
+ ctx->Driver.ColorMask = radeonColorMask;
+ ctx->Driver.CullFace = radeonCullFace;
+ ctx->Driver.DepthFunc = radeonDepthFunc;
+ ctx->Driver.DepthMask = radeonDepthMask;
+ ctx->Driver.DepthRange = radeonDepthRange;
+ ctx->Driver.Enable = radeonEnable;
+ ctx->Driver.Fogfv = radeonFogfv;
+ ctx->Driver.FrontFace = radeonFrontFace;
+ ctx->Driver.Hint = NULL;
+ ctx->Driver.IndexMask = NULL;
+ ctx->Driver.LightModelfv = radeonLightModelfv;
+ ctx->Driver.Lightfv = radeonLightfv;
+ ctx->Driver.LineStipple = radeonLineStipple;
+ ctx->Driver.LineWidth = radeonLineWidth;
+ ctx->Driver.LogicOpcode = radeonLogicOpCode;
+ ctx->Driver.PolygonMode = radeonPolygonMode;
+
+ if (RADEON_CONTEXT(ctx)->dri.drmMinor > 1)
+ ctx->Driver.PolygonOffset = radeonPolygonOffset;
+
+ ctx->Driver.PolygonStipple = radeonPolygonStipple;
+ ctx->Driver.RenderMode = radeonRenderMode;
+ ctx->Driver.Scissor = radeonScissor;
+ ctx->Driver.ShadeModel = radeonShadeModel;
+ ctx->Driver.StencilFunc = radeonStencilFunc;
+ ctx->Driver.StencilMask = radeonStencilMask;
+ ctx->Driver.StencilOp = radeonStencilOp;
+ ctx->Driver.Viewport = radeonViewport;
+
+ /* Pixel path fallbacks
+ */
+ ctx->Driver.Accum = _swrast_Accum;
+ ctx->Driver.Bitmap = _swrast_Bitmap;
+ ctx->Driver.CopyPixels = _swrast_CopyPixels;
+ ctx->Driver.DrawPixels = _swrast_DrawPixels;
+ ctx->Driver.ReadPixels = _swrast_ReadPixels;
+
+ /* Swrast hooks for imaging extensions:
+ */
+ ctx->Driver.CopyColorTable = _swrast_CopyColorTable;
+ ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable;
+ ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
+ ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
+
+ TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange = radeonUpdateMaterial;
+ TNL_CONTEXT(ctx)->Driver.RunPipeline = radeonWrapRunPipeline;
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_state.h b/src/mesa/drivers/dri/radeon/radeon_state.h
new file mode 100644
index 0000000000..a181d427e6
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_state.h
@@ -0,0 +1,77 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_state.h,v 1.5 2002/11/05 17:46:09 tsi 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 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 THE COPYRIGHT OWNER(S) 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:
+ * Kevin E. Martin <martin@valinux.com>
+ * Gareth Hughes <gareth@valinux.com>
+ *
+ */
+
+#ifndef __RADEON_STATE_H__
+#define __RADEON_STATE_H__
+
+#ifdef GLX_DIRECT_RENDERING
+
+#include "radeon_context.h"
+
+extern void radeonInitState( radeonContextPtr rmesa );
+extern void radeonInitStateFuncs( GLcontext *ctx );
+
+extern void radeonUpdateMaterial( GLcontext *ctx );
+
+extern void radeonSetCliprects( radeonContextPtr rmesa, GLenum mode );
+extern void radeonRecalcScissorRects( radeonContextPtr rmesa );
+extern void radeonUpdateViewportOffset( GLcontext *ctx );
+extern void radeonUpdateWindow( GLcontext *ctx );
+
+extern void radeonValidateState( GLcontext *ctx );
+
+extern void radeonPrintDirty( radeonContextPtr rmesa,
+ const char *msg );
+
+
+extern void radeonFallback( GLcontext *ctx, GLuint bit, GLboolean mode );
+#define FALLBACK( rmesa, bit, mode ) do { \
+ if ( 0 ) fprintf( stderr, "FALLBACK in %s: #%d=%d\n", \
+ __FUNCTION__, bit, mode ); \
+ radeonFallback( rmesa->glCtx, bit, mode ); \
+} while (0)
+
+
+#define MODEL_PROJ 0
+#define MODEL 1
+#define MODEL_IT 2
+#define TEXMAT_0 3
+#define TEXMAT_1 4
+#define TEXMAT_2 5
+
+#endif
+#endif
diff --git a/src/mesa/drivers/dri/radeon/radeon_state_init.c b/src/mesa/drivers/dri/radeon/radeon_state_init.c
new file mode 100644
index 0000000000..971ea699ea
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_state_init.c
@@ -0,0 +1,531 @@
+/* $XFree86$ */
+/*
+ * Copyright 2000, 2001 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
+ * 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:
+ * Gareth Hughes <gareth@valinux.com>
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "glheader.h"
+#include "imports.h"
+#include "api_arrayelt.h"
+
+#include "swrast/swrast.h"
+#include "array_cache/acache.h"
+#include "tnl/tnl.h"
+#include "tnl/t_pipeline.h"
+#include "swrast_setup/swrast_setup.h"
+
+#include "radeon_context.h"
+#include "radeon_ioctl.h"
+#include "radeon_state.h"
+#include "radeon_tcl.h"
+#include "radeon_tex.h"
+#include "radeon_swtcl.h"
+#include "radeon_vtxfmt.h"
+
+/* =============================================================
+ * State initialization
+ */
+
+void radeonPrintDirty( radeonContextPtr rmesa, const char *msg )
+{
+ struct radeon_state_atom *l;
+
+ fprintf(stderr, msg);
+ fprintf(stderr, ": ");
+
+ foreach(l, &(rmesa->hw.dirty)) {
+ fprintf(stderr, "%s, ", l->name);
+ }
+
+ fprintf(stderr, "\n");
+}
+
+static int cmdpkt( int id )
+{
+ drmRadeonCmdHeader h;
+ h.i = 0;
+ h.packet.cmd_type = RADEON_CMD_PACKET;
+ h.packet.packet_id = id;
+ return h.i;
+}
+
+static int cmdvec( int offset, int stride, int count )
+{
+ drmRadeonCmdHeader h;
+ h.i = 0;
+ h.vectors.cmd_type = RADEON_CMD_VECTORS;
+ h.vectors.offset = offset;
+ h.vectors.stride = stride;
+ h.vectors.count = count;
+ return h.i;
+}
+
+static int cmdscl( int offset, int stride, int count )
+{
+ drmRadeonCmdHeader h;
+ h.i = 0;
+ h.scalars.cmd_type = RADEON_CMD_SCALARS;
+ h.scalars.offset = offset;
+ h.scalars.stride = stride;
+ h.scalars.count = count;
+ return h.i;
+}
+
+#define CHECK( NM, FLAG ) \
+static GLboolean check_##NM( GLcontext *ctx ) \
+{ \
+ return FLAG; \
+}
+
+#define TCL_CHECK( NM, FLAG ) \
+static GLboolean check_##NM( GLcontext *ctx ) \
+{ \
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \
+ return !rmesa->TclFallback && (FLAG); \
+}
+
+
+CHECK( always, GL_TRUE )
+CHECK( tex0, ctx->Texture.Unit[0]._ReallyEnabled )
+CHECK( tex1, ctx->Texture.Unit[1]._ReallyEnabled )
+CHECK( fog, ctx->Fog.Enabled )
+TCL_CHECK( tcl, GL_TRUE )
+TCL_CHECK( tcl_tex0, ctx->Texture.Unit[0]._ReallyEnabled )
+TCL_CHECK( tcl_tex1, ctx->Texture.Unit[1]._ReallyEnabled )
+TCL_CHECK( tcl_lighting, ctx->Light.Enabled )
+TCL_CHECK( tcl_eyespace_or_lighting, ctx->_NeedEyeCoords || ctx->Light.Enabled )
+TCL_CHECK( tcl_lit0, ctx->Light.Enabled && ctx->Light.Light[0].Enabled )
+TCL_CHECK( tcl_lit1, ctx->Light.Enabled && ctx->Light.Light[1].Enabled )
+TCL_CHECK( tcl_lit2, ctx->Light.Enabled && ctx->Light.Light[2].Enabled )
+TCL_CHECK( tcl_lit3, ctx->Light.Enabled && ctx->Light.Light[3].Enabled )
+TCL_CHECK( tcl_lit4, ctx->Light.Enabled && ctx->Light.Light[4].Enabled )
+TCL_CHECK( tcl_lit5, ctx->Light.Enabled && ctx->Light.Light[5].Enabled )
+TCL_CHECK( tcl_lit6, ctx->Light.Enabled && ctx->Light.Light[6].Enabled )
+TCL_CHECK( tcl_lit7, ctx->Light.Enabled && ctx->Light.Light[7].Enabled )
+TCL_CHECK( tcl_ucp0, (ctx->Transform.ClipPlanesEnabled & 0x1) )
+TCL_CHECK( tcl_ucp1, (ctx->Transform.ClipPlanesEnabled & 0x2) )
+TCL_CHECK( tcl_ucp2, (ctx->Transform.ClipPlanesEnabled & 0x4) )
+TCL_CHECK( tcl_ucp3, (ctx->Transform.ClipPlanesEnabled & 0x8) )
+TCL_CHECK( tcl_ucp4, (ctx->Transform.ClipPlanesEnabled & 0x10) )
+TCL_CHECK( tcl_ucp5, (ctx->Transform.ClipPlanesEnabled & 0x20) )
+TCL_CHECK( tcl_eyespace_or_fog, ctx->_NeedEyeCoords || ctx->Fog.Enabled )
+
+CHECK( txr0, (ctx->Texture.Unit[0]._ReallyEnabled & TEXTURE_RECT_BIT))
+CHECK( txr1, (ctx->Texture.Unit[1]._ReallyEnabled & TEXTURE_RECT_BIT))
+
+
+
+/* Initialize the context's hardware state.
+ */
+void radeonInitState( radeonContextPtr rmesa )
+{
+ GLcontext *ctx = rmesa->glCtx;
+ GLuint color_fmt, depth_fmt, i;
+
+ switch ( rmesa->radeonScreen->cpp ) {
+ case 2:
+ color_fmt = RADEON_COLOR_FORMAT_RGB565;
+ break;
+ case 4:
+ color_fmt = RADEON_COLOR_FORMAT_ARGB8888;
+ break;
+ default:
+ fprintf( stderr, "Error: Unsupported pixel depth... exiting\n" );
+ exit( -1 );
+ }
+
+ rmesa->state.color.clear = 0x00000000;
+
+ switch ( ctx->Visual.depthBits ) {
+ case 16:
+ rmesa->state.depth.clear = 0x0000ffff;
+ rmesa->state.depth.scale = 1.0 / (GLfloat)0xffff;
+ depth_fmt = RADEON_DEPTH_FORMAT_16BIT_INT_Z;
+ rmesa->state.stencil.clear = 0x00000000;
+ break;
+ case 24:
+ rmesa->state.depth.clear = 0x00ffffff;
+ rmesa->state.depth.scale = 1.0 / (GLfloat)0xffffff;
+ depth_fmt = RADEON_DEPTH_FORMAT_24BIT_INT_Z;
+ rmesa->state.stencil.clear = 0xff000000;
+ break;
+ default:
+ fprintf( stderr, "Error: Unsupported depth %d... exiting\n",
+ ctx->Visual.depthBits );
+ exit( -1 );
+ }
+
+ /* Only have hw stencil when depth buffer is 24 bits deep */
+ rmesa->state.stencil.hwBuffer = ( ctx->Visual.stencilBits > 0 &&
+ ctx->Visual.depthBits == 24 );
+
+ rmesa->Fallback = 0;
+
+ if ( ctx->Visual.doubleBufferMode && rmesa->sarea->pfCurrentPage == 0 ) {
+ rmesa->state.color.drawOffset = rmesa->radeonScreen->backOffset;
+ rmesa->state.color.drawPitch = rmesa->radeonScreen->backPitch;
+ } else {
+ rmesa->state.color.drawOffset = rmesa->radeonScreen->frontOffset;
+ rmesa->state.color.drawPitch = rmesa->radeonScreen->frontPitch;
+ }
+ rmesa->state.pixel.readOffset = rmesa->state.color.drawOffset;
+ rmesa->state.pixel.readPitch = rmesa->state.color.drawPitch;
+
+ /* Initialize lists:
+ */
+ make_empty_list(&(rmesa->hw.dirty));
+ make_empty_list(&(rmesa->hw.clean));
+
+
+#define ALLOC_STATE( ATOM, CHK, SZ, NM, FLAG ) \
+ do { \
+ rmesa->hw.ATOM.cmd_size = SZ; \
+ rmesa->hw.ATOM.cmd = (int *)CALLOC(SZ * sizeof(int)); \
+ rmesa->hw.ATOM.lastcmd = (int *)CALLOC(SZ * sizeof(int)); \
+ rmesa->hw.ATOM.name = NM; \
+ rmesa->hw.ATOM.is_tcl = FLAG; \
+ rmesa->hw.ATOM.check = check_##CHK; \
+ insert_at_head(&(rmesa->hw.dirty), &(rmesa->hw.ATOM)); \
+ } while (0)
+
+
+ /* Allocate state buffers:
+ */
+ ALLOC_STATE( ctx, always, CTX_STATE_SIZE, "CTX/context", 0 );
+ ALLOC_STATE( lin, always, LIN_STATE_SIZE, "LIN/line", 0 );
+ ALLOC_STATE( msk, always, MSK_STATE_SIZE, "MSK/mask", 0 );
+ ALLOC_STATE( vpt, always, VPT_STATE_SIZE, "VPT/viewport", 0 );
+ ALLOC_STATE( set, always, SET_STATE_SIZE, "SET/setup", 0 );
+ ALLOC_STATE( msc, always, MSC_STATE_SIZE, "MSC/misc", 0 );
+ ALLOC_STATE( zbs, always, ZBS_STATE_SIZE, "ZBS/zbias", 0 );
+ ALLOC_STATE( tcl, always, TCL_STATE_SIZE, "TCL/tcl", 1 );
+ ALLOC_STATE( mtl, tcl_lighting, MTL_STATE_SIZE, "MTL/material", 1 );
+ ALLOC_STATE( grd, always, GRD_STATE_SIZE, "GRD/guard-band", 1 );
+ ALLOC_STATE( fog, fog, FOG_STATE_SIZE, "FOG/fog", 1 );
+ ALLOC_STATE( glt, tcl_lighting, GLT_STATE_SIZE, "GLT/light-global", 1 );
+ ALLOC_STATE( eye, tcl_lighting, EYE_STATE_SIZE, "EYE/eye-vector", 1 );
+ ALLOC_STATE( tex[0], tex0, TEX_STATE_SIZE, "TEX/tex-0", 0 );
+ ALLOC_STATE( tex[1], tex1, TEX_STATE_SIZE, "TEX/tex-1", 0 );
+ ALLOC_STATE( mat[0], tcl, MAT_STATE_SIZE, "MAT/modelproject", 1 );
+ ALLOC_STATE( mat[1], tcl_eyespace_or_fog, MAT_STATE_SIZE, "MAT/modelview", 1 );
+ ALLOC_STATE( mat[2], tcl_eyespace_or_lighting, MAT_STATE_SIZE, "MAT/it-modelview", 1 );
+ ALLOC_STATE( mat[3], tcl_tex0, MAT_STATE_SIZE, "MAT/texmat0", 1 );
+ ALLOC_STATE( mat[4], tcl_tex1, MAT_STATE_SIZE, "MAT/texmat1", 1 );
+ ALLOC_STATE( ucp[0], tcl_ucp0, UCP_STATE_SIZE, "UCP/userclip-0", 1 );
+ ALLOC_STATE( ucp[1], tcl_ucp1, UCP_STATE_SIZE, "UCP/userclip-1", 1 );
+ ALLOC_STATE( ucp[2], tcl_ucp2, UCP_STATE_SIZE, "UCP/userclip-2", 1 );
+ ALLOC_STATE( ucp[3], tcl_ucp3, UCP_STATE_SIZE, "UCP/userclip-3", 1 );
+ ALLOC_STATE( ucp[4], tcl_ucp4, UCP_STATE_SIZE, "UCP/userclip-4", 1 );
+ ALLOC_STATE( ucp[5], tcl_ucp5, UCP_STATE_SIZE, "UCP/userclip-5", 1 );
+ ALLOC_STATE( lit[0], tcl_lit0, LIT_STATE_SIZE, "LIT/light-0", 1 );
+ ALLOC_STATE( lit[1], tcl_lit1, LIT_STATE_SIZE, "LIT/light-1", 1 );
+ ALLOC_STATE( lit[2], tcl_lit2, LIT_STATE_SIZE, "LIT/light-2", 1 );
+ ALLOC_STATE( lit[3], tcl_lit3, LIT_STATE_SIZE, "LIT/light-3", 1 );
+ ALLOC_STATE( lit[4], tcl_lit4, LIT_STATE_SIZE, "LIT/light-4", 1 );
+ ALLOC_STATE( lit[5], tcl_lit5, LIT_STATE_SIZE, "LIT/light-5", 1 );
+ ALLOC_STATE( lit[6], tcl_lit6, LIT_STATE_SIZE, "LIT/light-6", 1 );
+ ALLOC_STATE( lit[7], tcl_lit7, LIT_STATE_SIZE, "LIT/light-7", 1 );
+ ALLOC_STATE( txr[0], txr0, TXR_STATE_SIZE, "TXR/txr-0", 0 );
+ ALLOC_STATE( txr[1], txr1, TXR_STATE_SIZE, "TXR/txr-1", 0 );
+
+
+ /* Fill in the packet headers:
+ */
+ rmesa->hw.ctx.cmd[CTX_CMD_0] = cmdpkt(RADEON_EMIT_PP_MISC);
+ rmesa->hw.ctx.cmd[CTX_CMD_1] = cmdpkt(RADEON_EMIT_PP_CNTL);
+ rmesa->hw.ctx.cmd[CTX_CMD_2] = cmdpkt(RADEON_EMIT_RB3D_COLORPITCH);
+ rmesa->hw.lin.cmd[LIN_CMD_0] = cmdpkt(RADEON_EMIT_RE_LINE_PATTERN);
+ rmesa->hw.lin.cmd[LIN_CMD_1] = cmdpkt(RADEON_EMIT_SE_LINE_WIDTH);
+ rmesa->hw.msk.cmd[MSK_CMD_0] = cmdpkt(RADEON_EMIT_RB3D_STENCILREFMASK);
+ rmesa->hw.vpt.cmd[VPT_CMD_0] = cmdpkt(RADEON_EMIT_SE_VPORT_XSCALE);
+ rmesa->hw.set.cmd[SET_CMD_0] = cmdpkt(RADEON_EMIT_SE_CNTL);
+ rmesa->hw.set.cmd[SET_CMD_1] = cmdpkt(RADEON_EMIT_SE_CNTL_STATUS);
+ rmesa->hw.msc.cmd[MSC_CMD_0] = cmdpkt(RADEON_EMIT_RE_MISC);
+ rmesa->hw.tex[0].cmd[TEX_CMD_0] = cmdpkt(RADEON_EMIT_PP_TXFILTER_0);
+ rmesa->hw.tex[0].cmd[TEX_CMD_1] = cmdpkt(RADEON_EMIT_PP_BORDER_COLOR_0);
+ rmesa->hw.tex[1].cmd[TEX_CMD_0] = cmdpkt(RADEON_EMIT_PP_TXFILTER_1);
+ rmesa->hw.tex[1].cmd[TEX_CMD_1] = cmdpkt(RADEON_EMIT_PP_BORDER_COLOR_1);
+ rmesa->hw.zbs.cmd[ZBS_CMD_0] = cmdpkt(RADEON_EMIT_SE_ZBIAS_FACTOR);
+ rmesa->hw.tcl.cmd[TCL_CMD_0] = cmdpkt(RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT);
+ rmesa->hw.mtl.cmd[MTL_CMD_0] =
+ cmdpkt(RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED);
+ rmesa->hw.txr[0].cmd[TXR_CMD_0] = cmdpkt(RADEON_EMIT_PP_TEX_SIZE_0);
+ rmesa->hw.txr[1].cmd[TXR_CMD_0] = cmdpkt(RADEON_EMIT_PP_TEX_SIZE_1);
+ rmesa->hw.grd.cmd[GRD_CMD_0] =
+ cmdscl( RADEON_SS_VERT_GUARD_CLIP_ADJ_ADDR, 1, 4 );
+ rmesa->hw.fog.cmd[FOG_CMD_0] =
+ cmdvec( RADEON_VS_FOG_PARAM_ADDR, 1, 4 );
+ rmesa->hw.glt.cmd[GLT_CMD_0] =
+ cmdvec( RADEON_VS_GLOBAL_AMBIENT_ADDR, 1, 4 );
+ rmesa->hw.eye.cmd[EYE_CMD_0] =
+ cmdvec( RADEON_VS_EYE_VECTOR_ADDR, 1, 4 );
+
+ for (i = 0 ; i < 5; i++) {
+ rmesa->hw.mat[i].cmd[MAT_CMD_0] =
+ cmdvec( RADEON_VS_MATRIX_0_ADDR + i*4, 1, 16);
+ }
+
+ for (i = 0 ; i < 8; i++) {
+ rmesa->hw.lit[i].cmd[LIT_CMD_0] =
+ cmdvec( RADEON_VS_LIGHT_AMBIENT_ADDR + i, 8, 24 );
+ rmesa->hw.lit[i].cmd[LIT_CMD_1] =
+ cmdscl( RADEON_SS_LIGHT_DCD_ADDR + i, 8, 6 );
+ }
+
+ for (i = 0 ; i < 6; i++) {
+ rmesa->hw.ucp[i].cmd[UCP_CMD_0] =
+ cmdvec( RADEON_VS_UCP_ADDR + i, 1, 4 );
+ }
+
+ rmesa->last_ReallyEnabled = -1;
+
+ /* Initial Harware state:
+ */
+ rmesa->hw.ctx.cmd[CTX_PP_MISC] = (RADEON_ALPHA_TEST_PASS |
+ RADEON_CHROMA_FUNC_FAIL |
+ RADEON_CHROMA_KEY_NEAREST |
+ RADEON_SHADOW_FUNC_EQUAL |
+ RADEON_SHADOW_PASS_1 |
+ RADEON_RIGHT_HAND_CUBE_OGL);
+
+ rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] = (RADEON_FOG_VERTEX |
+ RADEON_FOG_USE_DEPTH);
+
+ rmesa->hw.ctx.cmd[CTX_RE_SOLID_COLOR] = 0x00000000;
+
+ rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = (RADEON_COMB_FCN_ADD_CLAMP |
+ RADEON_SRC_BLEND_GL_ONE |
+ RADEON_DST_BLEND_GL_ZERO );
+
+ rmesa->hw.ctx.cmd[CTX_RB3D_DEPTHOFFSET] =
+ rmesa->radeonScreen->depthOffset;
+
+ rmesa->hw.ctx.cmd[CTX_RB3D_DEPTHPITCH] =
+ ((rmesa->radeonScreen->depthPitch &
+ RADEON_DEPTHPITCH_MASK) |
+ RADEON_DEPTH_ENDIAN_NO_SWAP);
+
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] = (depth_fmt |
+ RADEON_Z_TEST_LESS |
+ RADEON_STENCIL_TEST_ALWAYS |
+ RADEON_STENCIL_FAIL_KEEP |
+ RADEON_STENCIL_ZPASS_KEEP |
+ RADEON_STENCIL_ZFAIL_KEEP |
+ RADEON_Z_WRITE_ENABLE);
+
+ rmesa->hw.ctx.cmd[CTX_PP_CNTL] = (RADEON_SCISSOR_ENABLE |
+ RADEON_ANTI_ALIAS_NONE);
+
+ rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = (RADEON_PLANE_MASK_ENABLE |
+ color_fmt |
+ (1<<15));
+
+ rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_DITHER_ENABLE;
+
+ rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = (rmesa->state.color.drawOffset &
+ RADEON_COLOROFFSET_MASK);
+
+ rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = ((rmesa->state.color.drawPitch &
+ RADEON_COLORPITCH_MASK) |
+ RADEON_COLOR_ENDIAN_NO_SWAP);
+
+ rmesa->hw.set.cmd[SET_SE_CNTL] = (RADEON_FFACE_CULL_CCW |
+ RADEON_BFACE_SOLID |
+ RADEON_FFACE_SOLID |
+/* RADEON_BADVTX_CULL_DISABLE | */
+ RADEON_FLAT_SHADE_VTX_LAST |
+ RADEON_DIFFUSE_SHADE_GOURAUD |
+ RADEON_ALPHA_SHADE_GOURAUD |
+ RADEON_SPECULAR_SHADE_GOURAUD |
+ RADEON_FOG_SHADE_GOURAUD |
+ RADEON_VPORT_XY_XFORM_ENABLE |
+ RADEON_VPORT_Z_XFORM_ENABLE |
+ RADEON_VTX_PIX_CENTER_OGL |
+ RADEON_ROUND_MODE_TRUNC |
+ RADEON_ROUND_PREC_8TH_PIX);
+
+ rmesa->hw.set.cmd[SET_SE_CNTL_STATUS] =
+#ifdef MESA_BIG_ENDIAN
+ RADEON_VC_32BIT_SWAP;
+#else
+ RADEON_VC_NO_SWAP;
+#endif
+
+ if (!(rmesa->radeonScreen->chipset & RADEON_CHIPSET_TCL)) {
+ rmesa->hw.set.cmd[SET_SE_CNTL_STATUS] |= RADEON_TCL_BYPASS;
+ }
+
+ rmesa->hw.set.cmd[SET_SE_COORDFMT] = (
+ RADEON_VTX_W0_IS_NOT_1_OVER_W0 |
+ RADEON_TEX1_W_ROUTING_USE_Q1);
+
+
+ rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] = ((1 << 16) | 0xffff);
+
+ rmesa->hw.lin.cmd[LIN_RE_LINE_STATE] =
+ ((0 << RADEON_LINE_CURRENT_PTR_SHIFT) |
+ (1 << RADEON_LINE_CURRENT_COUNT_SHIFT));
+
+ rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] = (1 << 4);
+
+ rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] =
+ ((0x00 << RADEON_STENCIL_REF_SHIFT) |
+ (0xff << RADEON_STENCIL_MASK_SHIFT) |
+ (0xff << RADEON_STENCIL_WRITEMASK_SHIFT));
+
+ rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = RADEON_ROP_COPY;
+ rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] = 0xffffffff;
+
+ rmesa->hw.msc.cmd[MSC_RE_MISC] =
+ ((0 << RADEON_STIPPLE_X_OFFSET_SHIFT) |
+ (0 << RADEON_STIPPLE_Y_OFFSET_SHIFT) |
+ RADEON_STIPPLE_BIG_BIT_ORDER);
+
+ rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE] = 0x00000000;
+ rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = 0x00000000;
+ rmesa->hw.vpt.cmd[VPT_SE_VPORT_YSCALE] = 0x00000000;
+ rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = 0x00000000;
+ rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE] = 0x00000000;
+ rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = 0x00000000;
+
+ for ( i = 0 ; i < ctx->Const.MaxTextureUnits ; i++ ) {
+ rmesa->hw.tex[i].cmd[TEX_PP_TXFILTER] = RADEON_BORDER_MODE_OGL;
+ rmesa->hw.tex[i].cmd[TEX_PP_TXFORMAT] =
+ (RADEON_TXFORMAT_ENDIAN_NO_SWAP |
+ RADEON_TXFORMAT_PERSPECTIVE_ENABLE |
+ (i << 24) | /* This is one of RADEON_TXFORMAT_ST_ROUTE_STQ[012] */
+ (2 << RADEON_TXFORMAT_WIDTH_SHIFT) |
+ (2 << RADEON_TXFORMAT_HEIGHT_SHIFT));
+
+ /* FIXME: What is this magic value? */
+ rmesa->hw.tex[i].cmd[TEX_PP_TXOFFSET] = 0x2000 << (2 * i);
+
+ rmesa->hw.tex[i].cmd[TEX_PP_BORDER_COLOR] = 0;
+ rmesa->hw.tex[i].cmd[TEX_PP_TXCBLEND] =
+ (RADEON_COLOR_ARG_A_ZERO |
+ RADEON_COLOR_ARG_B_ZERO |
+ RADEON_COLOR_ARG_C_CURRENT_COLOR |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX);
+ rmesa->hw.tex[i].cmd[TEX_PP_TXABLEND] =
+ (RADEON_ALPHA_ARG_A_ZERO |
+ RADEON_ALPHA_ARG_B_ZERO |
+ RADEON_ALPHA_ARG_C_CURRENT_ALPHA |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX);
+ rmesa->hw.tex[i].cmd[TEX_PP_TFACTOR] = 0;
+ }
+
+ /* Can only add ST1 at the time of doing some multitex but can keep
+ * it after that. Errors if DIFFUSE is missing.
+ */
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] =
+ (RADEON_TCL_VTX_Z0 |
+ RADEON_TCL_VTX_W0 |
+ RADEON_TCL_VTX_PK_DIFFUSE
+ ); /* need to keep this uptodate */
+
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] =
+ ( RADEON_TCL_COMPUTE_XYZW |
+ (RADEON_TCL_TEX_INPUT_TEX_0 << RADEON_TCL_TEX_0_OUTPUT_SHIFT) |
+ (RADEON_TCL_TEX_INPUT_TEX_1 << RADEON_TCL_TEX_1_OUTPUT_SHIFT) |
+ (RADEON_TCL_TEX_INPUT_TEX_2 << RADEON_TCL_TEX_2_OUTPUT_SHIFT));
+
+
+ /* XXX */
+ rmesa->hw.tcl.cmd[TCL_MATRIX_SELECT_0] =
+ ((MODEL << RADEON_MODELVIEW_0_SHIFT) |
+ (MODEL_IT << RADEON_IT_MODELVIEW_0_SHIFT));
+
+ rmesa->hw.tcl.cmd[TCL_MATRIX_SELECT_1] =
+ ((MODEL_PROJ << RADEON_MODELPROJECT_0_SHIFT) |
+ (TEXMAT_0 << RADEON_TEXMAT_0_SHIFT) |
+ (TEXMAT_1 << RADEON_TEXMAT_1_SHIFT));
+
+ rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] =
+ (RADEON_UCP_IN_CLIP_SPACE |
+ RADEON_CULL_FRONT_IS_CCW);
+
+ rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL] = 0;
+
+ rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] =
+ (RADEON_SPECULAR_LIGHTS |
+ RADEON_DIFFUSE_SPECULAR_COMBINE |
+ RADEON_LOCAL_LIGHT_VEC_GL |
+ (RADEON_LM_SOURCE_STATE_PREMULT << RADEON_EMISSIVE_SOURCE_SHIFT) |
+ (RADEON_LM_SOURCE_STATE_PREMULT << RADEON_AMBIENT_SOURCE_SHIFT) |
+ (RADEON_LM_SOURCE_STATE_PREMULT << RADEON_DIFFUSE_SOURCE_SHIFT) |
+ (RADEON_LM_SOURCE_STATE_PREMULT << RADEON_SPECULAR_SOURCE_SHIFT));
+
+ for (i = 0 ; i < 8; i++) {
+ struct gl_light *l = &ctx->Light.Light[i];
+ GLenum p = GL_LIGHT0 + i;
+ *(float *)&(rmesa->hw.lit[i].cmd[LIT_RANGE_CUTOFF]) = FLT_MAX;
+
+ ctx->Driver.Lightfv( ctx, p, GL_AMBIENT, l->Ambient );
+ ctx->Driver.Lightfv( ctx, p, GL_DIFFUSE, l->Diffuse );
+ ctx->Driver.Lightfv( ctx, p, GL_SPECULAR, l->Specular );
+ ctx->Driver.Lightfv( ctx, p, GL_POSITION, 0 );
+ ctx->Driver.Lightfv( ctx, p, GL_SPOT_DIRECTION, 0 );
+ ctx->Driver.Lightfv( ctx, p, GL_SPOT_EXPONENT, &l->SpotExponent );
+ ctx->Driver.Lightfv( ctx, p, GL_SPOT_CUTOFF, &l->SpotCutoff );
+ ctx->Driver.Lightfv( ctx, p, GL_CONSTANT_ATTENUATION,
+ &l->ConstantAttenuation );
+ ctx->Driver.Lightfv( ctx, p, GL_LINEAR_ATTENUATION,
+ &l->LinearAttenuation );
+ ctx->Driver.Lightfv( ctx, p, GL_QUADRATIC_ATTENUATION,
+ &l->QuadraticAttenuation );
+ }
+
+ ctx->Driver.LightModelfv( ctx, GL_LIGHT_MODEL_AMBIENT,
+ ctx->Light.Model.Ambient );
+
+ TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx );
+
+ for (i = 0 ; i < 6; i++) {
+ ctx->Driver.ClipPlane( ctx, GL_CLIP_PLANE0 + i, NULL );
+ }
+
+ ctx->Driver.Fogfv( ctx, GL_FOG_MODE, 0 );
+ ctx->Driver.Fogfv( ctx, GL_FOG_DENSITY, &ctx->Fog.Density );
+ ctx->Driver.Fogfv( ctx, GL_FOG_START, &ctx->Fog.Start );
+ ctx->Driver.Fogfv( ctx, GL_FOG_END, &ctx->Fog.End );
+ ctx->Driver.Fogfv( ctx, GL_FOG_COLOR, ctx->Fog.Color );
+ ctx->Driver.Fogfv( ctx, GL_FOG_COORDINATE_SOURCE_EXT, 0 );
+
+ rmesa->hw.grd.cmd[GRD_VERT_GUARD_CLIP_ADJ] = IEEE_ONE;
+ rmesa->hw.grd.cmd[GRD_VERT_GUARD_DISCARD_ADJ] = IEEE_ONE;
+ rmesa->hw.grd.cmd[GRD_HORZ_GUARD_CLIP_ADJ] = IEEE_ONE;
+ rmesa->hw.grd.cmd[GRD_HORZ_GUARD_DISCARD_ADJ] = IEEE_ONE;
+
+ rmesa->hw.eye.cmd[EYE_X] = 0;
+ rmesa->hw.eye.cmd[EYE_Y] = 0;
+ rmesa->hw.eye.cmd[EYE_Z] = IEEE_ONE;
+ rmesa->hw.eye.cmd[EYE_RESCALE_FACTOR] = IEEE_ONE;
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_subset.h b/src/mesa/drivers/dri/radeon/radeon_subset.h
new file mode 100644
index 0000000000..1b6e7bd432
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_subset.h
@@ -0,0 +1,75 @@
+/**
+ * \file radeon_subset.h
+ * \brief Radeon subset driver declarations.
+ *
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+/*
+ * Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+ * Tungsten Grahpics Inc., Austin, Texas.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * 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, TUNGSTEN GRAHPICS 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.
+ */
+
+/* $XFree86$ */
+
+#ifndef __RADEON_SUBSET_H__
+#define __RADEON_SUBSET_H__
+
+extern void radeonPointsBitmap( GLsizei width, GLsizei height,
+ GLfloat xorig, GLfloat yorig,
+ GLfloat xmove, GLfloat ymove,
+ const GLubyte *bitmap );
+
+extern void radeonReadPixels( GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ GLvoid *pixels );
+
+extern void radeon_select_Install( GLcontext *ctx );
+
+extern void radeonInitSelect( GLcontext *ctx );
+
+extern void radeonVtxfmtDestroy( GLcontext *ctx );
+
+extern void radeonVtxfmtMakeCurrent( GLcontext *ctx );
+
+extern void radeonVtxfmtUnbindContext( GLcontext *ctx );
+
+extern void radeonVtxfmtInit( GLcontext *ctx );
+
+extern void radeonTclFallback( GLcontext *ctx, GLuint bit, GLboolean mode );
+
+extern void radeonVtxfmtInvalidate( GLcontext *ctx );
+
+extern void radeonSubsetVtxEnableTCL( radeonContextPtr rmesa, GLboolean flag );
+
+extern void radeonUpdateTextureState( GLcontext *ctx );
+
+extern void radeonInitTextureFuncs( GLcontext *ctx );
+
+extern void radeonAgeTextures( radeonContextPtr rmesa, int heap );
+
+extern void radeonDestroyTexObj( radeonContextPtr rmesa, radeonTexObjPtr t );
+
+#endif
diff --git a/src/mesa/drivers/dri/radeon/radeon_subset_bitmap.c b/src/mesa/drivers/dri/radeon/radeon_subset_bitmap.c
new file mode 100644
index 0000000000..cb4a514221
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_subset_bitmap.c
@@ -0,0 +1,197 @@
+/**
+ * \file radeon_subset_bitmap.c
+ * \brief Bitmap drawing.
+ *
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+/*
+ * Copyright 2003 ATI Technologies Inc., Ontario, Canada, and
+ * Tungsten Graphics Inc., Cedar Park, Texas.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * 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, TUNGSTEN GRAPHICS 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.
+ *
+ */
+
+/* $XFree86$ */
+
+#include "glheader.h"
+#include "mtypes.h"
+#include "colormac.h"
+#include "context.h"
+#include "enums.h"
+#include "imports.h"
+#include "image.h"
+/*#include "mmath.h"*/
+#include "macros.h"
+#include "state.h"
+
+#include "radeon_context.h"
+#include "radeon_ioctl.h"
+#include "radeon_state.h"
+#include "radeon_subset.h"
+
+/**
+ * \brief Cope with depth operations by drawing individual pixels as points
+ *
+ * \param xorig x coordinate of the bitmap corner.
+ * \param yorig y coordinate of the bitmap corner.
+ * \param xmove increment to the final x coordinate.
+ * \param ymove increment to the final y coordinate.
+ * \param width bitmap width.
+ * \param height bitmap height.
+ * \param bitmap bitmap pointer.
+ *
+ * Clips the bitmap coordinates and adjusts for windows coordinates. Draws the
+ * bitmap with glPoints(), turning off TCL and hardware viewport transformation
+ * to emit raw pixel coordinates. Finally fires any outstanding vertices and
+ * restores TCL, viewport, texture and color states.
+ */
+void
+radeonPointsBitmap( GLsizei width, GLsizei height,
+ GLfloat xorig, GLfloat yorig,
+ GLfloat xmove, GLfloat ymove,
+ const GLubyte *bitmap )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLsizei bmwidth = width, bmheight = height;
+ GLint px, py;
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLfloat saved_color[4], saved_tex0[2];
+ GLint row, col;
+ GLuint orig_se_cntl;
+ GLuint w, h;
+ const struct gl_pixelstore_attrib *unpack = &ctx->Unpack;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (width < 0 || height < 0) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glBitmap(width or height < 0)" );
+ return;
+ }
+
+ if (!ctx->Current.RasterPosValid)
+ return;
+
+ if (ctx->NewState)
+ _mesa_update_state(ctx);
+
+
+ if (ctx->_RotateMode) {
+ width = bmheight; height = bmwidth;
+
+ px = IFLOOR(ctx->Current.RasterPos[0] + yorig);
+ py = IFLOOR(ctx->Current.RasterPos[1] + xorig);
+
+ ctx->Current.RasterPos[0] += ymove;
+ ctx->Current.RasterPos[1] += xmove;
+ }
+ else {
+ px = IFLOOR(ctx->Current.RasterPos[0] - xorig);
+ py = IFLOOR(ctx->Current.RasterPos[1] - yorig);
+
+ ctx->Current.RasterPos[0] += xmove;
+ ctx->Current.RasterPos[1] += ymove;
+ }
+
+
+
+ /* Turn off tcl and the hw viewport transformation so that we can
+ * emit raw pixel coordinates:
+ */
+ radeonSubsetVtxEnableTCL( rmesa, GL_FALSE );
+ RADEON_STATECHANGE( rmesa, set );
+ orig_se_cntl = rmesa->hw.set.cmd[SET_SE_CNTL];
+ rmesa->hw.set.cmd[SET_SE_CNTL] &= ~(RADEON_VPORT_XY_XFORM_ENABLE |
+ RADEON_VPORT_Z_XFORM_ENABLE);
+
+
+ /* Adjust for window coordinates, flip y values:
+ */
+ h = rmesa->dri.drawable->h + rmesa->dri.drawable->y - 1;
+ w = rmesa->dri.drawable->w;
+ px += rmesa->dri.drawable->x;
+
+ /* Save current color, texcoord to restore later:
+ */
+ COPY_4V( saved_color, ctx->Current.Attrib[VERT_ATTRIB_COLOR0] );
+ COPY_2V( saved_tex0, ctx->Current.Attrib[VERT_ATTRIB_TEX0] );
+
+ /* Just use the GL entrypoints to talk to radeon_subset_vtx.c:
+ */
+ glBegin( GL_POINTS );
+ glColor4fv( ctx->Current.RasterColor );
+ glTexCoord2fv( ctx->Current.RasterTexCoords[0] );
+
+
+ if (ctx->_RotateMode) {
+ for (col=0; col<width; col++) {
+ const GLubyte *src = (const GLubyte *)
+ _mesa_image_address( unpack, bitmap, height, width,
+ GL_COLOR_INDEX, GL_BITMAP, 0, col, 0 );
+
+ /* Msb first */
+ GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
+ for (row=0; row<height; row++) {
+ if (*src & mask) {
+ glVertex2f( px-col, h - (py + row) );
+ }
+ src += mask & 1;
+ mask = ((mask << 7) & 0xff) | (mask >> 1);
+ }
+ /* get ready for next row */
+ if (mask != 128)
+ src++;
+ }
+ }
+ else {
+ for (row=0; row<height; row++) {
+ const GLubyte *src = (const GLubyte *)
+ _mesa_image_address( unpack, bitmap, width, height,
+ GL_COLOR_INDEX, GL_BITMAP, 0, row, 0 );
+
+ /* Msb first */
+ GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
+ for (col=0; col<width; col++) {
+ if (*src & mask) {
+ glVertex2f( px+col, h - (py + row) );
+ }
+ src += mask & 1;
+ mask = ((mask << 7) & 0xff) | (mask >> 1);
+ }
+ /* get ready for next row */
+ if (mask != 128)
+ src++;
+ }
+ }
+
+ glEnd();
+ glColor4fv( saved_color );
+ glTexCoord2fv( saved_tex0 );
+
+ /* Fire outstanding vertices, restore state
+ */
+ RADEON_STATECHANGE( rmesa, set );
+ rmesa->hw.set.cmd[SET_SE_CNTL] = orig_se_cntl;
+ radeonSubsetVtxEnableTCL( rmesa, GL_TRUE );
+}
+
diff --git a/src/mesa/drivers/dri/radeon/radeon_subset_readpix.c b/src/mesa/drivers/dri/radeon/radeon_subset_readpix.c
new file mode 100644
index 0000000000..f72d3b8472
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_subset_readpix.c
@@ -0,0 +1,246 @@
+/**
+ * \file radeon_subset_readpix.c
+ * \brief Pixel reading.
+ *
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ * \author Brian Paul <brian@tungstengraphics.com>
+ */
+
+/*
+ * Copyright 2003 ATI Technologies Inc., Ontario, Canada, and
+ * Tungsten Graphics Inc., Cedar Park, Texas.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * 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, TUNGSTEN GRAPHICS 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.
+ */
+
+/* $XFree86$ */
+
+#include "glheader.h"
+#include "mtypes.h"
+#include "colormac.h"
+#include "context.h"
+#include "enums.h"
+#include "imports.h"
+/*#include "mmath.h" */
+#include "macros.h"
+#include "state.h"
+
+#include "radeon_context.h"
+#include "radeon_ioctl.h"
+#include "radeon_state.h"
+#include "radeon_subset.h"
+
+/**
+ * \brief Read pixel in RGBA format on a Radeon 16bpp frame buffer.
+ *
+ * \param rgba destination pointer.
+ * \param ptr pointer to the pixel in the frame buffer.
+ */
+#define READ_RGBA_16( rgba, ptr ) \
+do { \
+ GLushort p = *(GLushort *)ptr; \
+ rgba[0] = ((p >> 8) & 0xf8) * 255 / 0xf8; \
+ rgba[1] = ((p >> 3) & 0xfc) * 255 / 0xfc; \
+ rgba[2] = ((p << 3) & 0xf8) * 255 / 0xf8; \
+ rgba[3] = 0xff; \
+} while (0)
+
+/**
+ * \brief Read pixel in RGBA format on a Radeon 32bpp frame buffer.
+ *
+ * \param rgba destination pointer.
+ * \param ptr pointer to the pixel in the frame buffer.
+ */
+#define READ_RGBA_32( rgba, ptr ) \
+do { \
+ GLuint p = *(GLuint *)ptr; \
+ rgba[0] = (p >> 16) & 0xff; \
+ rgba[1] = (p >> 8) & 0xff; \
+ rgba[2] = (p >> 0) & 0xff; \
+ rgba[3] = (p >> 24) & 0xff; \
+} while (0)
+
+/**
+ * \brief Read a span in RGBA format.
+ *
+ * \param ctx GL context.
+ * \param n number of pixels in the span.
+ * \param x x position of the span start.
+ * \param y y position of the span.
+ * \param rgba destination buffer.
+ *
+ * Calculates the pointer to the span start in the frame buffer and uses either
+ * #READ_RGBA_16 or #READ_RGBA_32 macros to copy the values.
+ */
+static void ReadRGBASpan( const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ GLubyte rgba[][4])
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ radeonScreenPtr radeonScreen = rmesa->radeonScreen;
+ __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
+ GLuint cpp = radeonScreen->cpp;
+ GLuint pitch = radeonScreen->frontPitch * cpp;
+ GLint i;
+
+ if (ctx->_RotateMode) {
+ char *ptr = (char *)(rmesa->dri.screen->pFB +
+ rmesa->state.pixel.readOffset +
+ ((dPriv->x + (dPriv->w - y - 1)) * cpp) +
+ ((dPriv->y + (dPriv->h - x - 1)) * pitch));
+
+ if (cpp == 4)
+ for (i = 0; i < n; i++, ptr -= pitch)
+ READ_RGBA_32( rgba[i], ptr );
+ else
+ for (i = 0; i < n; i++, ptr -= pitch)
+ READ_RGBA_16( rgba[i], ptr );
+ }
+ else {
+ char *ptr = (char *)(rmesa->dri.screen->pFB +
+ rmesa->state.pixel.readOffset +
+ ((dPriv->x + x) * cpp) +
+ ((dPriv->y + (dPriv->h - y - 1)) * pitch));
+
+ if (cpp == 4)
+ for (i = 0; i < n; i++, ptr += cpp)
+ READ_RGBA_32( rgba[i], ptr );
+ else
+ for (i = 0; i < n; i++, ptr += cpp)
+ READ_RGBA_16( rgba[i], ptr );
+ }
+}
+
+
+/**
+ * \brief Optimized glReadPixels().
+ *
+ * To be used with particular pixel formats GL_UNSIGNED_BYTE and GL_RGBA, when pixel
+ * scaling, biasing and mapping are disabled.
+ *
+ * \param x x start position of the reading rectangle.
+ * \param y y start position of the reading rectangle.
+ * \param width width of the reading rectangle.
+ * \param height height of the reading rectangle.
+ * \param format pixel format. Must be GL_RGBA.
+ * \param type pixel type. Must be GL_UNSIGNED_BYTE.
+ * \param pixels pixel data.
+ *
+ * After asserting the above conditions, compensates for clipping and calls
+ * ReadRGBASpan() to read each row.
+ */
+void radeonReadPixels( GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ GLvoid *pixels )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint srcX = x;
+ GLint srcY = y;
+ GLint readWidth = width; /* actual width read */
+ GLint readHeight = height; /* actual height read */
+ const struct gl_pixelstore_attrib *packing = &ctx->Pack;
+ GLint skipRows = packing->SkipRows;
+ GLint skipPixels = packing->SkipPixels;
+ GLint rowLength;
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ {
+ GLint tmp, tmps;
+ tmp = x; x = y; y = tmp;
+ tmps = width; width = height; height = tmps;
+ }
+
+ if (width < 0 || height < 0) {
+ _mesa_error( ctx, GL_INVALID_VALUE,
+ "glReadPixels(width=%d height=%d)", width, height );
+ return;
+ }
+
+ if (!pixels) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glReadPixels(pixels)" );
+ return;
+ }
+
+ if (ctx->NewState)
+ _mesa_update_state(ctx);
+
+
+ /* can't do scale, bias, mapping, etc */
+ assert(!ctx->_ImageTransferState);
+
+ /* can't do fancy pixel packing */
+ assert (packing->Alignment == 1 &&
+ !packing->SwapBytes &&
+ !packing->LsbFirst);
+
+
+ if (packing->RowLength > 0)
+ rowLength = packing->RowLength;
+ else
+ rowLength = width;
+
+ /* horizontal clipping */
+ if (srcX < 0) {
+ skipPixels -= srcX;
+ readWidth += srcX;
+ srcX = 0;
+ }
+ if (srcX + readWidth > (GLint) ctx->ReadBuffer->Width)
+ readWidth -= (srcX + readWidth - (GLint) ctx->ReadBuffer->Width);
+ if (readWidth <= 0)
+ return;
+
+ /* vertical clipping */
+ if (srcY < 0) {
+ skipRows -= srcY;
+ readHeight += srcY;
+ srcY = 0;
+ }
+ if (srcY + readHeight > (GLint) ctx->ReadBuffer->Height)
+ readHeight -= (srcY + readHeight - (GLint) ctx->ReadBuffer->Height);
+ if (readHeight <= 0)
+ return;
+
+ /*
+ * Ready to read!
+ * The window region at (destX, destY) of size (readWidth, readHeight)
+ * will be read back.
+ * We'll write pixel data to buffer pointed to by "pixels" but we'll
+ * skip "skipRows" rows and skip "skipPixels" pixels/row.
+ */
+ if (format == GL_RGBA && type == GL_UNSIGNED_BYTE) {
+ GLchan *dest = (GLchan *) pixels
+ + (skipRows * rowLength + skipPixels) * 4;
+ GLint row;
+
+ for (row=0; row<readHeight; row++) {
+ ReadRGBASpan(ctx, readWidth, srcX, srcY, (GLchan (*)[4]) dest);
+ dest += rowLength * 4;
+ srcY++;
+ }
+ }
+ else {
+ /* can't do this format/type combination */
+ assert(0);
+ }
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_subset_select.c b/src/mesa/drivers/dri/radeon/radeon_subset_select.c
new file mode 100644
index 0000000000..bd5003ffe5
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_subset_select.c
@@ -0,0 +1,998 @@
+/**
+ * \file radeon_subset_select.c
+ * \brief Selection.
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 4.1
+ *
+ * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/* $Id: radeon_subset_select.c,v 1.2 2003/08/22 20:11:45 brianp Exp $ */
+
+
+#include "glheader.h"
+#include "imports.h"
+#include "context.h"
+/*#include "mmath.h"*/
+#include "mtypes.h"
+#include "enums.h"
+#include "glapi.h"
+#include "feedback.h"
+
+#include "radeon_context.h"
+#include "radeon_subset.h"
+
+/**
+ * \brief Vertex.
+ */
+typedef struct {
+ struct { GLfloat x, y, z, w; } pos; /**< \brief position */
+ struct { GLfloat x, y, z, w; } eyePos; /**< \brief position, eye coordinates */
+ struct { GLfloat x, y, z, w; } clipPos; /**< \brief clipped coordinates */
+ struct { GLfloat x, y, z, w; } winPos; /**< \brief position, windows coordinates */
+ struct { GLfloat s, t; } texCoord; /**< \brief texture coordinates */
+ struct { GLfloat r, g, b, a; } color; /**< \brief color */
+} vertex;
+
+
+/**
+ * \brief Vertex buffer.
+ */
+static struct select_vb_t {
+ GLuint vCount; /**< \brief vertex count */
+ vertex vBuffer[4]; /**< \brief vertex buffer */
+ GLboolean lineReset;
+ GLboolean partialLineLoop; /**< \brief whether we are in a middle of a line loop */
+} vb;
+
+
+
+
+/**********************************************************************/
+/** \name Vertex Transformation and Clipping */
+/**********************************************************************/
+/*@{*/
+
+/**
+ * \brief Transform a point (column vector) by a matrix: Q = M * P.
+ *
+ * \param Q destination point.
+ * \param P source point.
+ * \param M transformation matrix.
+ */
+#define TRANSFORM_POINT( Q, M, P ) \
+ Q.x = M[0] * P.x + M[4] * P.y + M[8] * P.z + M[12] * P.w; \
+ Q.y = M[1] * P.x + M[5] * P.y + M[9] * P.z + M[13] * P.w; \
+ Q.z = M[2] * P.x + M[6] * P.y + M[10] * P.z + M[14] * P.w; \
+ Q.w = M[3] * P.x + M[7] * P.y + M[11] * P.z + M[15] * P.w;
+
+/**
+ * \brief Clip coord to window coord mapping.
+ *
+ * \param Q destination point.
+ * \param P source point.
+ * \param VP view port.
+ */
+#define MAP_POINT( Q, P, VP ) \
+ Q.x = (GLfloat) (((P.x / P.w) + 1.0) * VP.Width / 2.0 + VP.X); \
+ Q.y = (GLfloat) (((P.y / P.w) + 1.0) * VP.Height / 2.0 + VP.Y); \
+ Q.z = (GLfloat) (((P.z / P.w) + 1.0) * (VP.Far - VP.Near) / 2.0 + VP.Near);\
+ Q.w = (GLfloat) P.w;
+
+
+/**
+ * \brief Linear interpolation: (1 - T) * A + T * B.
+ *
+ * \param T interpolation factor.
+ * \param A first value.
+ * \param B second value.
+ * \result interpolated value.
+ */
+#define INTERPOLATE(T, A, B) ((A) + ((B) - (A)) * (T))
+
+
+
+/**
+ * \brief Interpolate vertex position, color, texcoords, etc.
+ *
+ * \param t interpolation factor.
+ * \param v0 first vertex.
+ * \param v1 second vertex.
+ * \param vOut output vertex.
+ *
+ * Uses the #INTERPOLATE macro for all the interpolation of all elements.
+ */
+static void
+interpolate_vertex(GLfloat t, const vertex *v0, const vertex *v1,
+ vertex *vOut)
+{
+ vOut->eyePos.x = INTERPOLATE(t, v0->eyePos.x, v1->eyePos.x);
+ vOut->eyePos.y = INTERPOLATE(t, v0->eyePos.y, v1->eyePos.y);
+ vOut->eyePos.z = INTERPOLATE(t, v0->eyePos.z, v1->eyePos.z);
+ vOut->eyePos.w = INTERPOLATE(t, v0->eyePos.w, v1->eyePos.w);
+
+ vOut->clipPos.x = INTERPOLATE(t, v0->clipPos.x, v1->clipPos.x);
+ vOut->clipPos.y = INTERPOLATE(t, v0->clipPos.y, v1->clipPos.y);
+ vOut->clipPos.z = INTERPOLATE(t, v0->clipPos.z, v1->clipPos.z);
+ vOut->clipPos.w = INTERPOLATE(t, v0->clipPos.w, v1->clipPos.w);
+
+ vOut->color.r = INTERPOLATE(t, v0->color.r, v1->color.r);
+ vOut->color.g = INTERPOLATE(t, v0->color.g, v1->color.g);
+ vOut->color.b = INTERPOLATE(t, v0->color.b, v1->color.b);
+ vOut->color.a = INTERPOLATE(t, v0->color.a, v1->color.a);
+
+ vOut->texCoord.s = INTERPOLATE(t, v0->texCoord.s, v1->texCoord.s);
+ vOut->texCoord.t = INTERPOLATE(t, v0->texCoord.t, v1->texCoord.t);
+}
+
+
+
+
+/*
+ * Clip bit codes
+ */
+#define CLIP_LEFT 1
+#define CLIP_RIGHT 2
+#define CLIP_BOTTOM 4
+#define CLIP_TOP 8
+#define CLIP_NEAR 16
+#define CLIP_FAR 32
+
+
+/**
+ * \brief Apply view volume clip testing to a point.
+ *
+ * \param v point to test.
+ * \return zero if visible, or the clip code mask, i.e., binary OR of a
+ * combination of the #CLIP_LEFT, #CLIP_RIGHT, #CLIP_BOTTOM, #CLIP_TOP, #CLIP_NEAR,
+ * #CLIP_FAR clip bit codes.
+ */
+static GLuint
+clip_point(const vertex *v)
+{
+ GLuint mask = 0;
+ if (v->clipPos.x > v->clipPos.w) mask |= CLIP_RIGHT;
+ if (v->clipPos.x < -v->clipPos.w) mask |= CLIP_LEFT;
+ if (v->clipPos.y > v->clipPos.w) mask |= CLIP_TOP;
+ if (v->clipPos.y < -v->clipPos.w) mask |= CLIP_BOTTOM;
+ if (v->clipPos.z > v->clipPos.w) mask |= CLIP_FAR;
+ if (v->clipPos.z < -v->clipPos.w) mask |= CLIP_NEAR;
+ return mask;
+}
+
+
+/**
+ * \def GENERAL_CLIP
+ * \brief Clipping utility macro.
+ *
+ * We use 6 instances of this code in each of the clip_line() and
+ * clip_polygon() to clip against the 6 planes. For each plane, we define the
+ * #OUTSIDE and #COMPUTE_INTERSECTION macros appropriately.
+ */
+
+
+/**
+ * \brief Apply clipping to a line segment.
+ *
+ * \param v0in input start vertex
+ * \param v1in input end vertesx
+ * \param v0new output start vertex
+ * \param v1new output end vertex
+ *
+ * \return GL_TRUE if the line segment is visible, or GL_FALSE if it is totally
+ * clipped.
+ *
+ * \sa #GENERAL_CLIP.
+ */
+static GLboolean
+clip_line(const vertex *v0in, const vertex *v1in,
+ vertex *v0new, vertex *v1new)
+{
+ vertex v0, v1, vNew;
+ GLfloat dx, dy, dz, dw, t;
+ GLuint code0, code1;
+
+ code0 = clip_point(v0in);
+ code1 = clip_point(v1in);
+ if (code0 & code1)
+ return GL_FALSE; /* totally clipped */
+
+ *v0new = *v0in;
+ *v1new = *v1in;
+ if (code0 == 0 && code1 == 0)
+ return GL_TRUE; /* no clipping needed */
+
+ v0 = *v0in;
+ v1 = *v1in;
+
+
+#define GENERAL_CLIP \
+ if (OUTSIDE(v0)) { \
+ if (OUTSIDE(v1)) { \
+ /* both verts are outside ==> return 0 */ \
+ return 0; \
+ } \
+ else { \
+ /* v0 is outside, v1 is inside ==> clip */ \
+ COMPUTE_INTERSECTION( v1, v0, vNew ) \
+ interpolate_vertex(t, &v1, &v0, &vNew); \
+ v0 = vNew; \
+ } \
+ } \
+ else { \
+ if (OUTSIDE(v1)) { \
+ /* v0 is inside, v1 is outside ==> clip */ \
+ COMPUTE_INTERSECTION( v0, v1, vNew ) \
+ interpolate_vertex(t, &v0, &v1, &vNew); \
+ v1 = vNew; \
+ } \
+ /* else both verts are inside ==> do nothing */ \
+ }
+
+ /* Clip against +X side */
+#define OUTSIDE(V) (V.clipPos.x > V.clipPos.w)
+#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
+ dx = OUT.clipPos.x - IN.clipPos.x; \
+ dw = OUT.clipPos.w - IN.clipPos.w; \
+ t = (IN.clipPos.x - IN.clipPos.w) / (dw-dx);
+ GENERAL_CLIP
+#undef OUTSIDE
+#undef COMPUTE_INTERSECTION
+
+ /* Clip against -X side */
+#define OUTSIDE(V) (V.clipPos.x < -(V.clipPos.w))
+#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
+ dx = OUT.clipPos.x - IN.clipPos.x; \
+ dw = OUT.clipPos.w - IN.clipPos.w; \
+ t = -(IN.clipPos.x + IN.clipPos.w) / (dw+dx);
+ GENERAL_CLIP
+#undef OUTSIDE
+#undef COMPUTE_INTERSECTION
+
+ /* Clip against +Y side */
+#define OUTSIDE(V) (V.clipPos.y > V.clipPos.w)
+#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
+ dy = OUT.clipPos.y - IN.clipPos.y; \
+ dw = OUT.clipPos.w - IN.clipPos.w; \
+ t = (IN.clipPos.y - IN.clipPos.w) / (dw-dy);
+ GENERAL_CLIP
+#undef OUTSIDE
+#undef COMPUTE_INTERSECTION
+
+ /* Clip against -Y side */
+#define OUTSIDE(V) (V.clipPos.y < -(V.clipPos.w))
+#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
+ dy = OUT.clipPos.y - IN.clipPos.y; \
+ dw = OUT.clipPos.w - IN.clipPos.w; \
+ t = -(IN.clipPos.y + IN.clipPos.w) / (dw+dy);
+ GENERAL_CLIP
+#undef OUTSIDE
+#undef COMPUTE_INTERSECTION
+
+ /* Clip against +Z side */
+#define OUTSIDE(V) (V.clipPos.z > V.clipPos.w)
+#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
+ dz = OUT.clipPos.z - IN.clipPos.z; \
+ dw = OUT.clipPos.w - IN.clipPos.w; \
+ t = (IN.clipPos.z - IN.clipPos.w) / (dw-dz);
+ GENERAL_CLIP
+#undef OUTSIDE
+#undef COMPUTE_INTERSECTION
+
+ /* Clip against -Z side */
+#define OUTSIDE(V) (V.clipPos.z < -(V.clipPos.w))
+#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
+ dz = OUT.clipPos.z - IN.clipPos.z; \
+ dw = OUT.clipPos.w - IN.clipPos.w; \
+ t = -(IN.clipPos.z + IN.clipPos.w) / (dw+dz);
+ GENERAL_CLIP
+#undef OUTSIDE
+#undef COMPUTE_INTERSECTION
+
+#undef GENERAL_CLIP
+
+ *v0new = v0;
+ *v1new = v1;
+ return GL_TRUE;
+}
+
+
+
+/**
+ * \brief Apply clipping to a polygon.
+ *
+ * \param vIn array of input vertices.
+ * \param inCount number of input vertices
+ * \param vOut array of output vertices.
+ *
+ * \return number of vertices in \p vOut.
+ *
+ * \sa #GENERAL_CLIP.
+ */
+static GLuint
+clip_polygon(const vertex *vIn, unsigned int inCount, vertex *vOut)
+{
+ vertex inlist[20], outlist[20];
+ GLfloat dx, dy, dz, dw, t;
+ GLuint incount, outcount, previ, curri, result;
+ const vertex *currVert, *prevVert;
+ vertex *newVert;
+
+
+#define GENERAL_CLIP(INCOUNT, INLIST, OUTCOUNT, OUTLIST) \
+ if (INCOUNT < 3) \
+ return GL_FALSE; \
+ previ = INCOUNT - 1; /* let previous = last vertex */ \
+ prevVert = INLIST + previ; \
+ OUTCOUNT = 0; \
+ for (curri = 0; curri < INCOUNT; curri++) { \
+ currVert = INLIST + curri; \
+ if (INSIDE(currVert)) { \
+ if (INSIDE(prevVert)) { \
+ /* both verts are inside ==> copy current to outlist */ \
+ OUTLIST[OUTCOUNT] = *currVert; \
+ OUTCOUNT++; \
+ } \
+ else { \
+ newVert = OUTLIST + OUTCOUNT; \
+ /* current is inside and previous is outside ==> clip */ \
+ COMPUTE_INTERSECTION( currVert, prevVert, newVert ) \
+ OUTCOUNT++; \
+ /* Output current */ \
+ OUTLIST[OUTCOUNT] = *currVert; \
+ OUTCOUNT++; \
+ } \
+ } \
+ else { \
+ if (INSIDE(prevVert)) { \
+ newVert = OUTLIST + OUTCOUNT; \
+ /* current is outside and previous is inside ==> clip */ \
+ COMPUTE_INTERSECTION( prevVert, currVert, newVert ); \
+ OUTLIST[OUTCOUNT] = *newVert; \
+ OUTCOUNT++; \
+ } \
+ /* else both verts are outside ==> do nothing */ \
+ } \
+ /* let previous = current */ \
+ previ = curri; \
+ prevVert = currVert; \
+ }
+
+/*
+ * Clip against +X
+ */
+#define INSIDE(V) (V->clipPos.x <= V->clipPos.w)
+#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
+ dx = OUT->clipPos.x - IN->clipPos.x; \
+ dw = OUT->clipPos.w - IN->clipPos.w; \
+ t = (IN->clipPos.x - IN->clipPos.w) / (dw - dx); \
+ interpolate_vertex(t, IN, OUT, NEW );
+
+ GENERAL_CLIP(inCount, vIn, outcount, outlist)
+
+#undef INSIDE
+#undef COMPUTE_INTERSECTION
+
+/*
+ * Clip against -X
+ */
+#define INSIDE(V) (V->clipPos.x >= -V->clipPos.w)
+#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
+ dx = OUT->clipPos.x - IN->clipPos.x; \
+ dw = OUT->clipPos.w - IN->clipPos.w; \
+ t = -(IN->clipPos.x + IN->clipPos.w) / (dw + dx); \
+ interpolate_vertex(t, IN, OUT, NEW );
+
+ GENERAL_CLIP(outcount, outlist, incount, inlist)
+
+#undef INSIDE
+#undef COMPUTE_INTERSECTION
+
+/*
+ * Clip against +Y
+ */
+#define INSIDE(V) (V->clipPos.y <= V->clipPos.w)
+#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
+ dy = OUT->clipPos.y - IN->clipPos.y; \
+ dw = OUT->clipPos.w - IN->clipPos.w; \
+ t = (IN->clipPos.y - IN->clipPos.w) / (dw - dy); \
+ interpolate_vertex(t, IN, OUT, NEW );
+
+ GENERAL_CLIP(incount, inlist, outcount, outlist)
+
+#undef INSIDE
+#undef COMPUTE_INTERSECTION
+
+/*
+ * Clip against -Y
+ */
+#define INSIDE(V) (V->clipPos.y >= -V->clipPos.w)
+#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
+ dy = OUT->clipPos.y - IN->clipPos.y; \
+ dw = OUT->clipPos.w - IN->clipPos.w; \
+ t = -(IN->clipPos.y + IN->clipPos.w) / (dw + dy); \
+ interpolate_vertex(t, IN, OUT, NEW );
+
+ GENERAL_CLIP(outcount, outlist, incount, inlist)
+
+#undef INSIDE
+#undef COMPUTE_INTERSECTION
+
+/*
+ * Clip against +Z
+ */
+#define INSIDE(V) (V->clipPos.z <= V->clipPos.w)
+#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
+ dz = OUT->clipPos.z - IN->clipPos.z; \
+ dw = OUT->clipPos.w - IN->clipPos.w; \
+ t = (IN->clipPos.z - IN->clipPos.w) / (dw - dz); \
+ interpolate_vertex(t, IN, OUT, NEW );
+
+ GENERAL_CLIP(incount, inlist, outcount, outlist)
+
+#undef INSIDE
+#undef COMPUTE_INTERSECTION
+
+/*
+ * Clip against -Z
+ */
+#define INSIDE(V) (V->clipPos.z >= -V->clipPos.w)
+#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
+ dz = OUT->clipPos.z - IN->clipPos.z; \
+ dw = OUT->clipPos.w - IN->clipPos.w; \
+ t = -(IN->clipPos.z + IN->clipPos.w) / (dw + dz); \
+ interpolate_vertex(t, IN, OUT, NEW );
+
+ GENERAL_CLIP(outcount, outlist, result, vOut)
+
+#undef INSIDE
+#undef COMPUTE_INTERSECTION
+
+#undef GENERAL_CLIP
+
+ return result;
+}
+
+/*@}*/
+
+
+
+/**********************************************************************/
+/** \name Selection */
+/**********************************************************************/
+/*@{*/
+
+/**
+ * \brief Select point.
+ *
+ * \param v vertex.
+ *
+ * If the clipped point is visible then maps the vertex into window coordinates
+ * and calls _mesa_update_hitflag().
+ */
+static void
+select_point(const vertex *v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (clip_point(v) == 0)
+ {
+ vertex c = *v;
+ MAP_POINT(c.winPos, c.clipPos, ctx->Viewport);
+ _mesa_update_hitflag(ctx, c.winPos.z);
+ }
+}
+
+/**
+ * \brief Select line.
+ *
+ * \param v0 first vertex.
+ * \param v1 second vertex.
+ *
+ * If the clipped line is visible then maps the vertices into window coordinates
+ * and calls _mesa_update_hitflag().
+ */
+static void
+select_line(const vertex *v0, const vertex *v1)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ vertex c0, c1;
+ if (clip_line(v0, v1, &c0, &c1))
+ {
+ MAP_POINT(c0.winPos, c0.clipPos, ctx->Viewport);
+ MAP_POINT(c1.winPos, c1.clipPos, ctx->Viewport);
+ _mesa_update_hitflag(ctx, c0.winPos.z);
+ _mesa_update_hitflag(ctx, c1.winPos.z);
+ }
+}
+
+/**
+ * \brief Select line.
+ *
+ * \param v0 first vertex.
+ * \param v1 second vertex.
+ * \param v2 third vertex.
+ *
+ * If the clipped polygon is visible then maps the vertices into window
+ * coordinates and calls _mesa_update_hitflag().
+ */
+static void
+select_triangle(const vertex *v0,
+ const vertex *v1,
+ const vertex *v2)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ vertex vlist[3], vclipped[8];
+ GLuint i, n;
+
+ vlist[0] = *v0;
+ vlist[1] = *v1;
+ vlist[2] = *v2;
+ n = clip_polygon(vlist, 3, vclipped);
+ for (i = 0; i < n; i++) {
+ MAP_POINT(vclipped[i].winPos, vclipped[i].clipPos, ctx->Viewport);
+ _mesa_update_hitflag(ctx, vclipped[i].winPos.z);
+ }
+}
+
+/**
+ * \brief Set current vertex coordinates.
+ *
+ * \param x x vertex coordinate.
+ * \param y y vertex coordinate.
+ * \param z z vertex coordinate.
+ * \param w homogeneous coordinate.
+ *
+ * Stores the vertex and current attributes in ::vb, transforms it into eye space and then clip space.
+ *
+ * If a sufficient number of vertices is stored calls one of select_point(),
+ * select_line() or select_triangle(), according to the current primitive.
+ */
+static void
+radeon_select_Vertex4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_polygon_attrib *p = &(ctx->Polygon);
+ vertex *v = vb.vBuffer + vb.vCount;
+
+ /* store the vertex */
+ v->pos.x = x;
+ v->pos.y = y;
+ v->pos.z = z;
+ v->pos.w = w;
+ v->color.r = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0];
+ v->color.g = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1];
+ v->color.b = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2];
+ v->color.a = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3];
+ v->texCoord.s = ctx->Current.Attrib[VERT_ATTRIB_TEX0][0];
+ v->texCoord.t = ctx->Current.Attrib[VERT_ATTRIB_TEX0][1];
+
+ /* transform to eye space, then clip space */
+ TRANSFORM_POINT(v->eyePos, ctx->ModelviewMatrixStack.Top->m, v->pos);
+ TRANSFORM_POINT(v->clipPos, ctx->ProjectionMatrixStack.Top->m, v->eyePos);
+
+ switch (ctx->Driver.CurrentExecPrimitive) {
+ case GL_POINTS:
+ assert(vb.vCount == 0);
+ select_point(v);
+ break;
+ case GL_LINES:
+ if (vb.vCount == 0)
+ {
+ vb.vCount = 1;
+ }
+ else
+ {
+ assert(vb.vCount == 1);
+ select_line(vb.vBuffer + 0, vb.vBuffer + 1);
+ vb.vCount = 0;
+ }
+ break;
+ case GL_LINE_STRIP:
+ if (vb.vCount == 0)
+ {
+ vb.vCount = 1;
+ }
+ else
+ {
+ assert(vb.vCount == 1);
+ select_line(vb.vBuffer + 0, vb.vBuffer + 1);
+ vb.vBuffer[0] = vb.vBuffer[1];
+ /* leave vb.vCount at 1 */
+ }
+ break;
+ case GL_LINE_LOOP:
+ if (vb.vCount == 0)
+ {
+ vb.vCount = 1;
+ vb.partialLineLoop = GL_FALSE;
+ }
+ else if (vb.vCount == 1)
+ {
+ select_line(vb.vBuffer + 0, vb.vBuffer + 1);
+ vb.partialLineLoop = GL_TRUE;
+ vb.vCount = 2;
+ }
+ else
+ {
+ assert(vb.vCount == 2);
+ vb.partialLineLoop = GL_FALSE;
+ select_line(vb.vBuffer + 1, vb.vBuffer + 2);
+ vb.vBuffer[1] = vb.vBuffer[2];
+ /* leave vb.vCount at 2 */
+ }
+ break;
+ case GL_TRIANGLES:
+ if (vb.vCount == 0 || vb.vCount == 1)
+ {
+ vb.vCount++;
+ }
+ else
+ {
+ assert(vb.vCount == 2);
+ select_triangle(vb.vBuffer + 0, vb.vBuffer + 1, vb.vBuffer + 2);
+ vb.vCount = 0;
+ }
+ break;
+ case GL_TRIANGLE_STRIP:
+ if (vb.vCount == 0 || vb.vCount == 1)
+ {
+ vb.vCount++;
+ }
+ else if (vb.vCount == 2)
+ {
+ select_triangle(vb.vBuffer + 0, vb.vBuffer + 1, vb.vBuffer + 2);
+ vb.vCount = 3;
+ }
+ else
+ {
+ assert(vb.vCount == 3);
+ select_triangle(vb.vBuffer + 1, vb.vBuffer + 3, vb.vBuffer + 2);
+ vb.vBuffer[0] = vb.vBuffer[2];
+ vb.vBuffer[1] = vb.vBuffer[3];
+ vb.vCount = 2;
+ }
+ break;
+ case GL_TRIANGLE_FAN:
+ if (vb.vCount == 0 || vb.vCount == 1)
+ {
+ vb.vCount++;
+ }
+ else
+ {
+ assert(vb.vCount == 2);
+ select_triangle(vb.vBuffer + 0, vb.vBuffer + 1, vb.vBuffer + 2);
+ vb.vBuffer[1] = vb.vBuffer[2];
+ /* leave vb.vCount = 2 */
+ }
+ break;
+ case GL_QUADS:
+ if (vb.vCount < 3)
+ {
+ vb.vCount++;
+ }
+ else
+ {
+ assert(vb.vCount == 3);
+ select_triangle(vb.vBuffer + 0, vb.vBuffer + 1, vb.vBuffer + 2);
+ select_triangle(vb.vBuffer + 0, vb.vBuffer + 2, vb.vBuffer + 3);
+ vb.vCount = 0;
+ }
+ break;
+ case GL_QUAD_STRIP:
+ if (vb.vCount < 3)
+ {
+ vb.vCount++;
+ }
+ else
+ {
+ assert(vb.vCount == 3);
+ select_triangle(vb.vBuffer + 0, vb.vBuffer + 1, vb.vBuffer + 2);
+ select_triangle(vb.vBuffer + 1, vb.vBuffer + 3, vb.vBuffer + 2);
+ vb.vBuffer[0] = vb.vBuffer[2];
+ vb.vBuffer[1] = vb.vBuffer[3];
+ vb.vCount = 2;
+ }
+ break;
+ case GL_POLYGON:
+ switch (p->FrontMode) {
+ case GL_POINT:
+ assert(vb.vCount == 0);
+ select_point(v);
+ break;
+ case GL_LINE:
+ if (vb.vCount == 0)
+ {
+ vb.vCount = 1;
+ vb.partialLineLoop = GL_FALSE;
+ }
+ else if (vb.vCount == 1)
+ {
+ select_line(vb.vBuffer + 0, vb.vBuffer + 1);
+ vb.partialLineLoop = GL_TRUE;
+ vb.vCount = 2;
+ }
+ else
+ {
+ assert(vb.vCount == 2);
+ vb.partialLineLoop = GL_FALSE;
+ select_line(vb.vBuffer + 1, vb.vBuffer + 2);
+ vb.vBuffer[1] = vb.vBuffer[2];
+ /* leave vb.vCount at 2 */
+ }
+ break;
+ case GL_FILL:
+ /* draw as a tri-fan */
+ if (vb.vCount == 0 || vb.vCount == 1)
+ {
+ vb.vCount++;
+ }
+ else
+ {
+ assert(vb.vCount == 2);
+ select_triangle(vb.vBuffer + 0, vb.vBuffer + 1, vb.vBuffer + 2);
+ vb.vBuffer[1] = vb.vBuffer[2];
+ /* leave vb.vCount = 2 */
+ }
+ break;
+ default:
+ ; /* impossible */
+ }
+ break;
+ default:
+ ; /* outside begin/end -- no action required */
+ }
+}
+
+/**
+ * \brief Calls radeon_select_Vertex4f().
+ */
+static void radeon_select_Vertex2f(GLfloat x, GLfloat y)
+{
+ radeon_select_Vertex4f(x, y, 0.0, 1.0);
+}
+
+/**
+ * \brief Calls radeon_select_Vertex4f().
+ */
+static void radeon_select_Vertex2fv(const GLfloat * v)
+{
+ radeon_select_Vertex4f(v[0], v[1], 0.0, 1.0);
+}
+
+/**
+ * \brief Calls radeon_select_Vertex4f().
+ */
+static void radeon_select_Vertex3f(GLfloat x, GLfloat y, GLfloat z)
+{
+ radeon_select_Vertex4f(x, y, z, 1.0);
+}
+
+/**
+ * \brief Calls radeon_select_Vertex4f().
+ */
+static void radeon_select_Vertex3fv(const GLfloat * v)
+{
+ radeon_select_Vertex4f(v[0], v[1], v[2], 1.0);
+}
+
+
+/**
+ * \brief Set current vertex color.
+ *
+ * \param r red color component.
+ * \param g gree color component.
+ * \param b blue color component.
+ * \param a alpha color component.
+ *
+ * Updates the GL context's current vertex color.
+ */
+static void radeon_select_Color4f( GLfloat r, GLfloat g,
+ GLfloat b, GLfloat a )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
+ dest[0] = r;
+ dest[1] = g;
+ dest[2] = b;
+ dest[3] = a;
+}
+
+/**
+ * \brief Calls radeon_select_Color4f().
+ */
+static void radeon_select_Color4fv( const GLfloat *v )
+{
+ radeon_select_Color4f( v[0], v[1], v[2], v[3] );
+}
+
+/**
+ * \brief Calls radeon_select_Color4f().
+ */
+static void radeon_select_Color3f( GLfloat r, GLfloat g, GLfloat b )
+{
+ radeon_select_Color4f( r, g, b, 1.0 );
+}
+
+/**
+ * \brief Calls radeon_select_Color4f().
+ */
+static void radeon_select_Color3fv( const GLfloat *v )
+{
+ radeon_select_Color4f( v[0], v[1], v[2], 1.0 );
+}
+
+/**
+ * \brief Set current vertex texture coordinates.
+ *
+ * \param s texture coordinate.
+ * \param t texture coordinate.
+ *
+ * Updates the GL context's current vertex texture coordinates.
+ */
+static __inline__ void radeon_select_TexCoord2f( GLfloat s, GLfloat t )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0];
+ dest[0] = s;
+ dest[1] = t;
+}
+
+/**
+ * \brief Calls radeon_select_TexCoord2f().
+ */
+static void radeon_select_TexCoord2fv( const GLfloat *v )
+{
+ radeon_select_TexCoord2f( v[0], v[1] );
+}
+
+
+/**
+ * \brief Process glBegin().
+ *
+ * \param mode primitive.
+ */
+static void radeon_select_Begin(GLenum mode)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (mode > GL_POLYGON) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glBegin" );
+ return;
+ }
+
+ if (ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) {
+ _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" );
+ return;
+ }
+
+ ctx->Driver.CurrentExecPrimitive = mode;
+
+ vb.vCount = 0;
+ vb.lineReset = GL_TRUE;
+ vb.partialLineLoop = GL_FALSE;
+}
+
+/**
+ * \brief Process glEnd().
+ */
+static void radeon_select_End(void)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if ( (ctx->Driver.CurrentExecPrimitive == GL_LINE_LOOP ||
+ (ctx->Driver.CurrentExecPrimitive == GL_POLYGON &&
+ ctx->Polygon.FrontMode == GL_LINE))
+ && vb.vCount == 2 )
+ {
+ /* draw the last line segment */
+ if (vb.partialLineLoop)
+ select_line(vb.vBuffer + 1, vb.vBuffer + 0);
+ else
+ select_line(vb.vBuffer + 2, vb.vBuffer + 0);
+ }
+
+ ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1;
+}
+
+
+/**
+ * \brief Flush vertices.
+ *
+ * \param ctx GL context.
+ * \param flags not used.
+ *
+ * Nothing much to do here, besides marking the vertices as flushed, as we
+ * don't buffer anything.
+ */
+static void radeonSelectFlushVertices( GLcontext *ctx, GLuint flags )
+{
+ ctx->Driver.NeedFlush = 0;
+}
+
+/**
+ * \brief Install the select callbacks.
+ *
+ * \param ctx GL context.
+ *
+ * Installs the glBegin()/glEnd() associated select callbacks into the glapi
+ * table.
+ */
+void radeon_select_Install( GLcontext *ctx )
+{
+ struct _glapi_table *exec = ctx->Exec;
+
+ exec->Color3f = radeon_select_Color3f;
+ exec->Color3fv = radeon_select_Color3fv;
+ exec->Color4f = radeon_select_Color4f;
+ exec->Color4fv = radeon_select_Color4fv;
+ exec->TexCoord2f = radeon_select_TexCoord2f;
+ exec->TexCoord2fv = radeon_select_TexCoord2fv;
+ exec->Vertex2f = radeon_select_Vertex2f;
+ exec->Vertex2fv = radeon_select_Vertex2fv;
+ exec->Vertex3f = radeon_select_Vertex3f;
+ exec->Vertex3fv = radeon_select_Vertex3fv;
+ exec->Begin = radeon_select_Begin;
+ exec->End = radeon_select_End;
+
+ ctx->Driver.FlushVertices = radeonSelectFlushVertices;
+}
+/*@}*/
+
+
+
+/**
+ * \brief Set rasterization mode.
+ *
+ * \param ctx GL context.
+ * \param mode rasterization mode. Supports GL_RENDER or
+ *
+ * If mode is GL_RENDER, calls either radeonVtxfmtInit() or
+ * radeon_noop_Install depending on whether the application has focus
+ * (i.e., a fullscreen-cliprect) or not. If mode is GL_SELECT, calls
+ * radeon_select_Install().
+ */
+static void radeonRenderMode( GLcontext *ctx, GLenum mode )
+{
+ switch (mode) {
+ case GL_RENDER:
+ radeonVtxfmtInit( ctx );
+ break;
+ case GL_SELECT:
+ radeon_select_Install( ctx );
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * \brief Setup the GL context driver callbacks.
+ *
+ * \param ctx GL context.
+ *
+ * \sa Called by radeonCreateContext().
+ */
+void radeonInitSelect( GLcontext *ctx )
+{
+ ctx->Driver.RenderMode = radeonRenderMode;
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_subset_tex.c b/src/mesa/drivers/dri/radeon/radeon_subset_tex.c
new file mode 100644
index 0000000000..e401779513
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_subset_tex.c
@@ -0,0 +1,1018 @@
+/**
+ * \file radeon_subset_tex.c
+ * \brief Texturing.
+ *
+ * \author Gareth Hughes <gareth@valinux.com>
+ * \author Brian Paul <brianp@valinux.com>
+ */
+
+/*
+ * 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.
+ */
+
+/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_tex.c,v 1.6 2002/09/16 18:05:20 eich Exp $ */
+
+#include "glheader.h"
+#include "imports.h"
+#include "colormac.h"
+#include "context.h"
+#include "enums.h"
+#include "image.h"
+#include "simple_list.h"
+#include "texformat.h"
+#include "texstore.h"
+
+#include "radeon_context.h"
+#include "radeon_state.h"
+#include "radeon_ioctl.h"
+#include "radeon_subset.h"
+
+#include <errno.h>
+#include <stdio.h>
+
+
+/**
+ * \brief Destroy hardware state associated with a texture.
+ *
+ * \param rmesa Radeon context.
+ * \param t Radeon texture object to be destroyed.
+ *
+ * Frees the memory associated with the texture and if the texture is bound to
+ * a texture unit cleans the associated hardware state.
+ */
+void radeonDestroyTexObj( radeonContextPtr rmesa, radeonTexObjPtr t )
+{
+ if ( t->memBlock ) {
+ mmFreeMem( t->memBlock );
+ t->memBlock = NULL;
+ }
+
+ if ( t->tObj )
+ t->tObj->DriverData = NULL;
+
+ if ( rmesa ) {
+ if ( t == rmesa->state.texture.unit[0].texobj ) {
+ rmesa->state.texture.unit[0].texobj = NULL;
+ remove_from_list( &rmesa->hw.tex[0] );
+ make_empty_list( &rmesa->hw.tex[0] );
+ }
+ }
+
+ remove_from_list( t );
+ FREE( t );
+}
+
+
+/**
+ * \brief Keep track of swapped out texture objects.
+ *
+ * \param rmesa Radeon context.
+ * \param t Radeon texture object.
+ *
+ * Frees the memory associated with the texture, marks all mipmap images in
+ * the texture as dirty and add it to the radeon_texture::swapped list.
+ */
+static void radeonSwapOutTexObj( radeonContextPtr rmesa, radeonTexObjPtr t )
+{
+ if ( t->memBlock ) {
+ mmFreeMem( t->memBlock );
+ t->memBlock = NULL;
+ }
+
+ t->dirty_images = ~0;
+ move_to_tail( &rmesa->texture.swapped, t );
+}
+
+
+/**
+ * Texture space has been invalidated.
+ *
+ * \param rmesa Radeon context.
+ * \param heap texture heap number.
+ *
+ * Swaps out every texture in the specified heap.
+ */
+void radeonAgeTextures( radeonContextPtr rmesa, int heap )
+{
+ radeonTexObjPtr t, tmp;
+
+ foreach_s ( t, tmp, &rmesa->texture.objects[heap] )
+ radeonSwapOutTexObj( rmesa, t );
+}
+
+
+/***************************************************************/
+/** \name Texture image conversions
+ */
+/*@{*/
+
+/**
+ * \brief Upload texture image.
+ *
+ * \param rmesa Radeon context.
+ * \param t Radeon texture object.
+ * \param level level of the image to take the sub-image.
+ * \param x sub-image abscissa.
+ * \param y sub-image ordinate.
+ * \param width sub-image width.
+ * \param height sub-image height.
+ *
+ * Fills in a drmRadeonTexture and drmRadeonTexImage structures and uploads the
+ * texture via the DRM_RADEON_TEXTURE ioctl, aborting in case of failure.
+ */
+static void radeonUploadSubImage( radeonContextPtr rmesa,
+ radeonTexObjPtr t, GLint level,
+ GLint x, GLint y, GLint width, GLint height )
+{
+ struct gl_texture_image *texImage;
+ GLint ret;
+ drmRadeonTexture tex;
+ drmRadeonTexImage tmp;
+
+ level += t->firstLevel;
+ texImage = t->tObj->Image[level];
+
+ if ( !texImage || !texImage->Data )
+ return;
+
+ t->image[level].data = texImage->Data;
+
+ tex.offset = t->bufAddr;
+ tex.pitch = (t->image[0].width * texImage->TexFormat->TexelBytes) / 64;
+ tex.format = t->pp_txformat & RADEON_TXFORMAT_FORMAT_MASK;
+ tex.width = texImage->Width;
+ tex.height = texImage->Height;
+ tex.image = &tmp;
+
+ memcpy( &tmp, &t->image[level], sizeof(drmRadeonTexImage) );
+
+ do {
+ ret = drmCommandWriteRead( rmesa->dri.fd, DRM_RADEON_TEXTURE,
+ &tex, sizeof(drmRadeonTexture) );
+ } while ( ret && errno == EAGAIN );
+
+ if ( ret ) {
+ UNLOCK_HARDWARE( rmesa );
+ fprintf( stderr, "DRM_RADEON_TEXTURE: return = %d\n", ret );
+ exit( 1 );
+ }
+}
+
+/**
+ * \brief Upload texture images.
+ *
+ * This might require removing our own and/or other client's texture objects to
+ * make room for these images.
+ *
+ * \param rmesa Radeon context.
+ * \param tObj texture object to upload.
+ *
+ * Sets the matching hardware texture format. Calculates which mipmap levels to
+ * send, depending of the base image size, GL_TEXTURE_MIN_LOD,
+ * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL and the
+ * Radeon offset rules. Kicks out textures until the requested texture fits,
+ * sets the texture hardware state and, while holding the hardware lock,
+ * uploads any images that are new.
+ */
+static void radeonSetTexImages( radeonContextPtr rmesa,
+ struct gl_texture_object *tObj )
+{
+ radeonTexObjPtr t = (radeonTexObjPtr)tObj->DriverData;
+ const struct gl_texture_image *baseImage = tObj->Image[tObj->BaseLevel];
+ GLint totalSize;
+ GLint texelsPerDword = 0, blitWidth = 0, blitPitch = 0;
+ GLint x, y, width, height;
+ GLint i;
+ GLint firstLevel, lastLevel, numLevels;
+ GLint log2Width, log2Height;
+ GLuint txformat = 0;
+
+ /* This code cannot be reached once we have lost focus
+ */
+ assert(rmesa->radeonScreen->buffers);
+
+ /* Set the hardware texture format
+ */
+ switch (baseImage->TexFormat->MesaFormat) {
+ case MESA_FORMAT_I8:
+ txformat = RADEON_TXFORMAT_I8;
+ texelsPerDword = 4;
+ blitPitch = 64;
+ break;
+ case MESA_FORMAT_RGBA8888:
+ txformat = RADEON_TXFORMAT_RGBA8888 | RADEON_TXFORMAT_ALPHA_IN_MAP;
+ texelsPerDword = 1;
+ blitPitch = 16;
+ break;
+ case MESA_FORMAT_RGB565:
+ txformat = RADEON_TXFORMAT_RGB565;
+ texelsPerDword = 2;
+ blitPitch = 32;
+ break;
+ default:
+ _mesa_problem(NULL, "unexpected texture format in radeonTexImage2D");
+ return;
+ }
+
+ t->pp_txformat &= ~(RADEON_TXFORMAT_FORMAT_MASK |
+ RADEON_TXFORMAT_ALPHA_IN_MAP);
+ t->pp_txformat |= txformat;
+
+
+ /* Select the larger of the two widths for our global texture image
+ * coordinate space. As the Radeon has very strict offset rules, we
+ * can't upload mipmaps directly and have to reference their location
+ * from the aligned start of the whole image.
+ */
+ blitWidth = MAX2( baseImage->Width, blitPitch );
+
+ /* Calculate mipmap offsets and dimensions.
+ */
+ totalSize = 0;
+ x = 0;
+ y = 0;
+
+ /* Compute which mipmap levels we really want to send to the hardware.
+ * This depends on the base image size, GL_TEXTURE_MIN_LOD,
+ * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
+ * Yes, this looks overly complicated, but it's all needed.
+ */
+ firstLevel = tObj->BaseLevel + (GLint) (tObj->MinLod + 0.5);
+ firstLevel = MAX2(firstLevel, tObj->BaseLevel);
+ lastLevel = tObj->BaseLevel + (GLint) (tObj->MaxLod + 0.5);
+ lastLevel = MAX2(lastLevel, tObj->BaseLevel);
+ lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2);
+ lastLevel = MIN2(lastLevel, tObj->MaxLevel);
+ lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */
+
+ /* save these values */
+ t->firstLevel = firstLevel;
+ t->lastLevel = lastLevel;
+
+ numLevels = lastLevel - firstLevel + 1;
+
+ log2Width = tObj->Image[firstLevel]->WidthLog2;
+ log2Height = tObj->Image[firstLevel]->HeightLog2;
+
+ for ( i = 0 ; i < numLevels ; i++ ) {
+ const struct gl_texture_image *texImage = tObj->Image[i + firstLevel];
+ if ( !texImage )
+ break;
+
+ width = texImage->Width;
+ height = texImage->Height;
+
+ /* Texture images have a minimum pitch of 32 bytes (half of the
+ * 64-byte minimum pitch for blits). For images that have a
+ * width smaller than this, we must pad each texture image
+ * scanline out to this amount.
+ */
+ if ( width < blitPitch / 2 ) {
+ width = blitPitch / 2;
+ }
+
+ totalSize += width * height * baseImage->TexFormat->TexelBytes;
+ ASSERT( (totalSize & 31) == 0 );
+
+ while ( width < blitWidth && height > 1 ) {
+ width *= 2;
+ height /= 2;
+ }
+
+ ASSERT(i < RADEON_MAX_TEXTURE_LEVELS);
+ t->image[i].x = x;
+ t->image[i].y = y;
+ t->image[i].width = width;
+ t->image[i].height = height;
+
+ /* While blits must have a pitch of at least 64 bytes, mipmaps
+ * must be aligned on a 32-byte boundary (just like each texture
+ * image scanline).
+ */
+ if ( width >= blitWidth ) {
+ y += height;
+ } else {
+ x += width;
+ if ( x >= blitWidth ) {
+ x = 0;
+ y++;
+ }
+ }
+ }
+
+ /* Align the total size of texture memory block.
+ */
+ t->totalSize = (totalSize + RADEON_OFFSET_MASK) & ~RADEON_OFFSET_MASK;
+
+ /* Hardware state:
+ */
+ t->pp_txfilter &= ~RADEON_MAX_MIP_LEVEL_MASK;
+ t->pp_txfilter |= (numLevels - 1) << RADEON_MAX_MIP_LEVEL_SHIFT;
+
+ t->pp_txformat &= ~(RADEON_TXFORMAT_WIDTH_MASK |
+ RADEON_TXFORMAT_HEIGHT_MASK);
+ t->pp_txformat |= ((log2Width << RADEON_TXFORMAT_WIDTH_SHIFT) |
+ (log2Height << RADEON_TXFORMAT_HEIGHT_SHIFT));
+ t->dirty_state = TEX_ALL;
+
+ /* Update the local texture LRU.
+ */
+ move_to_head( &rmesa->texture.objects[0], t );
+
+ LOCK_HARDWARE( rmesa );
+
+ /* Kick out textures until the requested texture fits */
+ while ( !t->memBlock ) {
+ t->memBlock = mmAllocMem( rmesa->texture.heap[0], t->totalSize, 12, 0);
+
+ if (!t->memBlock)
+ radeonSwapOutTexObj( rmesa, rmesa->texture.objects[0].prev );
+
+ }
+
+ /* Set the base offset of the texture image */
+ t->bufAddr = rmesa->radeonScreen->texOffset[0] + t->memBlock->ofs;
+ t->pp_txoffset = t->bufAddr;
+
+ /* Upload any images that are new
+ */
+ for ( i = 0 ; i < numLevels ; i++ ) {
+ if ( t->dirty_images & (1 << i) ) {
+ radeonUploadSubImage( rmesa, t, i, 0, 0,
+ t->image[i].width, t->image[i].height );
+ }
+ }
+
+ rmesa->texture.age[0] = ++rmesa->sarea->texAge[0];
+ UNLOCK_HARDWARE( rmesa );
+ t->dirty_images = 0;
+}
+
+/*@}*/
+
+
+/******************************************************************/
+/** \name Texture combine functions
+ */
+/*@{*/
+
+enum {
+ RADEON_DISABLE = 0, /**< \brief disabled */
+ RADEON_REPLACE = 1, /**< \brief replace function */
+ RADEON_MODULATE = 2, /**< \brief modulate function */
+ RADEON_DECAL = 3, /**< \brief decal function */
+ RADEON_BLEND = 4, /**< \brief blend function */
+ RADEON_MAX_COMBFUNC = 5 /**< \brief max number of combine functions */
+} ;
+
+
+/**
+ * \brief Color combine function hardware state table.
+ */
+static GLuint radeon_color_combine[][RADEON_MAX_COMBFUNC] =
+{
+ /* Unit 0:
+ */
+ {
+ /* Disable combiner stage
+ */
+ (RADEON_COLOR_ARG_A_ZERO |
+ RADEON_COLOR_ARG_B_ZERO |
+ RADEON_COLOR_ARG_C_CURRENT_COLOR |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+
+ /* GL_REPLACE = 0x00802800
+ */
+ (RADEON_COLOR_ARG_A_ZERO |
+ RADEON_COLOR_ARG_B_ZERO |
+ RADEON_COLOR_ARG_C_T0_COLOR |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+
+ /* GL_MODULATE = 0x00800142
+ */
+ (RADEON_COLOR_ARG_A_CURRENT_COLOR |
+ RADEON_COLOR_ARG_B_T0_COLOR |
+ RADEON_COLOR_ARG_C_ZERO |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+
+ /* GL_DECAL = 0x008c2d42
+ */
+ (RADEON_COLOR_ARG_A_CURRENT_COLOR |
+ RADEON_COLOR_ARG_B_T0_COLOR |
+ RADEON_COLOR_ARG_C_T0_ALPHA |
+ RADEON_BLEND_CTL_BLEND |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+
+ /* GL_BLEND = 0x008c2902
+ */
+ (RADEON_COLOR_ARG_A_CURRENT_COLOR |
+ RADEON_COLOR_ARG_B_TFACTOR_COLOR |
+ RADEON_COLOR_ARG_C_T0_COLOR |
+ RADEON_BLEND_CTL_BLEND |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+ },
+
+};
+
+/**
+ * \brief Alpha combine function hardware state table.
+ */
+static GLuint radeon_alpha_combine[][RADEON_MAX_COMBFUNC] =
+{
+ /* Unit 0:
+ */
+ {
+ /* Disable combiner stage
+ */
+ (RADEON_ALPHA_ARG_A_ZERO |
+ RADEON_ALPHA_ARG_B_ZERO |
+ RADEON_ALPHA_ARG_C_CURRENT_ALPHA |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+
+ /* GL_REPLACE = 0x00800500
+ */
+ (RADEON_ALPHA_ARG_A_ZERO |
+ RADEON_ALPHA_ARG_B_ZERO |
+ RADEON_ALPHA_ARG_C_T0_ALPHA |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+
+ /* GL_MODULATE = 0x00800051
+ */
+ (RADEON_ALPHA_ARG_A_CURRENT_ALPHA |
+ RADEON_ALPHA_ARG_B_T0_ALPHA |
+ RADEON_ALPHA_ARG_C_ZERO |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+
+ /* GL_DECAL = 0x00800100
+ */
+ (RADEON_ALPHA_ARG_A_ZERO |
+ RADEON_ALPHA_ARG_B_ZERO |
+ RADEON_ALPHA_ARG_C_CURRENT_ALPHA |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+
+ /* GL_BLEND = 0x00800051
+ */
+ (RADEON_ALPHA_ARG_A_CURRENT_ALPHA |
+ RADEON_ALPHA_ARG_B_TFACTOR_ALPHA |
+ RADEON_ALPHA_ARG_C_T0_ALPHA |
+ RADEON_BLEND_CTL_BLEND |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+
+ },
+
+};
+
+/*@}*/
+
+
+/******************************************************************/
+/** \name Texture unit state management
+ */
+/*@{*/
+
+/**
+ * \brief Update the texture environment.
+ *
+ * \param ctx GL context
+ * \param unit texture unit to update.
+ *
+ * Sets the state of the RADEON_TEX_PP_TXCBLEND and RADEON_TEX_PP_TXABLEND
+ * registers using the ::radeon_color_combine and ::radeon_alpha_combine tables,
+ * and informs of the state change.
+ */
+static void radeonUpdateTextureEnv( GLcontext *ctx, int unit )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+ const struct gl_texture_object *tObj = texUnit->_Current;
+ const GLenum format = tObj->Image[tObj->BaseLevel]->Format;
+ GLuint color_combine = radeon_color_combine[unit][RADEON_DISABLE];
+ GLuint alpha_combine = radeon_alpha_combine[unit][RADEON_DISABLE];
+
+
+ /* Set the texture environment state. Isn't this nice and clean?
+ * The Radeon will automagically set the texture alpha to 0xff when
+ * the texture format does not include an alpha component. This
+ * reduces the amount of special-casing we have to do, alpha-only
+ * textures being a notable exception.
+ */
+ switch ( texUnit->EnvMode ) {
+ case GL_REPLACE:
+ switch ( format ) {
+ case GL_RGBA:
+ case GL_INTENSITY:
+ color_combine = radeon_color_combine[unit][RADEON_REPLACE];
+ alpha_combine = radeon_alpha_combine[unit][RADEON_REPLACE];
+ break;
+ case GL_RGB:
+ color_combine = radeon_color_combine[unit][RADEON_REPLACE];
+ alpha_combine = radeon_alpha_combine[unit][RADEON_DISABLE];
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case GL_MODULATE:
+ switch ( format ) {
+ case GL_RGBA:
+ case GL_INTENSITY:
+ color_combine = radeon_color_combine[unit][RADEON_MODULATE];
+ alpha_combine = radeon_alpha_combine[unit][RADEON_MODULATE];
+ break;
+ case GL_RGB:
+ color_combine = radeon_color_combine[unit][RADEON_MODULATE];
+ alpha_combine = radeon_alpha_combine[unit][RADEON_DISABLE];
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case GL_DECAL:
+ switch ( format ) {
+ case GL_RGBA:
+ case GL_RGB:
+ color_combine = radeon_color_combine[unit][RADEON_DECAL];
+ alpha_combine = radeon_alpha_combine[unit][RADEON_DISABLE];
+ break;
+ case GL_INTENSITY:
+ color_combine = radeon_color_combine[unit][RADEON_DISABLE];
+ alpha_combine = radeon_alpha_combine[unit][RADEON_DISABLE];
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case GL_BLEND:
+ switch ( format ) {
+ case GL_RGBA:
+ case GL_RGB:
+ color_combine = radeon_color_combine[unit][RADEON_BLEND];
+ alpha_combine = radeon_alpha_combine[unit][RADEON_MODULATE];
+ break;
+ case GL_INTENSITY:
+ color_combine = radeon_color_combine[unit][RADEON_BLEND];
+ alpha_combine = radeon_alpha_combine[unit][RADEON_BLEND];
+ break;
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if ( rmesa->hw.tex[unit].cmd[TEX_PP_TXCBLEND] != color_combine ||
+ rmesa->hw.tex[unit].cmd[TEX_PP_TXABLEND] != alpha_combine ) {
+ RADEON_STATECHANGE( rmesa, tex[unit] );
+ rmesa->hw.tex[unit].cmd[TEX_PP_TXCBLEND] = color_combine;
+ rmesa->hw.tex[unit].cmd[TEX_PP_TXABLEND] = alpha_combine;
+ }
+}
+
+
+#define TEXOBJ_TXFILTER_MASK (RADEON_MAX_MIP_LEVEL_MASK | \
+ RADEON_MIN_FILTER_MASK | \
+ RADEON_MAG_FILTER_MASK | \
+ RADEON_MAX_ANISO_MASK | \
+ RADEON_CLAMP_S_MASK | \
+ RADEON_CLAMP_T_MASK)
+
+#define TEXOBJ_TXFORMAT_MASK (RADEON_TXFORMAT_WIDTH_MASK | \
+ RADEON_TXFORMAT_HEIGHT_MASK | \
+ RADEON_TXFORMAT_FORMAT_MASK | \
+ RADEON_TXFORMAT_ALPHA_IN_MAP)
+
+
+
+void radeonUpdateTextureState( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[0];
+
+ if ( texUnit->_ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT) ) {
+ struct gl_texture_object *tObj = texUnit->_Current;
+ radeonTexObjPtr t = (radeonTexObjPtr) tObj->DriverData;
+
+ /* Upload teximages (not pipelined)
+ */
+ if ( t->dirty_images ) {
+ RADEON_FIREVERTICES( rmesa );
+ radeonSetTexImages( rmesa, tObj );
+ }
+
+ /* Update state if this is a different texture object to last
+ * time.
+ */
+ if ( rmesa->state.texture.unit[0].texobj != t ) {
+ rmesa->state.texture.unit[0].texobj = t;
+ t->dirty_state |= 1<<0;
+ move_to_head( &rmesa->texture.objects[0], t );
+ }
+
+ if (t->dirty_state) {
+ GLuint *cmd = RADEON_DB_STATE( tex[0] );
+
+ cmd[TEX_PP_TXFILTER] &= ~TEXOBJ_TXFILTER_MASK;
+ cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
+ cmd[TEX_PP_TXFILTER] |= t->pp_txfilter & TEXOBJ_TXFILTER_MASK;
+ cmd[TEX_PP_TXFORMAT] |= t->pp_txformat & TEXOBJ_TXFORMAT_MASK;
+ cmd[TEX_PP_TXOFFSET] = t->pp_txoffset;
+ cmd[TEX_PP_BORDER_COLOR] = t->pp_border_color;
+
+ RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.tex[0] );
+ t->dirty_state = 0;
+ }
+
+ /* Newly enabled?
+ */
+ if (!(rmesa->hw.ctx.cmd[CTX_PP_CNTL] & RADEON_TEX_0_ENABLE)) {
+ RADEON_STATECHANGE( rmesa, ctx );
+ rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= (RADEON_TEX_0_ENABLE |
+ RADEON_TEX_BLEND_0_ENABLE);
+
+ RADEON_STATECHANGE( rmesa, tcl );
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_ST0;
+ }
+
+ radeonUpdateTextureEnv( ctx, 0 );
+ }
+ else if (rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (RADEON_TEX_0_ENABLE<<0)) {
+ /* Texture unit disabled */
+ rmesa->state.texture.unit[0].texobj = 0;
+ RADEON_STATECHANGE( rmesa, ctx );
+ rmesa->hw.ctx.cmd[CTX_PP_CNTL] &=
+ ~((RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE) << 0);
+
+ RADEON_STATECHANGE( rmesa, tcl );
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~(RADEON_TCL_VTX_ST0 |
+ RADEON_TCL_VTX_Q0);
+ }
+}
+
+
+
+/**
+ * \brief Choose texture format.
+ *
+ * \param ctx GL context.
+ * \param internalFormat texture internal format.
+ * \param format pixel format. Not used.
+ * \param type pixel data type. Not used.
+ *
+ * \return pointer to chosen texture format.
+ *
+ * Returns a pointer to one of the Mesa texture formats which is supported by
+ * Radeon and matches the internal format.
+ */
+static const struct gl_texture_format *
+radeonChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
+ GLenum format, GLenum type )
+{
+ switch ( internalFormat ) {
+ case GL_RGBA:
+ case GL_RGBA8:
+ return &_mesa_texformat_rgba8888;
+
+ case GL_RGB:
+ case GL_RGB5:
+ return &_mesa_texformat_rgb565;
+
+ case GL_INTENSITY:
+ case GL_INTENSITY8:
+ return &_mesa_texformat_i8;
+
+ default:
+ _mesa_problem(ctx, "unexpected texture format in radeonChoosTexFormat");
+ return NULL;
+ }
+}
+
+/**
+ * \brief Allocate a Radeon texture object.
+ *
+ * \param texObj texture object.
+ *
+ * \return pointer to the device specific texture object on success, or NULL on failure.
+ *
+ * Allocates and initializes a radeon_tex_obj structure to connect it to the
+ * driver private data pointer in \p texObj.
+ */
+static radeonTexObjPtr radeonAllocTexObj( struct gl_texture_object *texObj )
+{
+ radeonTexObjPtr t;
+
+ t = CALLOC_STRUCT( radeon_tex_obj );
+ if (!t)
+ return NULL;
+
+ t->tObj = texObj;
+ texObj->DriverData = t;
+ make_empty_list( t );
+ t->dirty_images = ~0;
+ return t;
+}
+
+
+/**
+ * \brief Load a texture image.
+ *
+ * \param ctx GL context.
+ * \param texObj texture object
+ * \param target target texture.
+ * \param level level of detail number.
+ * \param internalFormat internal format.
+ * \param width texture image width.
+ * \param height texture image height.
+ * \param border border width.
+ * \param format pixel format.
+ * \param type pixel data type.
+ * \param pixels image data.
+ * \param packing passed to _mesa_store_teximage2d() unchanged.
+ * \param texImage passed to _mesa_store_teximage2d() unchanged.
+ *
+ * If there is a device specific texture object associated with the given
+ * texture object then swaps that texture out. Calls _mesa_store_teximage2d()
+ * with all other parameters unchanged.
+ */
+static void radeonTexImage2D( 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 )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ radeonTexObjPtr t = (radeonTexObjPtr)texObj->DriverData;
+
+ if ( t )
+ radeonSwapOutTexObj( rmesa, t );
+
+ /* Note, this will call radeonChooseTextureFormat */
+ _mesa_store_teximage2d(ctx, target, level, internalFormat,
+ width, height, border, format, type, pixels,
+ &ctx->Unpack, texObj, texImage);
+}
+
+/**
+ * \brief Set texture environment parameters.
+ *
+ * \param ctx GL context.
+ * \param target texture environment.
+ * \param pname texture parameter. Accepted value is GL_TEXTURE_ENV_COLOR.
+ * \param param parameter value.
+ *
+ * Updates the current unit's RADEON_TEX_PP_TFACTOR register and informs of the
+ * state change.
+ */
+static void radeonTexEnv( GLcontext *ctx, GLenum target,
+ GLenum pname, const GLfloat *param )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLuint unit = ctx->Texture.CurrentUnit;
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+
+ switch ( pname ) {
+ case GL_TEXTURE_ENV_COLOR: {
+ GLubyte c[4];
+ GLuint envColor;
+ UNCLAMPED_FLOAT_TO_RGBA_CHAN( c, texUnit->EnvColor );
+ envColor = radeonPackColor( 4, c[0], c[1], c[2], c[3] );
+ if ( rmesa->hw.tex[unit].cmd[TEX_PP_TFACTOR] != envColor ) {
+ RADEON_STATECHANGE( rmesa, tex[unit] );
+ rmesa->hw.tex[unit].cmd[TEX_PP_TFACTOR] = envColor;
+ }
+ break;
+ }
+
+ default:
+ return;
+ }
+}
+
+/**
+ * \brief Set texture parameter.
+ *
+ * \param ctx GL context.
+ * \param target target texture.
+ * \param texObj texture object.
+ * \param pname texture parameter.
+ * \param params parameter value.
+ *
+ * Allocates the device specific texture object data if it doesn't exist
+ * already.
+ *
+ * Updates the texture object radeon_tex_obj::pp_txfilter register and marks
+ * the texture state (radeon_tex_obj::dirty_state) as dirty.
+ */
+static void radeonTexParameter( GLcontext *ctx, GLenum target,
+ struct gl_texture_object *texObj,
+ GLenum pname, const GLfloat *params )
+{
+ radeonTexObjPtr t = (radeonTexObjPtr) texObj->DriverData;
+
+ if (!t)
+ t = radeonAllocTexObj( texObj );
+
+ switch ( pname ) {
+ case GL_TEXTURE_MIN_FILTER:
+ t->pp_txfilter &= ~RADEON_MIN_FILTER_MASK;
+ switch ( texObj->MinFilter ) {
+ case GL_NEAREST:
+ t->pp_txfilter |= RADEON_MIN_FILTER_NEAREST;
+ break;
+ case GL_LINEAR:
+ t->pp_txfilter |= RADEON_MIN_FILTER_LINEAR;
+ break;
+ case GL_NEAREST_MIPMAP_NEAREST:
+ t->pp_txfilter |= RADEON_MIN_FILTER_NEAREST_MIP_NEAREST;
+ break;
+ case GL_NEAREST_MIPMAP_LINEAR:
+ t->pp_txfilter |= RADEON_MIN_FILTER_LINEAR_MIP_NEAREST;
+ break;
+ case GL_LINEAR_MIPMAP_NEAREST:
+ t->pp_txfilter |= RADEON_MIN_FILTER_NEAREST_MIP_LINEAR;
+ break;
+ case GL_LINEAR_MIPMAP_LINEAR:
+ t->pp_txfilter |= RADEON_MIN_FILTER_LINEAR_MIP_LINEAR;
+ break;
+ }
+ break;
+
+ case GL_TEXTURE_MAG_FILTER:
+ t->pp_txfilter &= ~RADEON_MAG_FILTER_MASK;
+ switch ( texObj->MagFilter ) {
+ case GL_NEAREST:
+ t->pp_txfilter |= RADEON_MAG_FILTER_NEAREST;
+ break;
+ case GL_LINEAR:
+ t->pp_txfilter |= RADEON_MAG_FILTER_LINEAR;
+ break;
+ }
+ break;
+
+ case GL_TEXTURE_WRAP_S:
+ t->pp_txfilter &= ~RADEON_CLAMP_S_MASK;
+ switch ( texObj->WrapS ) {
+ case GL_REPEAT:
+ t->pp_txfilter |= RADEON_CLAMP_S_WRAP;
+ break;
+ case GL_CLAMP_TO_EDGE:
+ t->pp_txfilter |= RADEON_CLAMP_S_CLAMP_LAST;
+ break;
+ }
+ break;
+
+ case GL_TEXTURE_WRAP_T:
+ t->pp_txfilter &= ~RADEON_CLAMP_T_MASK;
+ switch ( texObj->WrapT ) {
+ case GL_REPEAT:
+ t->pp_txfilter |= RADEON_CLAMP_T_WRAP;
+ break;
+ case GL_CLAMP_TO_EDGE:
+ t->pp_txfilter |= RADEON_CLAMP_T_CLAMP_LAST;
+ break;
+ }
+ break;
+
+ default:
+ return;
+ }
+
+ /* Mark this texobj as dirty (one bit per tex unit)
+ */
+ t->dirty_state = TEX_ALL;
+}
+
+/**
+ * \brief Bind texture.
+ *
+ * \param ctx GL context.
+ * \param target not used.
+ * \param texObj texture object.
+ *
+ * Allocates the device specific texture data if it doesn't exist already.
+ */
+static void radeonBindTexture( GLcontext *ctx, GLenum target,
+ struct gl_texture_object *texObj )
+{
+ if ( !texObj->DriverData )
+ radeonAllocTexObj( texObj );
+}
+
+/**
+ * \brief Delete texture.
+ *
+ * \param ctx GL context.
+ * \param texObj texture object.
+ *
+ * Fires any outstanding vertices and destroy the device specific texture
+ * object.
+ */
+static void radeonDeleteTexture( GLcontext *ctx,
+ struct gl_texture_object *texObj )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ radeonTexObjPtr t = (radeonTexObjPtr) texObj->DriverData;
+
+ if ( t ) {
+ if ( rmesa )
+ RADEON_FIREVERTICES( rmesa );
+ radeonDestroyTexObj( rmesa, t );
+ }
+}
+
+/**
+ * \brief Initialize context texture object data.
+ *
+ * \param ctx GL context.
+ *
+ * Called by radeonInitTextureFuncs() to setup the context initial texture
+ * objects.
+ */
+static void radeonInitTextureObjects( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ struct gl_texture_object *texObj;
+ GLuint tmp = ctx->Texture.CurrentUnit;
+
+ ctx->Texture.CurrentUnit = 0;
+
+ texObj = ctx->Texture.Unit[0].Current2D;
+ radeonBindTexture( ctx, GL_TEXTURE_2D, texObj );
+ move_to_tail( &rmesa->texture.swapped,
+ (radeonTexObjPtr)texObj->DriverData );
+
+
+ ctx->Texture.CurrentUnit = tmp;
+}
+
+/**
+ * \brief Setup the GL context driver callbacks.
+ *
+ * \param ctx GL context.
+ *
+ * \sa Called by radeonCreateContext().
+ */
+void radeonInitTextureFuncs( GLcontext *ctx )
+{
+ ctx->Driver.ChooseTextureFormat = radeonChooseTextureFormat;
+ ctx->Driver.TexImage2D = radeonTexImage2D;
+
+ ctx->Driver.BindTexture = radeonBindTexture;
+ ctx->Driver.CreateTexture = NULL; /* FIXME: Is this used??? */
+ ctx->Driver.DeleteTexture = radeonDeleteTexture;
+ ctx->Driver.PrioritizeTexture = NULL;
+ ctx->Driver.ActiveTexture = NULL;
+ ctx->Driver.UpdateTexturePalette = NULL;
+
+ ctx->Driver.TexEnv = radeonTexEnv;
+ ctx->Driver.TexParameter = radeonTexParameter;
+
+ radeonInitTextureObjects( ctx );
+}
+
+/*@}*/
diff --git a/src/mesa/drivers/dri/radeon/radeon_subset_vtx.c b/src/mesa/drivers/dri/radeon/radeon_subset_vtx.c
new file mode 100644
index 0000000000..aa6ec73d5b
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_subset_vtx.c
@@ -0,0 +1,989 @@
+/**
+ * \file radeon_subset_vtx.c
+ * \brief Vertex buffering.
+ *
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+/*
+ * Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+ * Tungsten Graphics Inc., Cedar Park, Texas.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * 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, TUNGSTEN GRAPHICS 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.
+ *
+ */
+
+/* $XFree86$ */
+
+#include "glheader.h"
+#include "imports.h"
+#include "api_noop.h"
+#include "context.h"
+/*#include "mmath.h" */
+#include "mtypes.h"
+#include "enums.h"
+#include "glapi.h"
+#include "colormac.h"
+#include "state.h"
+
+#include "radeon_context.h"
+#include "radeon_state.h"
+#include "radeon_ioctl.h"
+#include "radeon_subset.h"
+
+/**
+ * \brief Union for vertex data.
+ */
+union vertex_dword {
+ float f; /**< \brief floating point value */
+ int i; /**< \brief integer point value */
+};
+
+
+/**
+ * \brief Maximum number of dwords per vertex.
+ *
+ * Defined as 10 to hold: \code xyzw rgba st \endcode
+ */
+#define MAX_VERTEX_DWORDS 10
+
+
+/**
+ * \brief Global vertex buffer data.
+ */
+static struct vb_t {
+ /**
+ * \brief Notification mechanism.
+ *
+ * These are treated as a stack to allow us to do things like build quads in
+ * temporary storage and then emit them as triangles.
+ */
+ struct {
+ GLint vertspace; /**< \brief free vertices count */
+ GLint initial_vertspace; /**< \brief total vertices count */
+ GLint *dmaptr; /**< \brief */
+ void (*notify)( void ); /**< \brief notification callback */
+ } stack[2];
+
+ /**
+ * \brief Storage for current vertex.
+ */
+ union vertex_dword vertex[MAX_VERTEX_DWORDS];
+
+ /**
+ * \brief Temporary storage for quads, etc.
+ */
+ union vertex_dword vertex_store[MAX_VERTEX_DWORDS * 4];
+
+ /**
+ * \name Color/texture
+ *
+ * Pointers to either vertex or ctx->Current.Attrib, depending on whether
+ * color/texture participates in the current vertex.
+ */
+ /*@{*/
+ GLfloat *floatcolorptr; /**< \brief color */
+ GLfloat *texcoordptr; /**< \brief texture */
+ /*@}*/
+
+ /**
+ * \brief Pointer to the GL context.
+ */
+ GLcontext *context;
+
+ /**
+ * \brief Active primitive.
+ *
+ * \note May differ from ctx->Driver.CurrentExecPrimitive.
+ */
+ /*@{*/
+ GLenum prim; /**< \brief primitive */
+ GLuint vertex_format; /**< \brief vertex format */
+ GLint vertex_size; /**< \brief vertex size */
+ GLboolean recheck; /**< \brief set if it's needed to validate this information */
+ /*@}*/
+} vb;
+
+
+static void radeonFlushVertices( GLcontext *, GLuint );
+
+
+/**
+ * \brief Primitive information table.
+ */
+static struct prims_t {
+ int start, /**< \brief vertex count for the starting primitive */
+ incr, /**< \brief vertex increment for a further primitive */
+ hwprim; /**< \brief hardware primitive */
+} prims[10] = {
+ { 1, 1, RADEON_CP_VC_CNTL_PRIM_TYPE_POINT },
+ { 2, 2, RADEON_CP_VC_CNTL_PRIM_TYPE_LINE },
+ { 2, 1, RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP },
+ { 2, 1, RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP },
+ { 3, 3, RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST },
+ { 3, 1, RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP },
+ { 3, 1, RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN },
+ { 4, 4, RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST },
+ { 4, 2, RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP },
+ { 3, 1, RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN },
+};
+
+
+/**
+ * \brief Finish the primitive in the vertex buffer.
+ *
+ * \param rmesa Radeon context.
+ *
+ * Truncates any redundant vertices off the end of the buffer, emit the
+ * remaining vertices and advances the current DMA region.
+ */
+static void finish_prim( radeonContextPtr rmesa )
+{
+ GLuint prim_end = vb.stack[0].initial_vertspace - vb.stack[0].vertspace;
+
+ /* Too few vertices? (eg: 2 vertices for a triangles prim?)
+ */
+ if (prim_end < prims[vb.prim].start)
+ return;
+
+ /* Drop redundant vertices off end of primitive. (eg: 5 vertices
+ * for triangles prim?)
+ */
+ prim_end -= (prim_end - prims[vb.prim].start) % prims[vb.prim].incr;
+
+ radeonEmitVertexAOS( rmesa, vb.vertex_size, GET_START(&rmesa->dma.current) );
+
+ radeonEmitVbufPrim( rmesa, vb.vertex_format,
+ prims[vb.prim].hwprim | rmesa->tcl.tcl_flag,
+ prim_end );
+
+ rmesa->dma.current.ptr =
+ rmesa->dma.current.start += prim_end * vb.vertex_size * 4;
+}
+
+
+/**
+ * \brief Copy a vertex from the current DMA region
+ *
+ * \param rmesa Radeon context.
+ * \param n vertex index relative to the current DMA region.
+ * \param dst destination pointer.
+ *
+ * Used internally by copy_dma_verts().
+ */
+static void copy_vertex( radeonContextPtr rmesa, GLuint n, GLfloat *dst )
+{
+ GLuint i;
+ GLfloat *src = (GLfloat *)(rmesa->dma.current.address +
+ rmesa->dma.current.ptr +
+ n * vb.vertex_size * 4);
+
+ for (i = 0 ; i < vb.vertex_size; i++)
+ dst[i] = src[i];
+}
+
+
+/**
+ * \brief Copy last vertices from the current DMA buffer to resume in a new buffer.
+ *
+ * \param rmesa Radeon context.
+ * \param tmp destination buffer.
+ *
+ * Takes from the current DMA buffer the last vertices necessary to resume in a
+ * new buffer, according to the current primitive. Uses internally
+ * copy_vertex() for the vertex copying.
+ *
+ */
+static GLuint copy_dma_verts( radeonContextPtr rmesa,
+ GLfloat (*tmp)[MAX_VERTEX_DWORDS] )
+{
+ GLuint ovf, i;
+ GLuint nr = vb.stack[0].initial_vertspace - vb.stack[0].vertspace;
+
+ switch( vb.prim )
+ {
+ case GL_POINTS:
+ return 0;
+ case GL_LINES:
+ ovf = nr&1;
+ for (i = 0 ; i < ovf ; i++)
+ copy_vertex( rmesa, nr-ovf+i, tmp[i] );
+ return i;
+ case GL_LINE_STRIP:
+ if (nr == 0)
+ return 0;
+ copy_vertex( rmesa, nr-1, tmp[0] );
+ return 1;
+ case GL_LINE_LOOP:
+ case GL_TRIANGLE_FAN:
+ case GL_POLYGON:
+ if (nr == 0)
+ return 0;
+ else if (nr == 1) {
+ copy_vertex( rmesa, 0, tmp[0] );
+ return 1;
+ } else {
+ copy_vertex( rmesa, 0, tmp[0] );
+ copy_vertex( rmesa, nr-1, tmp[1] );
+ return 2;
+ }
+ case GL_TRIANGLES:
+ ovf = nr % 3;
+ for (i = 0 ; i < ovf ; i++)
+ copy_vertex( rmesa, nr-ovf+i, tmp[i] );
+ return i;
+ case GL_QUADS:
+ ovf = nr % 4;
+ for (i = 0 ; i < ovf ; i++)
+ copy_vertex( rmesa, nr-ovf+i, tmp[i] );
+ return i;
+ case GL_TRIANGLE_STRIP:
+ case GL_QUAD_STRIP:
+ ovf = MIN2(nr, 2);
+ for (i = 0 ; i < ovf ; i++)
+ copy_vertex( rmesa, nr-ovf+i, tmp[i] );
+ return i;
+ default:
+ return 0;
+ }
+}
+
+static void notify_wrap_buffer( void );
+
+/**
+ * \brief Resets the vertex buffer notification mechanism.
+ *
+ * Fills in vb_t::stack with the values from the current DMA region in
+ * radeon_dma::current and sets the notification callback to
+ * notify_wrap_buffer().
+ */
+static void reset_notify( void )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT( vb.context );
+
+ vb.stack[0].dmaptr = (int *)(rmesa->dma.current.address +
+ rmesa->dma.current.ptr);
+ vb.stack[0].vertspace = ((rmesa->dma.current.end - rmesa->dma.current.ptr) /
+ (vb.vertex_size * 4));
+ vb.stack[0].vertspace &= ~1; /* even numbers only -- avoid tristrip parity */
+ vb.stack[0].initial_vertspace = vb.stack[0].vertspace;
+ vb.stack[0].notify = notify_wrap_buffer;
+}
+
+/**
+ * \brief Full buffer notification callback.
+ *
+ * Makes a copy of the necessary vertices of the current buffer via
+ * copy_dma_verts(), gets and resets new buffer via radeon and re-emits the
+ * saved vertices.
+ */
+static void notify_wrap_buffer( void )
+{
+ GLcontext *ctx = vb.context;
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLfloat tmp[3][MAX_VERTEX_DWORDS];
+ GLuint i, nrverts = 0;
+
+ /* Copy vertices out of dma:
+ */
+ nrverts = copy_dma_verts( rmesa, tmp );
+ finish_prim( rmesa );
+
+ /* Get new buffer
+ */
+ radeonRefillCurrentDmaRegion( rmesa );
+
+ /* Reset vertspace[0], dmaptr
+ */
+ reset_notify();
+
+ /* Reemit saved vertices
+ */
+ for (i = 0 ; i < nrverts; i++) {
+ memcpy( vb.stack[0].dmaptr, tmp[i], vb.vertex_size * 4 );
+ vb.stack[0].dmaptr += vb.vertex_size;
+ vb.stack[0].vertspace--;
+ }
+}
+
+
+static void notify_noop( void )
+{
+ vb.stack[0].dmaptr = (int *)vb.vertex;
+ vb.stack[0].notify = notify_noop;
+ vb.stack[0].vertspace = 1;
+}
+
+/**
+ * \brief Pop the notification mechanism stack.
+ *
+ * Simply copy the second stack array element into the first.
+ *
+ * \sa vb_t::stack and push_notify().
+ */
+static void pop_notify( void )
+{
+ vb.stack[0] = vb.stack[1];
+}
+
+/**
+ * \brief Push the notification mechanism stack.
+ *
+ * \param notify new notify callback for the stack head.
+ * \param space space available for vertices in \p store.
+ * \param store buffer where to store the vertices.
+ *
+ * Copy the second stack array element into the first and makes the stack head
+ * use the given resources.
+ *
+ * \sa vb_t::stack and pop_notify().
+ */
+static void push_notify( void (*notify)( void ), int space,
+ union vertex_dword *store )
+{
+ vb.stack[1] = vb.stack[0];
+ vb.stack[0].notify = notify;
+ vb.stack[0].initial_vertspace = space;
+ vb.stack[0].vertspace = space;
+ vb.stack[0].dmaptr = (int *)store;
+}
+
+
+/**
+ * \brief Emit a stored vertex (in vb_t::vertex_store) to DMA.
+ *
+ * \param v vertex index.
+ *
+ * Adds the vertex into the current vertex buffer and calls the notification
+ * callback vb_t::notify().
+ */
+static void emit_vertex( int v )
+{
+ int i, *tmp = (int *)vb.vertex_store + v * vb.vertex_size;
+
+ for (i = 0 ; i < vb.vertex_size ; i++)
+ *vb.stack[0].dmaptr++ = *tmp++;
+
+ if (--vb.stack[0].vertspace == 0)
+ vb.stack[0].notify();
+}
+
+
+/**
+ * \brief Emit a quad (in vb_t::vertex_store) to DMA as two triangles.
+ *
+ * \param v0 first vertex index.
+ * \param v1 second vertex index.
+ * \param v2 third vertex index.
+ * \param v3 fourth vertex index.
+ *
+ * Calls emit_vertex() to emit the triangles' vertices.
+ */
+static void emit_quad( int v0, int v1, int v2, int v3 )
+{
+ emit_vertex( v0 ); emit_vertex( v1 ); emit_vertex( v3 );
+ emit_vertex( v1 ); emit_vertex( v2 ); emit_vertex( v3 );
+}
+
+/**
+ * \brief Every fourth vertex in a quad primitive, this is called to emit it.
+ *
+ * Pops the notification stack, calls emit_quad() and pushes the notification
+ * stack again, with itself and the vb_t::vertex_store to process another four
+ * vertices.
+ */
+static void notify_quad( void )
+{
+ pop_notify();
+ emit_quad( 0, 1, 2, 3 );
+ push_notify( notify_quad, 4, vb.vertex_store );
+}
+
+static void notify_qstrip1( void );
+
+/**
+ * \brief After the 4th vertex, emit either a quad or a flipped quad each two
+ * vertices.
+ *
+ * Pops the notification stack, calls emit_quad() with the flipped vertices and
+ * pushes the notification stack again, with notify_qstrip1() and the
+ * vb_t::vertex_store to process another two vertices.
+ *
+ * \sa notify_qstrip1().
+ */
+static void notify_qstrip0( void )
+{
+ pop_notify();
+ emit_quad( 0, 1, 3, 2 );
+ push_notify( notify_qstrip1, 2, vb.vertex_store );
+}
+
+/**
+ * \brief After the 4th vertex, emit either a quad or a flipped quad each two
+ * vertices.
+ *
+ * Pops the notification stack, calls emit_quad() with the straight vertices
+ * and pushes the notification stack again, with notify_qstrip0() and the
+ * vb_t::vertex_store to process another two vertices.
+ *
+ * \sa notify_qstrip0().
+ */
+static void notify_qstrip1( void )
+{
+ pop_notify();
+ emit_quad( 2, 3, 1, 0 );
+ push_notify( notify_qstrip0, 2, vb.vertex_store + 2*vb.vertex_size );
+}
+
+/**
+ * \brief Emit the saved vertex (but hang on to it for later).
+ *
+ * Continue processing this primitive as a linestrip.
+ *
+ * Pops the notification stack and calls emit_quad with the first vertex.
+ */
+static void notify_lineloop0( void )
+{
+ pop_notify();
+ emit_vertex(0);
+}
+
+/**
+ * \brief Invalidate the current vertex format.
+ *
+ * \param ctx GL context.
+ *
+ * Sets the vb_t::recheck flag.
+ */
+void radeonVtxfmtInvalidate( GLcontext *ctx )
+{
+ vb.recheck = GL_TRUE;
+}
+
+
+/**
+ * \brief Validate the vertex format from the context.
+ *
+ * \param ctx GL context.
+ *
+ * Signals a new primitive and determines the appropriate vertex format and
+ * size. Points vb_t::floatcolorptr and vb_t::texcoordptr to the current vertex
+ * and sets them to the current color and texture attributes.
+ *
+ * Clears the vb_t::recheck flag on exit.
+ */
+static void radeonVtxfmtValidate( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+ GLuint ind = (RADEON_CP_VC_FRMT_Z |
+ RADEON_CP_VC_FRMT_FPCOLOR |
+ RADEON_CP_VC_FRMT_FPALPHA);
+
+ if (ctx->Driver.NeedFlush)
+ ctx->Driver.FlushVertices( ctx, ctx->Driver.NeedFlush );
+
+ if (ctx->Texture.Unit[0]._ReallyEnabled)
+ ind |= RADEON_CP_VC_FRMT_ST0;
+
+ RADEON_NEWPRIM(rmesa);
+ vb.vertex_format = ind;
+ vb.vertex_size = 3;
+
+ /* Would prefer to use ubyte floats in the vertex:
+ */
+ vb.floatcolorptr = &vb.vertex[vb.vertex_size].f;
+ vb.vertex_size += 4;
+ vb.floatcolorptr[0] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0];
+ vb.floatcolorptr[1] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1];
+ vb.floatcolorptr[2] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2];
+ vb.floatcolorptr[3] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3];
+
+ if (ind & RADEON_CP_VC_FRMT_ST0) {
+ vb.texcoordptr = &vb.vertex[vb.vertex_size].f;
+ vb.vertex_size += 2;
+ vb.texcoordptr[0] = ctx->Current.Attrib[VERT_ATTRIB_TEX0][0];
+ vb.texcoordptr[1] = ctx->Current.Attrib[VERT_ATTRIB_TEX0][1];
+ }
+ else
+ vb.texcoordptr = ctx->Current.Attrib[VERT_ATTRIB_TEX0];
+
+ vb.recheck = GL_FALSE;
+ ctx->Driver.NeedFlush = FLUSH_UPDATE_CURRENT;
+}
+
+
+#define RESET_STIPPLE() do { \
+ RADEON_STATECHANGE( rmesa, lin ); \
+ radeonEmitState( rmesa ); \
+} while (0)
+
+#define AUTO_STIPPLE( mode ) do { \
+ RADEON_STATECHANGE( rmesa, lin ); \
+ if (mode) \
+ rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] |= \
+ RADEON_LINE_PATTERN_AUTO_RESET; \
+ else \
+ rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] &= \
+ ~RADEON_LINE_PATTERN_AUTO_RESET; \
+ radeonEmitState( rmesa ); \
+} while (0)
+
+
+/**
+ * \brief Process glBegin().
+ *
+ * \param mode primitive.
+ */
+static void radeon_Begin( GLenum mode )
+{
+ GLcontext *ctx = vb.context;
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLuint se_cntl;
+
+ if (mode > GL_POLYGON) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glBegin" );
+ return;
+ }
+
+ if (ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) {
+ _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" );
+ return;
+ }
+
+ if (ctx->NewState)
+ _mesa_update_state( ctx );
+
+ if (rmesa->NewGLState)
+ radeonValidateState( ctx );
+
+ if (vb.recheck)
+ radeonVtxfmtValidate( ctx );
+
+ /* Do we need to grab a new DMA region for the vertices?
+ */
+ if (rmesa->dma.current.ptr + 12*vb.vertex_size*4 > rmesa->dma.current.end) {
+ RADEON_NEWPRIM( rmesa );
+ radeonRefillCurrentDmaRegion( rmesa );
+ }
+
+ reset_notify();
+ vb.prim = ctx->Driver.CurrentExecPrimitive = mode;
+ se_cntl = rmesa->hw.set.cmd[SET_SE_CNTL] | RADEON_FLAT_SHADE_VTX_LAST;
+
+ if (ctx->Line.StippleFlag &&
+ (mode == GL_LINES ||
+ mode == GL_LINE_LOOP ||
+ mode == GL_LINE_STRIP))
+ RESET_STIPPLE();
+
+ switch( mode ) {
+ case GL_LINES:
+ if (ctx->Line.StippleFlag)
+ AUTO_STIPPLE( GL_TRUE );
+ break;
+ case GL_LINE_LOOP:
+ vb.prim = GL_LINE_STRIP;
+ push_notify( notify_lineloop0, 1, vb.vertex_store );
+ break;
+ case GL_QUADS:
+ vb.prim = GL_TRIANGLES;
+ push_notify( notify_quad, 4, vb.vertex_store );
+ break;
+ case GL_QUAD_STRIP:
+ if (ctx->_TriangleCaps & DD_FLATSHADE) {
+ vb.prim = GL_TRIANGLES;
+ push_notify( notify_qstrip0, 4, vb.vertex_store );
+ }
+ break;
+ case GL_POLYGON:
+ if (ctx->_TriangleCaps & DD_FLATSHADE)
+ se_cntl &= ~RADEON_FLAT_SHADE_VTX_LAST;
+ break;
+ default:
+ break;
+ }
+
+ if (se_cntl != rmesa->hw.set.cmd[SET_SE_CNTL]) {
+ RADEON_STATECHANGE( rmesa, set );
+ rmesa->hw.set.cmd[SET_SE_CNTL] = se_cntl;
+ }
+}
+
+
+/**
+ * \brief Process glEnd().
+ *
+ */
+static void radeon_End( void )
+{
+ GLcontext *ctx = vb.context;
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) {
+ _mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" );
+ return;
+ }
+
+ /* Need to finish a line loop?
+ */
+ if (ctx->Driver.CurrentExecPrimitive == GL_LINE_LOOP)
+ emit_vertex( 0 );
+
+ /* Need to pop off quads/quadstrip/etc notification?
+ */
+ if (vb.stack[0].notify != notify_wrap_buffer)
+ pop_notify();
+
+ finish_prim( rmesa );
+
+ if (ctx->Driver.CurrentExecPrimitive == GL_LINES && ctx->Line.StippleFlag)
+ AUTO_STIPPLE( GL_FALSE );
+
+ ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1;
+ notify_noop();
+}
+
+
+
+/**
+ * \brief Flush vertices.
+ *
+ * \param ctx GL context.
+ * \param flags flags.
+ *
+ * If FLUSH_UPDATE_CURRENT is et in \p flags then the current vertex attributes
+ * in the GL context is updated from vb_t::floatcolorptr and vb_t::texcoordptr.
+ */
+static void radeonFlushVertices( GLcontext *ctx, GLuint flags )
+{
+ if (flags & FLUSH_UPDATE_CURRENT) {
+ ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0] = vb.floatcolorptr[0];
+ ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1] = vb.floatcolorptr[1];
+ ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2] = vb.floatcolorptr[2];
+ ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3] = vb.floatcolorptr[3];
+
+ if (vb.vertex_format & RADEON_CP_VC_FRMT_ST0) {
+ ctx->Current.Attrib[VERT_ATTRIB_TEX0][0] = vb.texcoordptr[0];
+ ctx->Current.Attrib[VERT_ATTRIB_TEX0][1] = vb.texcoordptr[1];
+ ctx->Current.Attrib[VERT_ATTRIB_TEX0][2] = 0.0F;
+ ctx->Current.Attrib[VERT_ATTRIB_TEX0][3] = 1.0F;
+ }
+ }
+
+ ctx->Driver.NeedFlush &= ~FLUSH_STORED_VERTICES;
+}
+
+
+/**
+ * \brief Set current vertex coordinates.
+ *
+ * \param x x vertex coordinate.
+ * \param y y vertex coordinate.
+ * \param z z vertex coordinate.
+ *
+ * Set the current vertex coordinates. If run out of space in this buffer call
+ * the notification callback.
+ */
+static __inline__ void radeon_Vertex3f( GLfloat x, GLfloat y, GLfloat z )
+{
+ int i;
+
+ *vb.stack[0].dmaptr++ = *(int *)&x;
+ *vb.stack[0].dmaptr++ = *(int *)&y;
+ *vb.stack[0].dmaptr++ = *(int *)&z;
+
+ for (i = 3; i < vb.vertex_size; i++)
+ *vb.stack[0].dmaptr++ = vb.vertex[i].i;
+
+ if (--vb.stack[0].vertspace == 0)
+ vb.stack[0].notify();
+}
+
+/**
+ * \brief Set current vertex color.
+ *
+ * \param r red color component.
+ * \param g gree color component.
+ * \param b blue color component.
+ * \param a alpha color component.
+ *
+ * Sets the current vertex color via vb_t::floatcolorptr.
+ */
+static __inline__ void radeon_Color4f( GLfloat r, GLfloat g,
+ GLfloat b, GLfloat a )
+{
+ GLfloat *dest = vb.floatcolorptr;
+ dest[0] = r;
+ dest[1] = g;
+ dest[2] = b;
+ dest[3] = a;
+}
+
+/**
+ * \brief Set current vertex texture coordinates.
+ *
+ * \param s texture coordinate.
+ * \param t texture coordinate.
+ *
+ * Sets the current vertex color via vb_t::texcoordptr.
+ */
+static __inline__ void radeon_TexCoord2f( GLfloat s, GLfloat t )
+{
+ GLfloat *dest = vb.texcoordptr;
+ dest[0] = s;
+ dest[1] = t;
+}
+
+/**
+ * Calls radeon_Vertex3f(), which is expanded inline by the compiler to be
+ * efficient.
+ */
+static void radeon_Vertex3fv( const GLfloat *v )
+{
+ radeon_Vertex3f( v[0], v[1], v[2] );
+}
+
+/**
+ * Calls radeon_Vertex3f(), which is expanded inline by the compiler to be
+ * efficient.
+ */
+static void radeon_Vertex2f( GLfloat x, GLfloat y )
+{
+ radeon_Vertex3f( x, y, 0 );
+}
+
+/**
+ * Calls radeon_Vertex3f(), which is expanded inline by the compiler to be
+ * efficient.
+ */
+static void radeon_Vertex2fv( const GLfloat *v )
+{
+ radeon_Vertex3f( v[0], v[1], 0 );
+}
+
+/**
+ * Calls radeon_Vertex3f(), which is expanded inline by the compiler to be
+ * efficient.
+ */
+static void radeon_Color4fv( const GLfloat *v )
+{
+ radeon_Color4f( v[0], v[1], v[2], v[3] );
+}
+
+/**
+ * Calls radeon_Color4f(), which is expanded inline by the compiler to be
+ * efficient.
+ */
+static void radeon_Color3f( GLfloat r, GLfloat g, GLfloat b )
+{
+ radeon_Color4f( r, g, b, 1.0 );
+}
+
+/**
+ * Calls radeon_Color4f(), which is expanded inline by the compiler to be
+ * efficient.
+ */
+static void radeon_Color3fv( const GLfloat *v )
+{
+ radeon_Color4f( v[0], v[1], v[2], 1.0 );
+}
+
+/**
+ * Calls radeon_TexCoord2f(), which is expanded inline by the compiler to be
+ * efficient.
+ */
+static void radeon_TexCoord2fv( const GLfloat *v )
+{
+ radeon_TexCoord2f( v[0], v[1] );
+}
+
+
+/**
+ * No-op.
+ */
+void radeonVtxfmtUnbindContext( GLcontext *ctx )
+{
+}
+
+/**
+ * No-op.
+ */
+void radeonVtxfmtMakeCurrent( GLcontext *ctx )
+{
+}
+
+/**
+ * No-op.
+ */
+void radeonVtxfmtDestroy( GLcontext *ctx )
+{
+}
+
+/**
+ * \brief Software rendering fallback.
+ *
+ * \param ctx GL context.
+ * \param bit fallback bitmask.
+ * \param mode enable or disable.
+ *
+ * Does nothing except display a warning message if \p mode is set.
+ */
+void radeonFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
+{
+ if (mode)
+ fprintf(stderr, "Warning: hit nonexistant fallback path!\n");
+}
+
+/**
+ * \brief Software TCL fallback.
+ *
+ * \param ctx GL context.
+ * \param bit fallback bitmask.
+ * \param mode enable or disable.
+ *
+ * Does nothing except display a warning message if \p mode is set.
+ */
+void radeonTclFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
+{
+ if (mode)
+ fprintf(stderr, "Warning: hit nonexistant fallback path!\n");
+}
+
+/**
+ * \brief Called by radeonPointsBitmap() to disable TCL.
+ *
+ * \param rmesa Radeon context.
+ * \param flag whether to enable or disable TCL.
+ *
+ * Updates radeon_tcl_info::tcl_flag.
+ */
+void radeonSubsetVtxEnableTCL( radeonContextPtr rmesa, GLboolean flag )
+{
+ rmesa->tcl.tcl_flag = flag ? RADEON_CP_VC_CNTL_TCL_ENABLE : 0;
+}
+
+
+
+/**********************************************************************/
+/** \name Noop mode for operation without focus */
+/**********************************************************************/
+/*@{*/
+
+
+/**
+ * \brief Process glBegin().
+ *
+ * \param mode primitive.
+ */
+static void radeon_noop_Begin(GLenum mode)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (mode > GL_POLYGON) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glBegin" );
+ return;
+ }
+
+ if (ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) {
+ _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" );
+ return;
+ }
+
+ ctx->Driver.CurrentExecPrimitive = mode;
+}
+
+/**
+ * \brief Process glEnd().
+ */
+static void radeon_noop_End(void)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1;
+}
+
+
+/**
+ * \brief Install the noop callbacks.
+ *
+ * \param ctx GL context.
+ *
+ * Installs the noop callbacks into the glapi table. These functions
+ * will not attempt to emit any DMA vertices, but will keep internal
+ * GL state updated. Borrows heavily from the select code.
+ */
+static void radeon_noop_Install( GLcontext *ctx )
+{
+ ctx->Exec->Begin = radeon_noop_Begin;
+ ctx->Exec->End = radeon_noop_End;
+
+ vb.texcoordptr = ctx->Current.Attrib[VERT_ATTRIB_TEX0];
+ vb.floatcolorptr = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
+
+ notify_noop();
+}
+
+
+/**
+ * \brief Setup the GL context callbacks.
+ *
+ * \param ctx GL context.
+ *
+ * Setups the GL context callbacks and links _glapi_table entries related to
+ * the glBegin()/glEnd() pairs to the functions in this module.
+ *
+ * Called by radeonCreateContext() and radeonRenderMode().
+ */
+void radeonVtxfmtInit( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ struct _glapi_table *exec = ctx->Exec;
+
+ exec->Color3f = radeon_Color3f;
+ exec->Color3fv = radeon_Color3fv;
+ exec->Color4f = radeon_Color4f;
+ exec->Color4fv = radeon_Color4fv;
+ exec->TexCoord2f = radeon_TexCoord2f;
+ exec->TexCoord2fv = radeon_TexCoord2fv;
+ exec->Vertex2f = radeon_Vertex2f;
+ exec->Vertex2fv = radeon_Vertex2fv;
+ exec->Vertex3f = radeon_Vertex3f;
+ exec->Vertex3fv = radeon_Vertex3fv;
+ exec->Begin = radeon_Begin;
+ exec->End = radeon_End;
+
+ vb.context = ctx;
+
+ ctx->Driver.FlushVertices = radeonFlushVertices;
+ ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1;
+
+ if (rmesa->radeonScreen->buffers) {
+ radeonVtxfmtValidate( ctx );
+ notify_noop();
+ }
+ else
+ radeon_noop_Install( ctx );
+}
+
+
+/*@}*/
+
+
diff --git a/src/mesa/drivers/dri/radeon/radeon_swtcl.c b/src/mesa/drivers/dri/radeon/radeon_swtcl.c
new file mode 100644
index 0000000000..926b1523d6
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_swtcl.c
@@ -0,0 +1,1332 @@
+/* $XFree86$ */
+/**************************************************************************
+
+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 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 THE COPYRIGHT OWNER(S) 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 "glheader.h"
+#include "mtypes.h"
+#include "colormac.h"
+#include "enums.h"
+#include "imports.h"
+#include "macros.h"
+
+#include "swrast_setup/swrast_setup.h"
+#include "math/m_translate.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_imm_exec.h"
+#include "tnl/t_pipeline.h"
+
+#include "radeon_context.h"
+#include "radeon_ioctl.h"
+#include "radeon_state.h"
+#include "radeon_swtcl.h"
+#include "radeon_tcl.h"
+
+/***********************************************************************
+ * Build render functions from dd templates *
+ ***********************************************************************/
+
+
+#define RADEON_XYZW_BIT 0x01
+#define RADEON_RGBA_BIT 0x02
+#define RADEON_SPEC_BIT 0x04
+#define RADEON_TEX0_BIT 0x08
+#define RADEON_TEX1_BIT 0x10
+#define RADEON_PTEX_BIT 0x20
+#define RADEON_MAX_SETUP 0x40
+
+static void flush_last_swtcl_prim( radeonContextPtr rmesa );
+static void flush_last_swtcl_prim_compat( radeonContextPtr rmesa );
+
+static struct {
+ void (*emit)( GLcontext *, GLuint, GLuint, void *, GLuint );
+ interp_func interp;
+ copy_pv_func copy_pv;
+ GLboolean (*check_tex_sizes)( GLcontext *ctx );
+ GLuint vertex_size;
+ GLuint vertex_stride_shift;
+ GLuint vertex_format;
+} setup_tab[RADEON_MAX_SETUP];
+
+
+#define TINY_VERTEX_FORMAT (RADEON_CP_VC_FRMT_XY | \
+ RADEON_CP_VC_FRMT_Z | \
+ RADEON_CP_VC_FRMT_PKCOLOR)
+
+#define NOTEX_VERTEX_FORMAT (RADEON_CP_VC_FRMT_XY | \
+ RADEON_CP_VC_FRMT_Z | \
+ RADEON_CP_VC_FRMT_W0 | \
+ RADEON_CP_VC_FRMT_PKCOLOR | \
+ RADEON_CP_VC_FRMT_PKSPEC)
+
+#define TEX0_VERTEX_FORMAT (RADEON_CP_VC_FRMT_XY | \
+ RADEON_CP_VC_FRMT_Z | \
+ RADEON_CP_VC_FRMT_W0 | \
+ RADEON_CP_VC_FRMT_PKCOLOR | \
+ RADEON_CP_VC_FRMT_PKSPEC | \
+ RADEON_CP_VC_FRMT_ST0)
+
+#define TEX1_VERTEX_FORMAT (RADEON_CP_VC_FRMT_XY | \
+ RADEON_CP_VC_FRMT_Z | \
+ RADEON_CP_VC_FRMT_W0 | \
+ RADEON_CP_VC_FRMT_PKCOLOR | \
+ RADEON_CP_VC_FRMT_PKSPEC | \
+ RADEON_CP_VC_FRMT_ST0 | \
+ RADEON_CP_VC_FRMT_ST1)
+
+#define PROJ_TEX1_VERTEX_FORMAT (RADEON_CP_VC_FRMT_XY | \
+ RADEON_CP_VC_FRMT_Z | \
+ RADEON_CP_VC_FRMT_W0 | \
+ RADEON_CP_VC_FRMT_PKCOLOR | \
+ RADEON_CP_VC_FRMT_PKSPEC | \
+ RADEON_CP_VC_FRMT_ST0 | \
+ RADEON_CP_VC_FRMT_Q0 | \
+ RADEON_CP_VC_FRMT_ST1 | \
+ RADEON_CP_VC_FRMT_Q1)
+
+#define TEX2_VERTEX_FORMAT 0
+#define TEX3_VERTEX_FORMAT 0
+#define PROJ_TEX3_VERTEX_FORMAT 0
+
+#define DO_XYZW (IND & RADEON_XYZW_BIT)
+#define DO_RGBA (IND & RADEON_RGBA_BIT)
+#define DO_SPEC (IND & RADEON_SPEC_BIT)
+#define DO_FOG (IND & RADEON_SPEC_BIT)
+#define DO_TEX0 (IND & RADEON_TEX0_BIT)
+#define DO_TEX1 (IND & RADEON_TEX1_BIT)
+#define DO_TEX2 0
+#define DO_TEX3 0
+#define DO_PTEX (IND & RADEON_PTEX_BIT)
+
+#define VERTEX radeonVertex
+#define VERTEX_COLOR radeon_color_t
+#define GET_VIEWPORT_MAT() 0
+#define GET_TEXSOURCE(n) n
+#define GET_VERTEX_FORMAT() RADEON_CONTEXT(ctx)->swtcl.vertex_format
+#define GET_VERTEX_STORE() RADEON_CONTEXT(ctx)->swtcl.verts
+#define GET_VERTEX_STRIDE_SHIFT() RADEON_CONTEXT(ctx)->swtcl.vertex_stride_shift
+#define GET_UBYTE_COLOR_STORE() &RADEON_CONTEXT(ctx)->UbyteColor
+#define GET_UBYTE_SPEC_COLOR_STORE() &RADEON_CONTEXT(ctx)->UbyteSecondaryColor
+
+#define HAVE_HW_VIEWPORT 1
+/* Tiny vertices don't seem to work atm - haven't looked into why.
+ */
+#define HAVE_HW_DIVIDE (IND & ~(RADEON_XYZW_BIT|RADEON_RGBA_BIT))
+#define HAVE_TINY_VERTICES 1
+#define HAVE_RGBA_COLOR 1
+#define HAVE_NOTEX_VERTICES 1
+#define HAVE_TEX0_VERTICES 1
+#define HAVE_TEX1_VERTICES 1
+#define HAVE_TEX2_VERTICES 0
+#define HAVE_TEX3_VERTICES 0
+#define HAVE_PTEX_VERTICES 1
+
+#define CHECK_HW_DIVIDE (!(ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE| \
+ DD_TRI_UNFILLED)))
+
+#define IMPORT_QUALIFIER
+#define IMPORT_FLOAT_COLORS radeon_import_float_colors
+#define IMPORT_FLOAT_SPEC_COLORS radeon_import_float_spec_colors
+
+#define INTERP_VERTEX setup_tab[RADEON_CONTEXT(ctx)->swtcl.SetupIndex].interp
+#define COPY_PV_VERTEX setup_tab[RADEON_CONTEXT(ctx)->swtcl.SetupIndex].copy_pv
+
+
+/***********************************************************************
+ * Generate pv-copying and translation functions *
+ ***********************************************************************/
+
+#define TAG(x) radeon_##x
+#define IND ~0
+#include "tnl_dd/t_dd_vb.c"
+#undef IND
+
+
+/***********************************************************************
+ * Generate vertex emit and interp functions *
+ ***********************************************************************/
+
+#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT)
+#define TAG(x) x##_wg
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_TEX0_BIT)
+#define TAG(x) x##_wgt0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_TEX0_BIT|RADEON_PTEX_BIT)
+#define TAG(x) x##_wgpt0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_TEX0_BIT|RADEON_TEX1_BIT)
+#define TAG(x) x##_wgt0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_TEX0_BIT|RADEON_TEX1_BIT|\
+ RADEON_PTEX_BIT)
+#define TAG(x) x##_wgpt0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_SPEC_BIT)
+#define TAG(x) x##_wgfs
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_SPEC_BIT|\
+ RADEON_TEX0_BIT)
+#define TAG(x) x##_wgfst0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_SPEC_BIT|\
+ RADEON_TEX0_BIT|RADEON_PTEX_BIT)
+#define TAG(x) x##_wgfspt0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_SPEC_BIT|\
+ RADEON_TEX0_BIT|RADEON_TEX1_BIT)
+#define TAG(x) x##_wgfst0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_SPEC_BIT|\
+ RADEON_TEX0_BIT|RADEON_TEX1_BIT|RADEON_PTEX_BIT)
+#define TAG(x) x##_wgfspt0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+
+/***********************************************************************
+ * Initialization
+ ***********************************************************************/
+
+static void init_setup_tab( void )
+{
+ init_wg();
+ init_wgt0();
+ init_wgpt0();
+ init_wgt0t1();
+ init_wgpt0t1();
+ init_wgfs();
+ init_wgfst0();
+ init_wgfspt0();
+ init_wgfst0t1();
+ init_wgfspt0t1();
+}
+
+
+
+void radeonPrintSetupFlags(char *msg, GLuint flags )
+{
+ fprintf(stderr, "%s(%x): %s%s%s%s%s%s\n",
+ msg,
+ (int)flags,
+ (flags & RADEON_XYZW_BIT) ? " xyzw," : "",
+ (flags & RADEON_RGBA_BIT) ? " rgba," : "",
+ (flags & RADEON_SPEC_BIT) ? " spec/fog," : "",
+ (flags & RADEON_TEX0_BIT) ? " tex-0," : "",
+ (flags & RADEON_TEX1_BIT) ? " tex-1," : "",
+ (flags & RADEON_PTEX_BIT) ? " proj-tex," : "");
+}
+
+
+static void radeonRenderStart( GLcontext *ctx )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+
+ if (!setup_tab[rmesa->swtcl.SetupIndex].check_tex_sizes(ctx)) {
+ GLuint ind = rmesa->swtcl.SetupIndex |= (RADEON_PTEX_BIT|RADEON_RGBA_BIT);
+
+ /* Projective textures are handled nicely; just have to change
+ * up to the new vertex format.
+ */
+ if (setup_tab[ind].vertex_format != rmesa->swtcl.vertex_format) {
+ RADEON_NEWPRIM(rmesa);
+ rmesa->swtcl.vertex_format = setup_tab[ind].vertex_format;
+ rmesa->swtcl.vertex_size = setup_tab[ind].vertex_size;
+ rmesa->swtcl.vertex_stride_shift = setup_tab[ind].vertex_stride_shift;
+ }
+
+ if (!(ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
+ tnl->Driver.Render.Interp = setup_tab[rmesa->swtcl.SetupIndex].interp;
+ tnl->Driver.Render.CopyPV = setup_tab[rmesa->swtcl.SetupIndex].copy_pv;
+ }
+ }
+
+ if (rmesa->dma.flush != 0 &&
+ rmesa->dma.flush != flush_last_swtcl_prim_compat &&
+ rmesa->dma.flush != flush_last_swtcl_prim)
+ rmesa->dma.flush( rmesa );
+}
+
+
+void radeonBuildVertices( GLcontext *ctx, GLuint start, GLuint count,
+ GLuint newinputs )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+ GLubyte *v = ((GLubyte *)rmesa->swtcl.verts +
+ (start << rmesa->swtcl.vertex_stride_shift));
+ GLuint stride = 1 << rmesa->swtcl.vertex_stride_shift;
+
+ newinputs |= rmesa->swtcl.SetupNewInputs;
+ rmesa->swtcl.SetupNewInputs = 0;
+
+ if (!newinputs)
+ return;
+
+ setup_tab[rmesa->swtcl.SetupIndex].emit( ctx, start, count, v, stride );
+}
+
+void radeonChooseVertexState( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ GLuint ind = (RADEON_XYZW_BIT | RADEON_RGBA_BIT);
+
+ if (!rmesa->TclFallback || rmesa->Fallback)
+ return;
+
+ if (ctx->Fog.Enabled || (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR))
+ ind |= RADEON_SPEC_BIT;
+
+ if (ctx->Texture._EnabledUnits & 0x2)
+ /* unit 1 enabled */
+ ind |= RADEON_TEX0_BIT|RADEON_TEX1_BIT;
+ else if (ctx->Texture._EnabledUnits & 0x1)
+ /* unit 0 enabled */
+ ind |= RADEON_TEX0_BIT;
+
+ rmesa->swtcl.SetupIndex = ind;
+
+ if (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED)) {
+ tnl->Driver.Render.Interp = radeon_interp_extras;
+ tnl->Driver.Render.CopyPV = radeon_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 != rmesa->swtcl.vertex_format) {
+ RADEON_NEWPRIM(rmesa);
+ rmesa->swtcl.vertex_format = setup_tab[ind].vertex_format;
+ rmesa->swtcl.vertex_size = setup_tab[ind].vertex_size;
+ rmesa->swtcl.vertex_stride_shift = setup_tab[ind].vertex_stride_shift;
+ }
+
+ {
+ GLuint se_coord_fmt, needproj;
+
+ /* HW perspective divide is a win, but tiny vertex formats are a
+ * bigger one.
+ */
+ if (setup_tab[ind].vertex_format == TINY_VERTEX_FORMAT ||
+ (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
+ needproj = GL_TRUE;
+ se_coord_fmt = (RADEON_VTX_XY_PRE_MULT_1_OVER_W0 |
+ RADEON_VTX_Z_PRE_MULT_1_OVER_W0 |
+ RADEON_TEX1_W_ROUTING_USE_Q1);
+ }
+ else {
+ needproj = GL_FALSE;
+ se_coord_fmt = (RADEON_VTX_W0_IS_NOT_1_OVER_W0 |
+ RADEON_TEX1_W_ROUTING_USE_Q1);
+ }
+
+ if ( se_coord_fmt != rmesa->hw.set.cmd[SET_SE_COORDFMT] ) {
+ RADEON_STATECHANGE( rmesa, set );
+ rmesa->hw.set.cmd[SET_SE_COORDFMT] = se_coord_fmt;
+ }
+ _tnl_need_projected_coords( ctx, needproj );
+ }
+}
+
+
+/* Flush vertices in the current dma region.
+ */
+static void flush_last_swtcl_prim( radeonContextPtr rmesa )
+{
+ if (RADEON_DEBUG & DEBUG_IOCTL)
+ fprintf(stderr, "%s\n", __FUNCTION__);
+
+ rmesa->dma.flush = 0;
+
+ if (rmesa->dma.current.buf) {
+ struct radeon_dma_region *current = &rmesa->dma.current;
+ GLuint current_offset = (rmesa->radeonScreen->agp_buffer_offset +
+ current->buf->buf->idx * RADEON_BUFFER_SIZE +
+ current->start);
+
+ assert (!(rmesa->swtcl.hw_primitive & RADEON_CP_VC_CNTL_PRIM_WALK_IND));
+
+ assert (current->start +
+ rmesa->swtcl.numverts * rmesa->swtcl.vertex_size * 4 ==
+ current->ptr);
+
+ if (rmesa->dma.current.start != rmesa->dma.current.ptr) {
+ radeonEmitVertexAOS( rmesa,
+ rmesa->swtcl.vertex_size,
+ current_offset);
+
+ radeonEmitVbufPrim( rmesa,
+ rmesa->swtcl.vertex_format,
+ rmesa->swtcl.hw_primitive,
+ rmesa->swtcl.numverts);
+ }
+
+ rmesa->swtcl.numverts = 0;
+ current->start = current->ptr;
+ }
+}
+
+
+static void flush_last_swtcl_prim_compat( radeonContextPtr rmesa )
+{
+ struct radeon_dma_region *current = &rmesa->dma.current;
+
+ if (RADEON_DEBUG & DEBUG_IOCTL)
+ fprintf(stderr, "%s buf %p start %d ptr %d\n",
+ __FUNCTION__,
+ current->buf,
+ current->start,
+ current->ptr);
+
+ assert (!(rmesa->swtcl.hw_primitive & RADEON_CP_VC_CNTL_PRIM_WALK_IND));
+ assert (current->start +
+ rmesa->swtcl.numverts * rmesa->swtcl.vertex_size * 4 ==
+ current->ptr);
+ assert (current->start == 0);
+
+ rmesa->dma.flush = 0;
+
+ if (current->ptr && current->buf) {
+ assert (current->buf->refcount == 1);
+
+ radeonCompatEmitPrimitive( rmesa,
+ rmesa->swtcl.vertex_format,
+ rmesa->swtcl.hw_primitive,
+ rmesa->swtcl.numverts);
+
+ /* The buffer has been released:
+ */
+ FREE(current->buf);
+ current->buf = 0;
+ current->start = 0;
+ current->ptr = current->end;
+
+ }
+
+ rmesa->swtcl.numverts = 0;
+}
+
+
+/* Alloc space in the current dma region.
+ */
+static __inline void *radeonAllocDmaLowVerts( radeonContextPtr rmesa,
+ int nverts, int vsize )
+{
+ GLuint bytes = vsize * nverts;
+
+ if ( rmesa->dma.current.ptr + bytes > rmesa->dma.current.end )
+ radeonRefillCurrentDmaRegion( rmesa );
+
+ if (!rmesa->dma.flush) {
+ rmesa->glCtx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
+ if (rmesa->dri.drmMinor == 1)
+ rmesa->dma.flush = flush_last_swtcl_prim_compat;
+ else
+ rmesa->dma.flush = flush_last_swtcl_prim;
+ }
+
+ assert( vsize == rmesa->swtcl.vertex_size * 4 );
+ assert( rmesa->dma.flush == flush_last_swtcl_prim ||
+ rmesa->dma.flush == flush_last_swtcl_prim_compat);
+ assert (rmesa->dma.current.start +
+ rmesa->swtcl.numverts * rmesa->swtcl.vertex_size * 4 ==
+ rmesa->dma.current.ptr);
+
+
+ {
+ char *head = rmesa->dma.current.address + rmesa->dma.current.ptr;
+ rmesa->dma.current.ptr += bytes;
+ rmesa->swtcl.numverts += nverts;
+ return head;
+ }
+
+}
+
+
+
+
+void radeon_emit_contiguous_verts( GLcontext *ctx, GLuint start, GLuint count )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLuint vertex_size = rmesa->swtcl.vertex_size * 4;
+ CARD32 *dest = radeonAllocDmaLowVerts( rmesa, count-start, vertex_size );
+ setup_tab[rmesa->swtcl.SetupIndex].emit( ctx, start, count, dest,
+ vertex_size );
+}
+
+
+
+void radeon_emit_indexed_verts( GLcontext *ctx, GLuint start, GLuint count )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ radeonAllocDmaRegionVerts( rmesa,
+ &rmesa->swtcl.indexed_verts,
+ count - start,
+ rmesa->swtcl.vertex_size * 4,
+ 64);
+
+ setup_tab[rmesa->swtcl.SetupIndex].emit(
+ ctx, start, count,
+ rmesa->swtcl.indexed_verts.address + rmesa->swtcl.indexed_verts.start,
+ rmesa->swtcl.vertex_size * 4 );
+}
+
+
+/*
+ * Render unclipped vertex buffers by emitting vertices directly to
+ * dma buffers. Use strip/fan hardware primitives where possible.
+ * Try to simulate missing primitives with indexed vertices.
+ */
+#define HAVE_POINTS 1
+#define HAVE_LINES 1
+#define HAVE_LINE_STRIPS 1
+#define HAVE_TRIANGLES 1
+#define HAVE_TRI_STRIPS 1
+#define HAVE_TRI_STRIP_1 0
+#define HAVE_TRI_FANS 1
+#define HAVE_QUADS 0
+#define HAVE_QUAD_STRIPS 0
+#define HAVE_POLYGONS 0
+#define HAVE_ELTS 1
+
+static const GLuint hw_prim[GL_POLYGON+1] = {
+ RADEON_CP_VC_CNTL_PRIM_TYPE_POINT,
+ RADEON_CP_VC_CNTL_PRIM_TYPE_LINE,
+ 0,
+ RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP,
+ RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST,
+ RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP,
+ RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN,
+ 0,
+ 0,
+ 0
+};
+
+static __inline void radeonDmaPrimitive( radeonContextPtr rmesa, GLenum prim )
+{
+ RADEON_NEWPRIM( rmesa );
+ rmesa->swtcl.hw_primitive = hw_prim[prim];
+ assert(rmesa->dma.current.ptr == rmesa->dma.current.start);
+}
+
+static __inline void radeonEltPrimitive( radeonContextPtr rmesa, GLenum prim )
+{
+ RADEON_NEWPRIM( rmesa );
+ rmesa->swtcl.hw_primitive = hw_prim[prim] | RADEON_CP_VC_CNTL_PRIM_WALK_IND;
+}
+
+
+static void VERT_FALLBACK( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ tnl->Driver.Render.PrimitiveNotify( ctx, flags & PRIM_MODE_MASK );
+ tnl->Driver.Render.BuildVertices( ctx, start, count, ~0 );
+ tnl->Driver.Render.PrimTabVerts[flags&PRIM_MODE_MASK]( ctx, start, count, flags );
+ RADEON_CONTEXT(ctx)->swtcl.SetupNewInputs = VERT_BIT_CLIP;
+}
+
+static void ELT_FALLBACK( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ tnl->Driver.Render.PrimitiveNotify( ctx, flags & PRIM_MODE_MASK );
+ tnl->Driver.Render.BuildVertices( ctx, start, count, ~0 );
+ tnl->Driver.Render.PrimTabElts[flags&PRIM_MODE_MASK]( ctx, start, count, flags );
+ RADEON_CONTEXT(ctx)->swtcl.SetupNewInputs = VERT_BIT_CLIP;
+}
+
+
+#define LOCAL_VARS radeonContextPtr rmesa = RADEON_CONTEXT(ctx)
+#define ELTS_VARS GLushort *dest
+#define INIT( prim ) radeonDmaPrimitive( rmesa, prim )
+#define ELT_INIT(prim) radeonEltPrimitive( rmesa, prim )
+#define NEW_PRIMITIVE() RADEON_NEWPRIM( rmesa )
+#define NEW_BUFFER() radeonRefillCurrentDmaRegion( rmesa )
+#define GET_CURRENT_VB_MAX_VERTS() \
+ (((int)rmesa->dma.current.end - (int)rmesa->dma.current.ptr) / (rmesa->swtcl.vertex_size*4))
+#define GET_SUBSEQUENT_VB_MAX_VERTS() \
+ ((RADEON_BUFFER_SIZE) / (rmesa->swtcl.vertex_size*4))
+
+#if RADEON_OLD_PACKETS
+# define GET_CURRENT_VB_MAX_ELTS() \
+ ((RADEON_CMD_BUF_SZ - (rmesa->store.cmd_used + 24)) / 2)
+#else
+# define GET_CURRENT_VB_MAX_ELTS() \
+ ((RADEON_CMD_BUF_SZ - (rmesa->store.cmd_used + 16)) / 2)
+#endif
+#define GET_SUBSEQUENT_VB_MAX_ELTS() \
+ ((RADEON_CMD_BUF_SZ - 1024) / 2)
+
+
+
+/* How do you extend an existing primitive?
+ */
+#define ALLOC_ELTS(nr) \
+do { \
+ if (rmesa->dma.flush == radeonFlushElts && \
+ rmesa->store.cmd_used + nr*2 < RADEON_CMD_BUF_SZ) { \
+ \
+ dest = (GLushort *)(rmesa->store.cmd_buf + \
+ rmesa->store.cmd_used); \
+ rmesa->store.cmd_used += nr*2; \
+ } \
+ else { \
+ if (rmesa->dma.flush) { \
+ rmesa->dma.flush( rmesa ); \
+ } \
+ \
+ radeonEmitVertexAOS( rmesa, \
+ rmesa->swtcl.vertex_size, \
+ (rmesa->radeonScreen->agp_buffer_offset + \
+ rmesa->swtcl.indexed_verts.buf->buf->idx * \
+ RADEON_BUFFER_SIZE + \
+ rmesa->swtcl.indexed_verts.start)); \
+ \
+ dest = radeonAllocEltsOpenEnded( rmesa, \
+ rmesa->swtcl.vertex_format, \
+ rmesa->swtcl.hw_primitive, \
+ nr ); \
+ } \
+} while (0)
+
+#define ALLOC_ELTS_NEW_PRIMITIVE(nr) ALLOC_ELTS( nr )
+
+#ifdef MESA_BIG_ENDIAN
+/* We could do without (most of) this ugliness if dest was always 32 bit word aligned... */
+#define EMIT_ELT(offset, x) do { \
+ int off = offset + ( ( (GLuint)dest & 0x2 ) >> 1 ); \
+ GLushort *des = (GLushort *)( (GLuint)dest & ~0x2 ); \
+ (des)[ off + 1 - 2 * ( off & 1 ) ] = (GLushort)(x); } while (0)
+#else
+#define EMIT_ELT(offset, x) (dest)[offset] = (GLushort) (x)
+#endif
+#define EMIT_TWO_ELTS(offset, x, y) *(GLuint *)(dest+offset) = ((y)<<16)|(x);
+#define INCR_ELTS( nr ) dest += nr
+#define RELEASE_ELT_VERTS() \
+ radeonReleaseDmaRegion( rmesa, &rmesa->swtcl.indexed_verts, __FUNCTION__ )
+#define EMIT_VERTS( ctx, j, nr ) \
+ radeon_emit_contiguous_verts(ctx, j, (j)+(nr))
+#define EMIT_INDEXED_VERTS( ctx, start, count ) \
+ radeon_emit_indexed_verts( ctx, start, count )
+
+
+#define TAG(x) radeon_dma_##x
+#include "tnl_dd/t_dd_dmatmp.h"
+
+
+/**********************************************************************/
+/* Render pipeline stage */
+/**********************************************************************/
+
+
+static GLboolean radeon_run_render( GLcontext *ctx,
+ struct gl_pipeline_stage *stage )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ GLuint i, length, flags = 0;
+ render_func *tab = TAG(render_tab_verts);
+
+ if (rmesa->swtcl.indexed_verts.buf && (!VB->Elts || stage->changed_inputs))
+ RELEASE_ELT_VERTS();
+
+ if (VB->ClipOrMask || /* No clipping */
+ rmesa->swtcl.RenderIndex != 0 || /* No per-vertex manipulations */
+ ctx->Line.StippleFlag) /* GH: THIS IS A HACK!!! */
+ return GL_TRUE;
+
+ if (rmesa->dri.drmMinor < 3) {
+ /* drm 1.1 doesn't support vertex primitives starting in the
+ * middle of a buffer. It doesn't support sane indexed vertices
+ * either. drm 1.2 fixes both of these problems, but we don't have a
+ * compatibility layer to that version yet.
+ */
+ return GL_TRUE;
+ }
+
+ tnl->Driver.Render.Start( ctx );
+
+ if (VB->Elts) {
+ tab = TAG(render_tab_elts);
+ if (!rmesa->swtcl.indexed_verts.buf)
+ if (!TAG(emit_elt_verts)(ctx, 0, VB->Count))
+ return GL_TRUE; /* too many vertices */
+ }
+
+ for (i = 0 ; !(flags & PRIM_LAST) ; i += length)
+ {
+ flags = VB->Primitive[i];
+ length = VB->PrimitiveLength[i];
+
+ if (RADEON_DEBUG & DEBUG_PRIMS)
+ fprintf(stderr, "radeon_render.c: prim %s %d..%d\n",
+ _mesa_lookup_enum_by_nr(flags & PRIM_MODE_MASK),
+ i, i+length);
+
+ if (length)
+ tab[flags & PRIM_MODE_MASK]( ctx, i, i + length, flags );
+ }
+
+ tnl->Driver.Render.Finish( ctx );
+
+ return GL_FALSE; /* finished the pipe */
+}
+
+
+
+static void radeon_check_render( GLcontext *ctx,
+ struct gl_pipeline_stage *stage )
+{
+ GLuint inputs = VERT_BIT_POS | VERT_BIT_CLIP | VERT_BIT_COLOR0;
+
+ if (ctx->RenderMode == GL_RENDER) {
+ if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)
+ inputs |= VERT_BIT_COLOR1;
+
+ if (ctx->Texture.Unit[0]._ReallyEnabled)
+ inputs |= VERT_BIT_TEX0;
+
+ if (ctx->Texture.Unit[1]._ReallyEnabled)
+ inputs |= VERT_BIT_TEX1;
+
+ if (ctx->Fog.Enabled)
+ inputs |= VERT_BIT_FOG;
+ }
+
+ stage->inputs = inputs;
+}
+
+
+static void dtr( struct gl_pipeline_stage *stage )
+{
+ (void)stage;
+}
+
+
+const struct gl_pipeline_stage _radeon_render_stage =
+{
+ "radeon render",
+ (_DD_NEW_SEPARATE_SPECULAR |
+ _NEW_TEXTURE|
+ _NEW_FOG|
+ _NEW_RENDERMODE), /* re-check (new inputs) */
+ 0, /* re-run (always runs) */
+ GL_TRUE, /* active */
+ 0, 0, /* inputs (set in check_render), outputs */
+ 0, 0, /* changed_inputs, private */
+ dtr, /* destructor */
+ radeon_check_render, /* check - initially set to alloc data */
+ radeon_run_render /* run */
+};
+
+
+/**************************************************************************/
+
+/* Radeon texture rectangle expects coords in 0..1 range, not 0..dimension
+ * as in the extension spec. Need to translate here.
+ *
+ * Note that swrast expects 0..dimension, so if a fallback is active,
+ * don't do anything. (Maybe need to configure swrast to match hw)
+ */
+struct texrect_stage_data {
+ GLvector4f texcoord[MAX_TEXTURE_UNITS];
+};
+
+#define TEXRECT_STAGE_DATA(stage) ((struct texrect_stage_data *)stage->privatePtr)
+
+
+static GLboolean run_texrect_stage( GLcontext *ctx,
+ struct gl_pipeline_stage *stage )
+{
+ struct texrect_stage_data *store = TEXRECT_STAGE_DATA(stage);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ GLuint i;
+
+ if (rmesa->Fallback)
+ return GL_TRUE;
+
+ for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) {
+ if (!(ctx->Texture.Unit[i]._ReallyEnabled & TEXTURE_RECT_BIT))
+ continue;
+
+ if (stage->changed_inputs & VERT_BIT_TEX(i)) {
+ struct gl_texture_object *texObj = ctx->Texture.Unit[i].CurrentRect;
+ struct gl_texture_image *texImage = texObj->Image[texObj->BaseLevel];
+ const GLfloat iw = 1.0/texImage->Width;
+ const GLfloat ih = 1.0/texImage->Height;
+ GLfloat *in = (GLfloat *)VB->TexCoordPtr[i]->data;
+ GLint instride = VB->TexCoordPtr[i]->stride;
+ GLfloat (*out)[4] = store->texcoord[i].data;
+ GLint j;
+
+ for (j = 0 ; j < VB->Count ; j++) {
+ out[j][0] = in[0] * iw;
+ out[j][1] = in[1] * ih;
+ in = (GLfloat *)((GLubyte *)in + instride);
+ }
+ }
+
+ VB->TexCoordPtr[i] = &store->texcoord[i];
+ }
+
+ return GL_TRUE;
+}
+
+
+/* Called the first time stage->run() is invoked.
+ */
+static GLboolean alloc_texrect_data( GLcontext *ctx,
+ struct gl_pipeline_stage *stage )
+{
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ struct texrect_stage_data *store;
+ GLuint i;
+
+ stage->privatePtr = CALLOC(sizeof(*store));
+ store = TEXRECT_STAGE_DATA(stage);
+ if (!store)
+ return GL_FALSE;
+
+ for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++)
+ _mesa_vector4f_alloc( &store->texcoord[i], 0, VB->Size, 32 );
+
+ /* Now run the stage.
+ */
+ stage->run = run_texrect_stage;
+ return stage->run( ctx, stage );
+}
+
+
+static void check_texrect( GLcontext *ctx,
+ struct gl_pipeline_stage *stage )
+{
+ GLuint flags = 0;
+
+ if (ctx->Texture.Unit[0]._ReallyEnabled & TEXTURE_RECT_BIT)
+ flags |= VERT_BIT_TEX0;
+
+ if (ctx->Texture.Unit[1]._ReallyEnabled & TEXTURE_RECT_BIT)
+ flags |= VERT_BIT_TEX1;
+
+ stage->inputs = flags;
+ stage->outputs = flags;
+ stage->active = (flags != 0);
+}
+
+
+static void free_texrect_data( struct gl_pipeline_stage *stage )
+{
+ struct texrect_stage_data *store = TEXRECT_STAGE_DATA(stage);
+ GLuint i;
+
+ if (store) {
+ for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++)
+ if (store->texcoord[i].data)
+ _mesa_vector4f_free( &store->texcoord[i] );
+ FREE( store );
+ stage->privatePtr = 0;
+ }
+}
+
+
+const struct gl_pipeline_stage _radeon_texrect_stage =
+{
+ "radeon texrect stage", /* name */
+ _NEW_TEXTURE, /* check_state */
+ _NEW_TEXTURE, /* run_state */
+ GL_TRUE, /* active? */
+ 0, /* inputs */
+ 0, /* outputs */
+ 0, /* changed_inputs */
+ NULL, /* private data */
+ free_texrect_data, /* destructor */
+ check_texrect, /* check */
+ alloc_texrect_data, /* run -- initially set to init */
+};
+
+
+/**************************************************************************/
+
+
+static const GLuint reduced_hw_prim[GL_POLYGON+1] = {
+ RADEON_CP_VC_CNTL_PRIM_TYPE_POINT,
+ RADEON_CP_VC_CNTL_PRIM_TYPE_LINE,
+ RADEON_CP_VC_CNTL_PRIM_TYPE_LINE,
+ RADEON_CP_VC_CNTL_PRIM_TYPE_LINE,
+ RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST,
+ RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST,
+ RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST,
+ RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST,
+ RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST,
+ RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST
+};
+
+static void radeonRasterPrimitive( GLcontext *ctx, GLuint hwprim );
+static void radeonRenderPrimitive( GLcontext *ctx, GLenum prim );
+static void radeonResetLineStipple( GLcontext *ctx );
+
+
+/***********************************************************************
+ * Emit primitives as inline vertices *
+ ***********************************************************************/
+
+#undef LOCAL_VARS
+#define CTX_ARG radeonContextPtr rmesa
+#define CTX_ARG2 rmesa
+#define GET_VERTEX_DWORDS() rmesa->swtcl.vertex_size
+#define ALLOC_VERTS( n, size ) radeonAllocDmaLowVerts( rmesa, n, size * 4 )
+#undef LOCAL_VARS
+#define LOCAL_VARS \
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \
+ const GLuint shift = rmesa->swtcl.vertex_stride_shift; \
+ const char *radeonverts = (char *)rmesa->swtcl.verts;
+#define VERT(x) (radeonVertex *)(radeonverts + (x << shift))
+#define VERTEX radeonVertex
+#undef TAG
+#define TAG(x) radeon_##x
+#include "tnl_dd/t_dd_triemit.h"
+
+
+/***********************************************************************
+ * Macros for t_dd_tritmp.h to draw basic primitives *
+ ***********************************************************************/
+
+#define QUAD( a, b, c, d ) radeon_quad( rmesa, a, b, c, d )
+#define TRI( a, b, c ) radeon_triangle( rmesa, a, b, c )
+#define LINE( a, b ) radeon_line( rmesa, a, b )
+#define POINT( a ) radeon_point( rmesa, a )
+
+/***********************************************************************
+ * Build render functions from dd templates *
+ ***********************************************************************/
+
+#define RADEON_TWOSIDE_BIT 0x01
+#define RADEON_UNFILLED_BIT 0x02
+#define RADEON_OFFSET_BIT 0x04 /* drmMinor == 1 */
+#define RADEON_MAX_TRIFUNC 0x08
+
+
+static struct {
+ points_func points;
+ line_func line;
+ triangle_func triangle;
+ quad_func quad;
+} rast_tab[RADEON_MAX_TRIFUNC];
+
+
+#define DO_FALLBACK 0
+#define DO_OFFSET (IND & RADEON_OFFSET_BIT)
+#define DO_UNFILLED (IND & RADEON_UNFILLED_BIT)
+#define DO_TWOSIDE (IND & RADEON_TWOSIDE_BIT)
+#define DO_FLAT 0
+#define DO_TRI 1
+#define DO_QUAD 1
+#define DO_LINE 1
+#define DO_POINTS 1
+#define DO_FULL_QUAD 1
+
+#define HAVE_RGBA 1
+#define HAVE_SPEC 1
+#define HAVE_INDEX 0
+#define HAVE_BACK_COLORS 0
+#define HAVE_HW_FLATSHADE 1
+#define TAB rast_tab
+
+#define DEPTH_SCALE 1.0
+#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) (rmesa->swtcl.verts + (e<<rmesa->swtcl.vertex_stride_shift))
+
+#define VERT_SET_RGBA( v, c ) v->ui[coloroffset] = LE32_TO_CPU(*(GLuint *)c)
+#define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
+#define VERT_SAVE_RGBA( idx ) color[idx] = CPU_TO_LE32(v[idx]->ui[coloroffset])
+#define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = LE32_TO_CPU(color[idx])
+
+#define VERT_SET_SPEC( v0, c ) if (havespec) { \
+ v0->v.specular.red = (c)[0]; \
+ v0->v.specular.green = (c)[1]; \
+ v0->v.specular.blue = (c)[2]; }
+#define VERT_COPY_SPEC( v0, v1 ) if (havespec) { \
+ v0->v.specular.red = v1->v.specular.red; \
+ v0->v.specular.green = v1->v.specular.green; \
+ v0->v.specular.blue = v1->v.specular.blue; }
+#define VERT_SAVE_SPEC( idx ) if (havespec) spec[idx] = CPU_TO_LE32(v[idx]->ui[5])
+#define VERT_RESTORE_SPEC( idx ) if (havespec) v[idx]->ui[5] = LE32_TO_CPU(spec[idx])
+
+#undef LOCAL_VARS
+#undef TAG
+#undef INIT
+
+#define LOCAL_VARS(n) \
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \
+ GLuint color[n], spec[n]; \
+ GLuint coloroffset = (rmesa->swtcl.vertex_size == 4 ? 3 : 4); \
+ GLboolean havespec = (rmesa->swtcl.vertex_size > 4); \
+ (void) color; (void) spec; (void) coloroffset; (void) havespec;
+
+/***********************************************************************
+ * Helpers for rendering unfilled primitives *
+ ***********************************************************************/
+
+#define RASTERIZE(x) radeonRasterPrimitive( ctx, reduced_hw_prim[x] )
+#define RENDER_PRIMITIVE rmesa->swtcl.render_primitive
+#undef TAG
+#define TAG(x) x
+#include "tnl_dd/t_dd_unfilled.h"
+#undef IND
+
+
+/***********************************************************************
+ * Generate GL render functions *
+ ***********************************************************************/
+
+
+#define IND (0)
+#define TAG(x) x
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (RADEON_TWOSIDE_BIT)
+#define TAG(x) x##_twoside
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (RADEON_UNFILLED_BIT)
+#define TAG(x) x##_unfilled
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (RADEON_TWOSIDE_BIT|RADEON_UNFILLED_BIT)
+#define TAG(x) x##_twoside_unfilled
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (RADEON_OFFSET_BIT)
+#define TAG(x) x##_offset
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (RADEON_TWOSIDE_BIT|RADEON_OFFSET_BIT)
+#define TAG(x) x##_twoside_offset
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (RADEON_UNFILLED_BIT|RADEON_OFFSET_BIT)
+#define TAG(x) x##_unfilled_offset
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (RADEON_TWOSIDE_BIT|RADEON_UNFILLED_BIT|RADEON_OFFSET_BIT)
+#define TAG(x) x##_twoside_unfilled_offset
+#include "tnl_dd/t_dd_tritmp.h"
+
+
+static void init_rast_tab( void )
+{
+ init();
+ init_twoside();
+ init_unfilled();
+ init_twoside_unfilled();
+ init_offset();
+ init_twoside_offset();
+ init_unfilled_offset();
+ init_twoside_unfilled_offset();
+}
+
+/**********************************************************************/
+/* Render unclipped begin/end objects */
+/**********************************************************************/
+
+#define VERT(x) (radeonVertex *)(radeonverts + (x << shift))
+#define RENDER_POINTS( start, count ) \
+ for ( ; start < count ; start++) \
+ radeon_point( rmesa, VERT(start) )
+#define RENDER_LINE( v0, v1 ) \
+ radeon_line( rmesa, VERT(v0), VERT(v1) )
+#define RENDER_TRI( v0, v1, v2 ) \
+ radeon_triangle( rmesa, VERT(v0), VERT(v1), VERT(v2) )
+#define RENDER_QUAD( v0, v1, v2, v3 ) \
+ radeon_quad( rmesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
+#undef INIT
+#define INIT(x) do { \
+ radeonRenderPrimitive( ctx, x ); \
+} while (0)
+#undef LOCAL_VARS
+#define LOCAL_VARS \
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \
+ const GLuint shift = rmesa->swtcl.vertex_stride_shift; \
+ const char *radeonverts = (char *)rmesa->swtcl.verts; \
+ const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
+ const GLboolean stipple = ctx->Line.StippleFlag; \
+ (void) elt; (void) stipple;
+#define RESET_STIPPLE if ( stipple ) radeonResetLineStipple( ctx );
+#define RESET_OCCLUSION
+#define PRESERVE_VB_DEFS
+#define ELT(x) (x)
+#define TAG(x) radeon_##x##_verts
+#include "tnl/t_vb_rendertmp.h"
+#undef ELT
+#undef TAG
+#define TAG(x) radeon_##x##_elts
+#define ELT(x) elt[x]
+#include "tnl/t_vb_rendertmp.h"
+
+
+
+/**********************************************************************/
+/* Choose render functions */
+/**********************************************************************/
+
+void radeonChooseRenderState( GLcontext *ctx )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLuint index = 0;
+ GLuint flags = ctx->_TriangleCaps;
+
+ if (!rmesa->TclFallback || rmesa->Fallback)
+ return;
+
+ if (flags & DD_TRI_LIGHT_TWOSIDE) index |= RADEON_TWOSIDE_BIT;
+ if (flags & DD_TRI_UNFILLED) index |= RADEON_UNFILLED_BIT;
+ if ((flags & DD_TRI_OFFSET) &&
+ rmesa->dri.drmMinor == 1) index |= RADEON_OFFSET_BIT;
+
+ if (index != rmesa->swtcl.RenderIndex) {
+ tnl->Driver.Render.Points = rast_tab[index].points;
+ tnl->Driver.Render.Line = rast_tab[index].line;
+ tnl->Driver.Render.ClippedLine = rast_tab[index].line;
+ tnl->Driver.Render.Triangle = rast_tab[index].triangle;
+ tnl->Driver.Render.Quad = rast_tab[index].quad;
+
+ if (index == 0) {
+ tnl->Driver.Render.PrimTabVerts = radeon_render_tab_verts;
+ tnl->Driver.Render.PrimTabElts = radeon_render_tab_elts;
+ tnl->Driver.Render.ClippedPolygon = radeon_fast_clipped_poly;
+ } else {
+ tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
+ tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
+ tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon;
+ }
+
+ rmesa->swtcl.RenderIndex = index;
+ }
+}
+
+
+/**********************************************************************/
+/* High level hooks for t_vb_render.c */
+/**********************************************************************/
+
+
+static void radeonRasterPrimitive( GLcontext *ctx, GLuint hwprim )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ if (rmesa->swtcl.hw_primitive != hwprim) {
+ RADEON_NEWPRIM( rmesa );
+ rmesa->swtcl.hw_primitive = hwprim;
+ }
+}
+
+static void radeonRenderPrimitive( GLcontext *ctx, GLenum prim )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ rmesa->swtcl.render_primitive = prim;
+ if (prim < GL_TRIANGLES || !(ctx->_TriangleCaps & DD_TRI_UNFILLED))
+ radeonRasterPrimitive( ctx, reduced_hw_prim[prim] );
+}
+
+static void radeonRenderFinish( GLcontext *ctx )
+{
+}
+
+static void radeonResetLineStipple( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ RADEON_STATECHANGE( rmesa, lin );
+}
+
+
+/**********************************************************************/
+/* Transition to/from hardware rasterization. */
+/**********************************************************************/
+
+static const char * const fallbackStrings[] = {
+ "Texture mode",
+ "glDrawBuffer(GL_FRONT_AND_BACK)",
+ "glEnable(GL_STENCIL) without hw stencil buffer",
+ "glRenderMode(selection or feedback)",
+ "glBlendEquation",
+ "glBlendFunc",
+ "RADEON_NO_RAST",
+ "Mixing GL_CLAMP_TO_BORDER and GL_CLAMP (or GL_MIRROR_CLAMP_ATI)"
+};
+
+
+static const char *getFallbackString(GLuint bit)
+{
+ int i = 0;
+ while (bit > 1) {
+ i++;
+ bit >>= 1;
+ }
+ return fallbackStrings[i];
+}
+
+
+void radeonFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ GLuint oldfallback = rmesa->Fallback;
+
+ if (mode) {
+ rmesa->Fallback |= bit;
+ if (oldfallback == 0) {
+ RADEON_FIREVERTICES( rmesa );
+ TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_RASTER, GL_TRUE );
+ _swsetup_Wakeup( ctx );
+ _tnl_need_projected_coords( ctx, GL_TRUE );
+ rmesa->swtcl.RenderIndex = ~0;
+ if (RADEON_DEBUG & DEBUG_FALLBACKS) {
+ fprintf(stderr, "Radeon begin rasterization fallback: 0x%x %s\n",
+ bit, getFallbackString(bit));
+ }
+ }
+ }
+ else {
+ rmesa->Fallback &= ~bit;
+ if (oldfallback == bit) {
+ _swrast_flush( ctx );
+ tnl->Driver.Render.Start = radeonRenderStart;
+ tnl->Driver.Render.PrimitiveNotify = radeonRenderPrimitive;
+ tnl->Driver.Render.Finish = radeonRenderFinish;
+ tnl->Driver.Render.BuildVertices = radeonBuildVertices;
+ tnl->Driver.Render.ResetLineStipple = radeonResetLineStipple;
+ TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_RASTER, GL_FALSE );
+ if (rmesa->TclFallback) {
+ /* These are already done if rmesa->TclFallback goes to
+ * zero above. But not if it doesn't (RADEON_NO_TCL for
+ * example?)
+ */
+ radeonChooseVertexState( ctx );
+ radeonChooseRenderState( ctx );
+ }
+ if (RADEON_DEBUG & DEBUG_FALLBACKS) {
+ fprintf(stderr, "Radeon end rasterization fallback: 0x%x %s\n",
+ bit, getFallbackString(bit));
+ }
+ }
+ }
+}
+
+
+void radeonFlushVertices( GLcontext *ctx, GLuint flags )
+{
+ _tnl_flush_vertices( ctx, flags );
+
+ if (flags & FLUSH_STORED_VERTICES)
+ RADEON_NEWPRIM( RADEON_CONTEXT( ctx ) );
+}
+
+/**********************************************************************/
+/* Initialization. */
+/**********************************************************************/
+
+void radeonInitSwtcl( GLcontext *ctx )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLuint size = TNL_CONTEXT(ctx)->vb.Size;
+ static int firsttime = 1;
+
+ if (firsttime) {
+ init_rast_tab();
+ init_setup_tab();
+ firsttime = 0;
+ }
+
+ tnl->Driver.Render.Start = radeonRenderStart;
+ tnl->Driver.Render.Finish = radeonRenderFinish;
+ tnl->Driver.Render.PrimitiveNotify = radeonRenderPrimitive;
+ tnl->Driver.Render.ResetLineStipple = radeonResetLineStipple;
+ tnl->Driver.Render.BuildVertices = radeonBuildVertices;
+
+ rmesa->swtcl.verts = ALIGN_MALLOC( size * 16 * 4, 32 );
+ rmesa->swtcl.RenderIndex = ~0;
+ rmesa->swtcl.render_primitive = GL_TRIANGLES;
+ rmesa->swtcl.hw_primitive = 0;
+}
+
+
+void radeonDestroySwtcl( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ if (rmesa->swtcl.indexed_verts.buf)
+ radeonReleaseDmaRegion( rmesa, &rmesa->swtcl.indexed_verts,
+ __FUNCTION__ );
+
+ if (rmesa->swtcl.verts) {
+ ALIGN_FREE(rmesa->swtcl.verts);
+ rmesa->swtcl.verts = 0;
+ }
+
+ if (rmesa->UbyteSecondaryColor.Ptr) {
+ ALIGN_FREE(rmesa->UbyteSecondaryColor.Ptr);
+ rmesa->UbyteSecondaryColor.Ptr = 0;
+ }
+
+ if (rmesa->UbyteColor.Ptr) {
+ ALIGN_FREE(rmesa->UbyteColor.Ptr);
+ rmesa->UbyteColor.Ptr = 0;
+ }
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_swtcl.h b/src/mesa/drivers/dri/radeon/radeon_swtcl.h
new file mode 100644
index 0000000000..c45e711c0b
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_swtcl.h
@@ -0,0 +1,77 @@
+/* $XFree86$ */
+/**************************************************************************
+
+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>
+ *
+ */
+
+#ifndef __RADEON_TRIS_H__
+#define __RADEON_TRIS_H__
+
+#include "mtypes.h"
+#include "swrast/swrast.h"
+#include "radeon_context.h"
+
+extern void radeonInitSwtcl( GLcontext *ctx );
+extern void radeonDestroySwtcl( GLcontext *ctx );
+
+extern void radeonFlushVertices( GLcontext *ctx, GLuint flags );
+extern void radeonChooseRenderState( GLcontext *ctx );
+extern void radeonChooseVertexState( GLcontext *ctx );
+
+extern void radeonCheckTexSizes( GLcontext *ctx );
+
+extern void radeonBuildVertices( GLcontext *ctx, GLuint start, GLuint count,
+ GLuint newinputs );
+
+extern void radeonPrintSetupFlags(char *msg, GLuint flags );
+
+
+extern void radeon_emit_contiguous_verts( GLcontext *ctx,
+ GLuint start,
+ GLuint count );
+
+extern void radeon_emit_indexed_verts( GLcontext *ctx,
+ GLuint start,
+ GLuint count );
+
+extern void radeon_translate_vertex( GLcontext *ctx,
+ const radeonVertex *src,
+ SWvertex *dst );
+
+extern void radeon_print_vertex( GLcontext *ctx, const radeonVertex *v );
+
+extern void radeon_import_float_colors( GLcontext *ctx );
+extern void radeon_import_float_spec_colors( GLcontext *ctx );
+
+
+
+#endif
diff --git a/src/mesa/drivers/dri/radeon/radeon_tcl.c b/src/mesa/drivers/dri/radeon/radeon_tcl.c
new file mode 100644
index 0000000000..651194a804
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_tcl.c
@@ -0,0 +1,527 @@
+/* $XFree86$ */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+ Tungsten Graphics Inc., Austin, Texas.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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 "glheader.h"
+#include "imports.h"
+#include "light.h"
+#include "mtypes.h"
+#include "enums.h"
+
+#include "array_cache/acache.h"
+#include "tnl/tnl.h"
+#include "tnl/t_pipeline.h"
+
+#include "radeon_context.h"
+#include "radeon_state.h"
+#include "radeon_ioctl.h"
+#include "radeon_tex.h"
+#include "radeon_tcl.h"
+#include "radeon_swtcl.h"
+#include "radeon_maos.h"
+
+
+
+/*
+ * Render unclipped vertex buffers by emitting vertices directly to
+ * dma buffers. Use strip/fan hardware primitives where possible.
+ * Try to simulate missing primitives with indexed vertices.
+ */
+#define HAVE_POINTS 1
+#define HAVE_LINES 1
+#define HAVE_LINE_LOOP 0
+#define HAVE_LINE_STRIPS 1
+#define HAVE_TRIANGLES 1
+#define HAVE_TRI_STRIPS 1
+#define HAVE_TRI_STRIP_1 0
+#define HAVE_TRI_FANS 1
+#define HAVE_QUADS 0
+#define HAVE_QUAD_STRIPS 0
+#define HAVE_POLYGONS 1
+#define HAVE_ELTS 1
+
+
+#define HW_POINTS RADEON_CP_VC_CNTL_PRIM_TYPE_POINT
+#define HW_LINES RADEON_CP_VC_CNTL_PRIM_TYPE_LINE
+#define HW_LINE_LOOP 0
+#define HW_LINE_STRIP RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP
+#define HW_TRIANGLES RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST
+#define HW_TRIANGLE_STRIP_0 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP
+#define HW_TRIANGLE_STRIP_1 0
+#define HW_TRIANGLE_FAN RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN
+#define HW_QUADS 0
+#define HW_QUAD_STRIP 0
+#define HW_POLYGON RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN
+
+
+static GLboolean discrete_prim[0x10] = {
+ 0, /* 0 none */
+ 1, /* 1 points */
+ 1, /* 2 lines */
+ 0, /* 3 line_strip */
+ 1, /* 4 tri_list */
+ 0, /* 5 tri_fan */
+ 0, /* 6 tri_type2 */
+ 1, /* 7 rect list (unused) */
+ 1, /* 8 3vert point */
+ 1, /* 9 3vert line */
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+};
+
+
+#define LOCAL_VARS radeonContextPtr rmesa = RADEON_CONTEXT(ctx)
+#define ELT_TYPE GLushort
+
+#define ELT_INIT(prim, hw_prim) \
+ radeonTclPrimitive( ctx, prim, hw_prim | RADEON_CP_VC_CNTL_PRIM_WALK_IND )
+
+#define GET_MESA_ELTS() rmesa->tcl.Elts
+
+
+/* Don't really know how many elts will fit in what's left of cmdbuf,
+ * as there is state to emit, etc:
+ */
+
+/* Testing on isosurf shows a maximum around here. Don't know if it's
+ * the card or driver or kernel module that is causing the behaviour.
+ */
+#define GET_MAX_HW_ELTS() 300
+
+
+#define RESET_STIPPLE() do { \
+ RADEON_STATECHANGE( rmesa, lin ); \
+ radeonEmitState( rmesa ); \
+} while (0)
+
+#define AUTO_STIPPLE( mode ) do { \
+ RADEON_STATECHANGE( rmesa, lin ); \
+ if (mode) \
+ rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] |= \
+ RADEON_LINE_PATTERN_AUTO_RESET; \
+ else \
+ rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] &= \
+ ~RADEON_LINE_PATTERN_AUTO_RESET; \
+ radeonEmitState( rmesa ); \
+} while (0)
+
+
+
+#define ALLOC_ELTS(nr) radeonAllocElts( rmesa, nr )
+
+static GLushort *radeonAllocElts( radeonContextPtr rmesa, GLuint nr )
+{
+ if (rmesa->dma.flush)
+ rmesa->dma.flush( rmesa );
+
+ radeonEmitAOS( rmesa,
+ rmesa->tcl.aos_components,
+ rmesa->tcl.nr_aos_components, 0 );
+
+ return radeonAllocEltsOpenEnded( rmesa,
+ rmesa->tcl.vertex_format,
+ rmesa->tcl.hw_primitive, nr );
+}
+
+#define CLOSE_ELTS() RADEON_NEWPRIM( rmesa )
+
+
+
+/* TODO: Try to extend existing primitive if both are identical,
+ * discrete and there are no intervening state changes. (Somewhat
+ * duplicates changes to DrawArrays code)
+ */
+static void EMIT_PRIM( GLcontext *ctx,
+ GLenum prim,
+ GLuint hwprim,
+ GLuint start,
+ GLuint count)
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+ radeonTclPrimitive( ctx, prim, hwprim );
+
+ radeonEmitAOS( rmesa,
+ rmesa->tcl.aos_components,
+ rmesa->tcl.nr_aos_components,
+ start );
+
+ /* Why couldn't this packet have taken an offset param?
+ */
+ radeonEmitVbufPrim( rmesa,
+ rmesa->tcl.vertex_format,
+ rmesa->tcl.hw_primitive,
+ count - start );
+}
+
+
+
+/* Try & join small primitives
+ */
+#if 0
+#define PREFER_DISCRETE_ELT_PRIM( NR, PRIM ) 0
+#else
+#define PREFER_DISCRETE_ELT_PRIM( NR, PRIM ) \
+ ((NR) < 20 || \
+ ((NR) < 40 && \
+ rmesa->tcl.hw_primitive == (PRIM| \
+ RADEON_CP_VC_CNTL_PRIM_WALK_IND| \
+ RADEON_CP_VC_CNTL_TCL_ENABLE)))
+#endif
+
+#ifdef MESA_BIG_ENDIAN
+/* We could do without (most of) this ugliness if dest was always 32 bit word aligned... */
+#define EMIT_ELT(dest, offset, x) do { \
+ int off = offset + ( ( (GLuint)dest & 0x2 ) >> 1 ); \
+ GLushort *des = (GLushort *)( (GLuint)dest & ~0x2 ); \
+ (des)[ off + 1 - 2 * ( off & 1 ) ] = (GLushort)(x); } while (0)
+#else
+#define EMIT_ELT(dest, offset, x) (dest)[offset] = (GLushort) (x)
+#endif
+
+#define EMIT_TWO_ELTS(dest, offset, x, y) *(GLuint *)(dest+offset) = ((y)<<16)|(x);
+
+
+
+#define TAG(x) tcl_##x
+#include "tnl_dd/t_dd_dmatmp2.h"
+
+/**********************************************************************/
+/* External entrypoints */
+/**********************************************************************/
+
+void radeonEmitPrimitive( GLcontext *ctx,
+ GLuint first,
+ GLuint last,
+ GLuint flags )
+{
+ tcl_render_tab_verts[flags&PRIM_MODE_MASK]( ctx, first, last, flags );
+}
+
+void radeonEmitEltPrimitive( GLcontext *ctx,
+ GLuint first,
+ GLuint last,
+ GLuint flags )
+{
+ tcl_render_tab_elts[flags&PRIM_MODE_MASK]( ctx, first, last, flags );
+}
+
+void radeonTclPrimitive( GLcontext *ctx,
+ GLenum prim,
+ int hw_prim )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLuint se_cntl;
+ GLuint newprim = hw_prim | RADEON_CP_VC_CNTL_TCL_ENABLE;
+
+ if (newprim != rmesa->tcl.hw_primitive ||
+ !discrete_prim[hw_prim&0xf]) {
+ RADEON_NEWPRIM( rmesa );
+ rmesa->tcl.hw_primitive = newprim;
+ }
+
+ se_cntl = rmesa->hw.set.cmd[SET_SE_CNTL];
+ se_cntl &= ~RADEON_FLAT_SHADE_VTX_LAST;
+
+ if (prim == GL_POLYGON && (ctx->_TriangleCaps & DD_FLATSHADE))
+ se_cntl |= RADEON_FLAT_SHADE_VTX_0;
+ else
+ se_cntl |= RADEON_FLAT_SHADE_VTX_LAST;
+
+ if (se_cntl != rmesa->hw.set.cmd[SET_SE_CNTL]) {
+ RADEON_STATECHANGE( rmesa, set );
+ rmesa->hw.set.cmd[SET_SE_CNTL] = se_cntl;
+ }
+}
+
+
+/**********************************************************************/
+/* Render pipeline stage */
+/**********************************************************************/
+
+
+/* TCL render.
+ */
+static GLboolean radeon_run_tcl_render( GLcontext *ctx,
+ struct gl_pipeline_stage *stage )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ GLuint i,flags = 0,length;
+
+ /* TODO: separate this from the swtnl pipeline
+ */
+ if (rmesa->TclFallback)
+ return GL_TRUE; /* fallback to software t&l */
+
+ if (VB->Count == 0)
+ return GL_FALSE;
+
+ radeonReleaseArrays( ctx, stage->changed_inputs );
+ radeonEmitArrays( ctx, stage->inputs );
+
+ rmesa->tcl.Elts = VB->Elts;
+
+ for (i = VB->FirstPrimitive ; !(flags & PRIM_LAST) ; i += length)
+ {
+ flags = VB->Primitive[i];
+ length = VB->PrimitiveLength[i];
+
+ if (RADEON_DEBUG & DEBUG_PRIMS)
+ fprintf(stderr, "%s: prim %s %d..%d\n",
+ __FUNCTION__,
+ _mesa_lookup_enum_by_nr(flags & PRIM_MODE_MASK),
+ i, i+length);
+
+ if (!length)
+ continue;
+
+ if (rmesa->tcl.Elts)
+ radeonEmitEltPrimitive( ctx, i, i+length, flags );
+ else
+ radeonEmitPrimitive( ctx, i, i+length, flags );
+ }
+
+ return GL_FALSE; /* finished the pipe */
+}
+
+
+
+static void radeon_check_tcl_render( GLcontext *ctx,
+ struct gl_pipeline_stage *stage )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLuint inputs = VERT_BIT_POS;
+
+ if (ctx->RenderMode == GL_RENDER) {
+ /* Make all this event-driven:
+ */
+ if (ctx->Light.Enabled) {
+ inputs |= VERT_BIT_NORMAL;
+
+ if (1 || ctx->Light.ColorMaterialEnabled) {
+ inputs |= VERT_BIT_COLOR0;
+ }
+ }
+ else {
+ inputs |= VERT_BIT_COLOR0;
+
+ if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) {
+ inputs |= VERT_BIT_COLOR1;
+ }
+ }
+
+ if (ctx->Texture.Unit[0]._ReallyEnabled) {
+ if (ctx->Texture.Unit[0].TexGenEnabled) {
+ if (rmesa->TexGenNeedNormals[0]) {
+ inputs |= VERT_BIT_NORMAL;
+ }
+ } else {
+ inputs |= VERT_BIT_TEX0;
+ }
+ }
+
+ if (ctx->Texture.Unit[1]._ReallyEnabled) {
+ if (ctx->Texture.Unit[1].TexGenEnabled) {
+ if (rmesa->TexGenNeedNormals[1]) {
+ inputs |= VERT_BIT_NORMAL;
+ }
+ } else {
+ inputs |= VERT_BIT_TEX1;
+ }
+ }
+
+ stage->inputs = inputs;
+ stage->active = 1;
+ }
+ else
+ stage->active = 0;
+}
+
+static void radeon_init_tcl_render( GLcontext *ctx,
+ struct gl_pipeline_stage *stage )
+{
+ stage->check = radeon_check_tcl_render;
+ stage->check( ctx, stage );
+}
+
+static void dtr( struct gl_pipeline_stage *stage )
+{
+ (void)stage;
+}
+
+
+/* Initial state for tcl stage.
+ */
+const struct gl_pipeline_stage _radeon_tcl_stage =
+{
+ "radeon render",
+ (_DD_NEW_SEPARATE_SPECULAR |
+ _NEW_LIGHT|
+ _NEW_TEXTURE|
+ _NEW_FOG|
+ _NEW_RENDERMODE), /* re-check (new inputs) */
+ 0, /* re-run (always runs) */
+ GL_TRUE, /* active */
+ 0, 0, /* inputs (set in check_render), outputs */
+ 0, 0, /* changed_inputs, private */
+ dtr, /* destructor */
+ radeon_init_tcl_render, /* check - initially set to alloc data */
+ radeon_run_tcl_render /* run */
+};
+
+
+
+/**********************************************************************/
+/* Validate state at pipeline start */
+/**********************************************************************/
+
+
+/*-----------------------------------------------------------------------
+ * Manage TCL fallbacks
+ */
+
+
+static void transition_to_swtnl( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ GLuint se_cntl;
+
+ RADEON_NEWPRIM( rmesa );
+ rmesa->swtcl.vertex_format = 0;
+
+ radeonChooseVertexState( ctx );
+ radeonChooseRenderState( ctx );
+
+ _mesa_validate_all_lighting_tables( ctx );
+
+ tnl->Driver.NotifyMaterialChange =
+ _mesa_validate_all_lighting_tables;
+
+ radeonReleaseArrays( ctx, ~0 );
+
+ se_cntl = rmesa->hw.set.cmd[SET_SE_CNTL];
+ se_cntl |= RADEON_FLAT_SHADE_VTX_LAST;
+
+ if (se_cntl != rmesa->hw.set.cmd[SET_SE_CNTL]) {
+ RADEON_STATECHANGE( rmesa, set );
+ rmesa->hw.set.cmd[SET_SE_CNTL] = se_cntl;
+ }
+}
+
+
+static void transition_to_hwtnl( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ GLuint se_coord_fmt = (RADEON_VTX_W0_IS_NOT_1_OVER_W0 |
+ RADEON_TEX1_W_ROUTING_USE_Q1);
+
+ if ( se_coord_fmt != rmesa->hw.set.cmd[SET_SE_COORDFMT] ) {
+ RADEON_STATECHANGE( rmesa, set );
+ rmesa->hw.set.cmd[SET_SE_COORDFMT] = se_coord_fmt;
+ _tnl_need_projected_coords( ctx, GL_FALSE );
+ }
+
+ radeonUpdateMaterial( ctx );
+
+ tnl->Driver.NotifyMaterialChange = radeonUpdateMaterial;
+
+ if ( rmesa->dma.flush )
+ rmesa->dma.flush( rmesa );
+
+ rmesa->dma.flush = 0;
+ rmesa->swtcl.vertex_format = 0;
+
+ if (rmesa->swtcl.indexed_verts.buf)
+ radeonReleaseDmaRegion( rmesa, &rmesa->swtcl.indexed_verts,
+ __FUNCTION__ );
+
+ if (RADEON_DEBUG & DEBUG_FALLBACKS)
+ fprintf(stderr, "Radeon end tcl fallback\n");
+}
+
+static char *fallbackStrings[] = {
+ "Rasterization fallback",
+ "Unfilled triangles",
+ "Twosided lighting, differing materials",
+ "Materials in VB (maybe between begin/end)",
+ "Texgen unit 0",
+ "Texgen unit 1",
+ "Texgen unit 2",
+ "User disable"
+};
+
+
+static char *getFallbackString(GLuint bit)
+{
+ int i = 0;
+ while (bit > 1) {
+ i++;
+ bit >>= 1;
+ }
+ return fallbackStrings[i];
+}
+
+
+
+void radeonTclFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLuint oldfallback = rmesa->TclFallback;
+
+ if (mode) {
+ rmesa->TclFallback |= bit;
+ if (oldfallback == 0) {
+ if (RADEON_DEBUG & DEBUG_FALLBACKS)
+ fprintf(stderr, "Radeon begin tcl fallback %s\n",
+ getFallbackString( bit ));
+ transition_to_swtnl( ctx );
+ }
+ }
+ else {
+ rmesa->TclFallback &= ~bit;
+ if (oldfallback == bit) {
+ if (RADEON_DEBUG & DEBUG_FALLBACKS)
+ fprintf(stderr, "Radeon end tcl fallback %s\n",
+ getFallbackString( bit ));
+ transition_to_hwtnl( ctx );
+ }
+ }
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_tcl.h b/src/mesa/drivers/dri/radeon/radeon_tcl.h
new file mode 100644
index 0000000000..1e97d32148
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_tcl.h
@@ -0,0 +1,70 @@
+/* $XFree86$ */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+ Tungsten Grahpics Inc., Austin, Texas.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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 __RADEON_TCL_H__
+#define __RADEON_TCL_H__
+
+#ifdef GLX_DIRECT_RENDERING
+
+#include "radeon_context.h"
+
+extern void radeonTclPrimitive( GLcontext *ctx, GLenum prim, int hw_prim );
+extern void radeonEmitEltPrimitive( GLcontext *ctx, GLuint first, GLuint last,
+ GLuint flags );
+extern void radeonEmitPrimitive( GLcontext *ctx, GLuint first, GLuint last,
+ GLuint flags );
+
+extern void radeonTclFallback( GLcontext *ctx, GLuint bit, GLboolean mode );
+
+#define RADEON_TCL_FALLBACK_RASTER 0x1 /* rasterization */
+#define RADEON_TCL_FALLBACK_UNFILLED 0x2 /* unfilled tris */
+#define RADEON_TCL_FALLBACK_LIGHT_TWOSIDE 0x4 /* twoside tris */
+#define RADEON_TCL_FALLBACK_MATERIAL 0x8 /* material in vb */
+#define RADEON_TCL_FALLBACK_TEXGEN_0 0x10 /* texgen, unit 0 */
+#define RADEON_TCL_FALLBACK_TEXGEN_1 0x20 /* texgen, unit 1 */
+#define RADEON_TCL_FALLBACK_TEXGEN_2 0x40 /* texgen, unit 2 */
+#define RADEON_TCL_FALLBACK_TCL_DISABLE 0x80 /* user disable */
+#define RADEON_TCL_FALLBACK_TEXRECT_0 0x100 /* texture rectangle */
+#define RADEON_TCL_FALLBACK_TEXRECT_1 0x200 /* texture rectangle */
+#define RADEON_TCL_FALLBACK_TEXRECT_2 0x400 /* texture rectangle */
+
+#define RADEON_MAX_TCL_VERTSIZE (15*4)
+
+#define TCL_FALLBACK( ctx, bit, mode ) radeonTclFallback( ctx, bit, mode )
+
+
+#endif
+#endif
diff --git a/src/mesa/drivers/dri/radeon/radeon_tex.c b/src/mesa/drivers/dri/radeon/radeon_tex.c
new file mode 100644
index 0000000000..e068202c5e
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_tex.c
@@ -0,0 +1,733 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_tex.c,v 1.6 2002/09/16 18:05:20 eich 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 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 THE COPYRIGHT OWNER(S) 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:
+ * Gareth Hughes <gareth@valinux.com>
+ * Brian Paul <brianp@valinux.com>
+ */
+
+#include "glheader.h"
+#include "imports.h"
+#include "colormac.h"
+#include "context.h"
+#include "enums.h"
+#include "image.h"
+#include "simple_list.h"
+#include "texformat.h"
+#include "texstore.h"
+#include "teximage.h"
+
+
+#include "radeon_context.h"
+#include "radeon_state.h"
+#include "radeon_ioctl.h"
+#include "radeon_swtcl.h"
+#include "radeon_tex.h"
+
+
+
+/**
+ * Set the texture wrap modes.
+ *
+ * \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 radeonSetTexWrap( radeonTexObjPtr t, GLenum swrap, GLenum twrap )
+{
+ GLboolean is_clamp = GL_FALSE;
+ GLboolean is_clamp_to_border = GL_FALSE;
+
+ t->pp_txfilter &= ~(RADEON_CLAMP_S_MASK | RADEON_CLAMP_T_MASK | RADEON_BORDER_MODE_D3D);
+
+ switch ( swrap ) {
+ case GL_REPEAT:
+ t->pp_txfilter |= RADEON_CLAMP_S_WRAP;
+ break;
+ case GL_CLAMP:
+ t->pp_txfilter |= RADEON_CLAMP_S_CLAMP_GL;
+ is_clamp = GL_TRUE;
+ break;
+ case GL_CLAMP_TO_EDGE:
+ t->pp_txfilter |= RADEON_CLAMP_S_CLAMP_LAST;
+ break;
+ case GL_CLAMP_TO_BORDER:
+ t->pp_txfilter |= RADEON_CLAMP_S_CLAMP_GL;
+ is_clamp_to_border = GL_TRUE;
+ break;
+ case GL_MIRRORED_REPEAT:
+ t->pp_txfilter |= RADEON_CLAMP_S_MIRROR;
+ break;
+ case GL_MIRROR_CLAMP_ATI:
+ t->pp_txfilter |= RADEON_CLAMP_S_MIRROR_CLAMP_GL;
+ is_clamp = GL_TRUE;
+ break;
+ case GL_MIRROR_CLAMP_TO_EDGE_ATI:
+ t->pp_txfilter |= RADEON_CLAMP_S_MIRROR_CLAMP_LAST;
+ break;
+ default:
+ _mesa_problem(NULL, "bad S wrap mode in %s", __FUNCTION__);
+ }
+
+ switch ( twrap ) {
+ case GL_REPEAT:
+ t->pp_txfilter |= RADEON_CLAMP_T_WRAP;
+ break;
+ case GL_CLAMP:
+ t->pp_txfilter |= RADEON_CLAMP_T_CLAMP_GL;
+ is_clamp = GL_TRUE;
+ break;
+ case GL_CLAMP_TO_EDGE:
+ t->pp_txfilter |= RADEON_CLAMP_T_CLAMP_LAST;
+ break;
+ case GL_CLAMP_TO_BORDER:
+ t->pp_txfilter |= RADEON_CLAMP_T_CLAMP_GL;
+ is_clamp_to_border = GL_TRUE;
+ break;
+ case GL_MIRRORED_REPEAT:
+ t->pp_txfilter |= RADEON_CLAMP_T_MIRROR;
+ break;
+ case GL_MIRROR_CLAMP_ATI:
+ t->pp_txfilter |= RADEON_CLAMP_T_MIRROR_CLAMP_GL;
+ is_clamp = GL_TRUE;
+ break;
+ case GL_MIRROR_CLAMP_TO_EDGE_ATI:
+ t->pp_txfilter |= RADEON_CLAMP_T_MIRROR_CLAMP_LAST;
+ break;
+ default:
+ _mesa_problem(NULL, "bad T wrap mode in %s", __FUNCTION__);
+ }
+
+ if ( is_clamp_to_border ) {
+ t->pp_txfilter |= RADEON_BORDER_MODE_D3D;
+ }
+
+ t->border_fallback = (is_clamp && is_clamp_to_border);
+}
+
+static void radeonSetTexMaxAnisotropy( radeonTexObjPtr t, GLfloat max )
+{
+ t->pp_txfilter &= ~RADEON_MAX_ANISO_MASK;
+
+ if ( max == 1.0 ) {
+ t->pp_txfilter |= RADEON_MAX_ANISO_1_TO_1;
+ } else if ( max <= 2.0 ) {
+ t->pp_txfilter |= RADEON_MAX_ANISO_2_TO_1;
+ } else if ( max <= 4.0 ) {
+ t->pp_txfilter |= RADEON_MAX_ANISO_4_TO_1;
+ } else if ( max <= 8.0 ) {
+ t->pp_txfilter |= RADEON_MAX_ANISO_8_TO_1;
+ } else {
+ t->pp_txfilter |= RADEON_MAX_ANISO_16_TO_1;
+ }
+}
+
+/**
+ * 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 radeonSetTexFilter( radeonTexObjPtr t, GLenum minf, GLenum magf )
+{
+ GLuint anisotropy = (t->pp_txfilter & RADEON_MAX_ANISO_MASK);
+
+ t->pp_txfilter &= ~(RADEON_MIN_FILTER_MASK | RADEON_MAG_FILTER_MASK);
+
+ if ( anisotropy == RADEON_MAX_ANISO_1_TO_1 ) {
+ switch ( minf ) {
+ case GL_NEAREST:
+ t->pp_txfilter |= RADEON_MIN_FILTER_NEAREST;
+ break;
+ case GL_LINEAR:
+ t->pp_txfilter |= RADEON_MIN_FILTER_LINEAR;
+ break;
+ case GL_NEAREST_MIPMAP_NEAREST:
+ t->pp_txfilter |= RADEON_MIN_FILTER_NEAREST_MIP_NEAREST;
+ break;
+ case GL_NEAREST_MIPMAP_LINEAR:
+ t->pp_txfilter |= RADEON_MIN_FILTER_LINEAR_MIP_NEAREST;
+ break;
+ case GL_LINEAR_MIPMAP_NEAREST:
+ t->pp_txfilter |= RADEON_MIN_FILTER_NEAREST_MIP_LINEAR;
+ break;
+ case GL_LINEAR_MIPMAP_LINEAR:
+ t->pp_txfilter |= RADEON_MIN_FILTER_LINEAR_MIP_LINEAR;
+ break;
+ }
+ } else {
+ switch ( minf ) {
+ case GL_NEAREST:
+ t->pp_txfilter |= RADEON_MIN_FILTER_ANISO_NEAREST;
+ break;
+ case GL_LINEAR:
+ t->pp_txfilter |= RADEON_MIN_FILTER_ANISO_LINEAR;
+ break;
+ case GL_NEAREST_MIPMAP_NEAREST:
+ case GL_LINEAR_MIPMAP_NEAREST:
+ t->pp_txfilter |= RADEON_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST;
+ break;
+ case GL_NEAREST_MIPMAP_LINEAR:
+ case GL_LINEAR_MIPMAP_LINEAR:
+ t->pp_txfilter |= RADEON_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR;
+ break;
+ }
+ }
+
+ switch ( magf ) {
+ case GL_NEAREST:
+ t->pp_txfilter |= RADEON_MAG_FILTER_NEAREST;
+ break;
+ case GL_LINEAR:
+ t->pp_txfilter |= RADEON_MAG_FILTER_LINEAR;
+ break;
+ }
+}
+
+static void radeonSetTexBorderColor( radeonTexObjPtr t, GLubyte c[4] )
+{
+ t->pp_border_color = radeonPackColor( 4, c[0], c[1], c[2], c[3] );
+}
+
+
+/**
+ * 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 radeonTexObjPtr radeonAllocTexObj( struct gl_texture_object *texObj )
+{
+ radeonTexObjPtr t;
+
+ t = CALLOC_STRUCT( radeon_tex_obj );
+ texObj->DriverData = t;
+ if ( t != NULL ) {
+ if ( RADEON_DEBUG & DEBUG_TEXTURE ) {
+ fprintf( stderr, "%s( %p, %p )\n", __FUNCTION__, texObj, t );
+ }
+
+ /* Initialize non-image-dependent parts of the state:
+ */
+ t->base.tObj = texObj;
+ t->border_fallback = GL_FALSE;
+
+ t->pp_txfilter = RADEON_BORDER_MODE_OGL;
+ t->pp_txformat = (RADEON_TXFORMAT_ENDIAN_NO_SWAP |
+ RADEON_TXFORMAT_PERSPECTIVE_ENABLE);
+
+ make_empty_list( & t->base );
+
+ radeonSetTexWrap( t, texObj->WrapS, texObj->WrapT );
+ radeonSetTexMaxAnisotropy( t, texObj->MaxAnisotropy );
+ radeonSetTexFilter( t, texObj->MinFilter, texObj->MagFilter );
+ radeonSetTexBorderColor( t, texObj->_BorderChan );
+ }
+
+ return t;
+}
+
+
+static const struct gl_texture_format *
+radeonChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
+ GLenum format, GLenum type )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ const GLboolean do32bpt = ( rmesa->radeonScreen->cpp == 4 );
+
+ switch ( internalFormat ) {
+ case 4:
+ case GL_RGBA:
+ case GL_COMPRESSED_RGBA:
+ if ( format == GL_BGRA ) {
+ if ( type == GL_UNSIGNED_INT_8_8_8_8_REV ) {
+ return &_mesa_texformat_argb8888;
+ }
+ else if ( type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) {
+ return &_mesa_texformat_argb4444;
+ }
+ else if ( type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) {
+ return &_mesa_texformat_argb1555;
+ }
+ }
+ return do32bpt ? &_mesa_texformat_rgba8888 : &_mesa_texformat_argb4444;
+
+ case 3:
+ case GL_RGB:
+ case GL_COMPRESSED_RGB:
+ if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) {
+ return &_mesa_texformat_rgb565;
+ }
+ return do32bpt ? &_mesa_texformat_rgba8888 : &_mesa_texformat_rgb565;
+
+ case GL_RGBA8:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ return do32bpt ? &_mesa_texformat_rgba8888 : &_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 do32bpt ? &_mesa_texformat_rgba8888 : &_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:
+ return &_mesa_texformat_al88;
+
+ case 1:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ case GL_COMPRESSED_LUMINANCE:
+ return &_mesa_texformat_al88;
+
+ case 2:
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE4_ALPHA4:
+ case GL_LUMINANCE6_ALPHA2:
+ case GL_LUMINANCE8_ALPHA8:
+ case GL_LUMINANCE12_ALPHA4:
+ case GL_LUMINANCE12_ALPHA12:
+ case GL_LUMINANCE16_ALPHA16:
+ case GL_COMPRESSED_LUMINANCE_ALPHA:
+ return &_mesa_texformat_al88;
+
+ case GL_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ case GL_COMPRESSED_INTENSITY:
+ return &_mesa_texformat_i8;
+
+ case GL_YCBCR_MESA:
+ if (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
+ type == GL_UNSIGNED_BYTE)
+ return &_mesa_texformat_ycbcr;
+ else
+ return &_mesa_texformat_ycbcr_rev;
+
+ default:
+ _mesa_problem(ctx, "unexpected texture format in %s", __FUNCTION__);
+ return NULL;
+ }
+
+ return NULL; /* never get here */
+}
+
+
+static void radeonTexImage1D( GLcontext *ctx, GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint border,
+ GLenum format, GLenum type, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage )
+{
+ driTextureObject * t = (driTextureObject *) texObj->DriverData;
+
+ if ( t ) {
+ driSwapOutTextureObject( t );
+ }
+ else {
+ t = (driTextureObject *) radeonAllocTexObj( texObj );
+ if (!t) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
+ return;
+ }
+ }
+
+ /* Note, this will call ChooseTextureFormat */
+ _mesa_store_teximage1d(ctx, target, level, internalFormat,
+ width, border, format, type, pixels,
+ &ctx->Unpack, texObj, texImage);
+
+ t->dirty_images[0] |= (1 << level);
+}
+
+
+static void radeonTexSubImage1D( GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset,
+ GLsizei width,
+ GLenum format, GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage )
+{
+ driTextureObject * t = (driTextureObject *) texObj->DriverData;
+
+ assert( t ); /* this _should_ be true */
+ if ( t ) {
+ driSwapOutTextureObject( t );
+ }
+ else {
+ t = (driTextureObject *) radeonAllocTexObj( texObj );
+ if (!t) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
+ return;
+ }
+ }
+
+ _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
+ format, type, pixels, packing, texObj,
+ texImage);
+
+ t->dirty_images[0] |= (1 << level);
+}
+
+
+static void radeonTexImage2D( 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;
+ GLuint face;
+
+ /* which cube face or ordinary 2D image */
+ switch (target) {
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
+ ASSERT(face < 6);
+ break;
+ default:
+ face = 0;
+ }
+
+ if ( t != NULL ) {
+ driSwapOutTextureObject( t );
+ }
+ else {
+ t = (driTextureObject *) radeonAllocTexObj( texObj );
+ if (!t) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
+ return;
+ }
+ }
+
+ /* Note, this will call ChooseTextureFormat */
+ _mesa_store_teximage2d(ctx, target, level, internalFormat,
+ width, height, border, format, type, pixels,
+ &ctx->Unpack, texObj, texImage);
+
+ t->dirty_images[face] |= (1 << level);
+}
+
+
+static void radeonTexSubImage2D( 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;
+ GLuint face;
+
+
+ /* which cube face or ordinary 2D image */
+ switch (target) {
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
+ ASSERT(face < 6);
+ break;
+ default:
+ face = 0;
+ }
+
+ assert( t ); /* this _should_ be true */
+ if ( t ) {
+ driSwapOutTextureObject( t );
+ }
+ else {
+ t = (driTextureObject *) radeonAllocTexObj( texObj );
+ if (!t) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
+ return;
+ }
+ }
+
+ _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
+ height, format, type, pixels, packing, texObj,
+ texImage);
+
+ t->dirty_images[face] |= (1 << level);
+}
+
+
+
+#define SCALED_FLOAT_TO_BYTE( x, scale ) \
+ (((GLuint)((255.0F / scale) * (x))) / 2)
+
+static void radeonTexEnv( GLcontext *ctx, GLenum target,
+ GLenum pname, const GLfloat *param )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLuint unit = ctx->Texture.CurrentUnit;
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+
+ if ( RADEON_DEBUG & DEBUG_STATE ) {
+ fprintf( stderr, "%s( %s )\n",
+ __FUNCTION__, _mesa_lookup_enum_by_nr( pname ) );
+ }
+
+ switch ( pname ) {
+ case GL_TEXTURE_ENV_COLOR: {
+ GLubyte c[4];
+ GLuint envColor;
+ UNCLAMPED_FLOAT_TO_RGBA_CHAN( c, texUnit->EnvColor );
+ envColor = radeonPackColor( 4, c[0], c[1], c[2], c[3] );
+ if ( rmesa->hw.tex[unit].cmd[TEX_PP_TFACTOR] != envColor ) {
+ RADEON_STATECHANGE( rmesa, tex[unit] );
+ rmesa->hw.tex[unit].cmd[TEX_PP_TFACTOR] = envColor;
+ }
+ break;
+ }
+
+ case GL_TEXTURE_LOD_BIAS_EXT: {
+ GLfloat bias;
+ GLuint b;
+
+ /* The Radeon's LOD bias is a signed 2's complement value with a
+ * range of -1.0 <= bias < 4.0. We break this into two linear
+ * functions, one mapping [-1.0,0.0] to [-128,0] and one mapping
+ * [0.0,4.0] to [0,127].
+ */
+ bias = CLAMP( *param, -1.0, 4.0 );
+ if ( bias == 0 ) {
+ b = 0;
+ } else if ( bias > 0 ) {
+ b = ((GLuint)SCALED_FLOAT_TO_BYTE( bias, 4.0 )) << RADEON_LOD_BIAS_SHIFT;
+ } else {
+ b = ((GLuint)SCALED_FLOAT_TO_BYTE( bias, 1.0 )) << RADEON_LOD_BIAS_SHIFT;
+ }
+ if ( (rmesa->hw.tex[unit].cmd[TEX_PP_TXFILTER] & RADEON_LOD_BIAS_MASK) != b ) {
+ RADEON_STATECHANGE( rmesa, tex[unit] );
+ rmesa->hw.tex[unit].cmd[TEX_PP_TXFILTER] &= ~RADEON_LOD_BIAS_MASK;
+ rmesa->hw.tex[unit].cmd[TEX_PP_TXFILTER] |= (b & RADEON_LOD_BIAS_MASK);
+ }
+ break;
+ }
+
+ default:
+ return;
+ }
+}
+
+
+/**
+ * Changes variables and flags for a state update, which will happen at the
+ * next UpdateTextureState
+ */
+
+static void radeonTexParameter( GLcontext *ctx, GLenum target,
+ struct gl_texture_object *texObj,
+ GLenum pname, const GLfloat *params )
+{
+ radeonTexObjPtr t = (radeonTexObjPtr) texObj->DriverData;
+
+ if ( RADEON_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) {
+ fprintf( stderr, "%s( %s )\n", __FUNCTION__,
+ _mesa_lookup_enum_by_nr( pname ) );
+ }
+
+ if ( ( target != GL_TEXTURE_2D ) &&
+ ( target != GL_TEXTURE_1D ) )
+ return;
+
+ switch ( pname ) {
+ case GL_TEXTURE_MIN_FILTER:
+ case GL_TEXTURE_MAG_FILTER:
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ radeonSetTexMaxAnisotropy( t, texObj->MaxAnisotropy );
+ radeonSetTexFilter( t, texObj->MinFilter, texObj->MagFilter );
+ break;
+
+ case GL_TEXTURE_WRAP_S:
+ case GL_TEXTURE_WRAP_T:
+ radeonSetTexWrap( t, texObj->WrapS, texObj->WrapT );
+ break;
+
+ case GL_TEXTURE_BORDER_COLOR:
+ radeonSetTexBorderColor( t, texObj->_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;
+ }
+
+ /* Mark this texobj as dirty (one bit per tex unit)
+ */
+ t->dirty_state = TEX_ALL;
+}
+
+
+
+static void radeonBindTexture( GLcontext *ctx, GLenum target,
+ struct gl_texture_object *texObj )
+{
+ if ( RADEON_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) {
+ fprintf( stderr, "%s( %p ) unit=%d\n", __FUNCTION__, texObj,
+ ctx->Texture.CurrentUnit );
+ }
+
+ if ( target == GL_TEXTURE_2D || target == GL_TEXTURE_1D ) {
+ if ( texObj->DriverData == NULL ) {
+ radeonAllocTexObj( texObj );
+ }
+ }
+}
+
+static void radeonDeleteTexture( GLcontext *ctx,
+ struct gl_texture_object *texObj )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ driTextureObject * t = (driTextureObject *) texObj->DriverData;
+
+ if ( RADEON_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) {
+ fprintf( stderr, "%s( %p (target = %s) )\n", __FUNCTION__, texObj,
+ _mesa_lookup_enum_by_nr( texObj->Target ) );
+ }
+
+ if ( t != NULL ) {
+ if ( rmesa ) {
+ RADEON_FIREVERTICES( rmesa );
+ }
+
+ driDestroyTextureObject( t );
+ }
+}
+
+/* Need:
+ * - Same GEN_MODE for all active bits
+ * - Same EyePlane/ObjPlane for all active bits when using Eye/Obj
+ * - STRQ presumably all supported (matrix means incoming R values
+ * can end up in STQ, this has implications for vertex support,
+ * presumably ok if maos is used, though?)
+ *
+ * Basically impossible to do this on the fly - just collect some
+ * basic info & do the checks from ValidateState().
+ */
+static void radeonTexGen( GLcontext *ctx,
+ GLenum coord,
+ GLenum pname,
+ const GLfloat *params )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLuint unit = ctx->Texture.CurrentUnit;
+ rmesa->recheck_texgen[unit] = GL_TRUE;
+}
+
+
+void radeonInitTextureFuncs( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+
+ ctx->Driver.ChooseTextureFormat = radeonChooseTextureFormat;
+ ctx->Driver.TexImage1D = radeonTexImage1D;
+ ctx->Driver.TexImage2D = radeonTexImage2D;
+ ctx->Driver.TexImage3D = _mesa_store_teximage3d;
+ ctx->Driver.TexSubImage1D = radeonTexSubImage1D;
+ ctx->Driver.TexSubImage2D = radeonTexSubImage2D;
+ ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
+ ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d;
+ ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d;
+ ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d;
+ ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d;
+ ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d;
+ ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage;
+
+ ctx->Driver.BindTexture = radeonBindTexture;
+ ctx->Driver.CreateTexture = NULL; /* FIXME: Is this used??? */
+ ctx->Driver.DeleteTexture = radeonDeleteTexture;
+ ctx->Driver.IsTextureResident = driIsTextureResident;
+ ctx->Driver.PrioritizeTexture = NULL;
+ ctx->Driver.ActiveTexture = NULL;
+ ctx->Driver.UpdateTexturePalette = NULL;
+
+ ctx->Driver.TexEnv = radeonTexEnv;
+ ctx->Driver.TexParameter = radeonTexParameter;
+ ctx->Driver.TexGen = radeonTexGen;
+
+ driInitTextureObjects( ctx, & rmesa->swapped,
+ DRI_TEXMGR_DO_TEXTURE_1D
+ | DRI_TEXMGR_DO_TEXTURE_2D );
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_tex.h b/src/mesa/drivers/dri/radeon/radeon_tex.h
new file mode 100644
index 0000000000..ce079baec2
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_tex.h
@@ -0,0 +1,53 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_tex.h,v 1.3 2002/02/22 21:45:01 dawes 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 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 THE COPYRIGHT OWNER(S) 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:
+ * Kevin E. Martin <martin@valinux.com>
+ * Gareth Hughes <gareth@valinux.com>
+ *
+ */
+
+#ifndef __RADEON_TEX_H__
+#define __RADEON_TEX_H__
+
+#ifdef GLX_DIRECT_RENDERING
+
+extern void radeonUpdateTextureState( GLcontext *ctx );
+
+extern int radeonUploadTexImages( radeonContextPtr rmesa, radeonTexObjPtr t,
+ GLuint face );
+
+extern void radeonDestroyTexObj( radeonContextPtr rmesa, radeonTexObjPtr t );
+
+extern void radeonInitTextureFuncs( GLcontext *ctx );
+
+#endif
+#endif /* __RADEON_TEX_H__ */
diff --git a/src/mesa/drivers/dri/radeon/radeon_texmem.c b/src/mesa/drivers/dri/radeon/radeon_texmem.c
new file mode 100644
index 0000000000..3adc2a951c
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_texmem.c
@@ -0,0 +1,378 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_texmem.c,v 1.7 2002/12/16 16:18:59 dawes 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:
+ * Kevin E. Martin <martin@valinux.com>
+ * Gareth Hughes <gareth@valinux.com>
+ *
+ */
+#include <errno.h>
+
+#include "glheader.h"
+#include "imports.h"
+#include "context.h"
+#include "macros.h"
+#include "simple_list.h"
+
+#include "radeon_context.h"
+#include "radeon_ioctl.h"
+#include "radeon_tex.h"
+
+
+/**
+ * Destroy any device-dependent state associated with the texture. This may
+ * include NULLing out hardware state that points to the texture.
+ */
+void
+radeonDestroyTexObj( radeonContextPtr rmesa, radeonTexObjPtr t )
+{
+ if ( RADEON_DEBUG & DEBUG_TEXTURE ) {
+ fprintf( stderr, "%s( %p, %p )\n", __FUNCTION__, t, t->base.tObj );
+ }
+
+ if ( rmesa != NULL ) {
+ unsigned i;
+
+
+ for ( i = 0 ; i < rmesa->glCtx->Const.MaxTextureUnits ; i++ ) {
+ if ( t == rmesa->state.texture.unit[i].texobj ) {
+ rmesa->state.texture.unit[i].texobj = NULL;
+ remove_from_list( &rmesa->hw.tex[i] );
+ make_empty_list( &rmesa->hw.tex[i] );
+ }
+ }
+ }
+}
+
+
+/* ------------------------------------------------------------
+ * Texture image conversions
+ */
+
+
+static void radeonUploadRectSubImage( radeonContextPtr rmesa,
+ radeonTexObjPtr t,
+ struct gl_texture_image *texImage,
+ GLint x, GLint y,
+ GLint width, GLint height )
+{
+ const struct gl_texture_format *texFormat = texImage->TexFormat;
+ int blit_format, dstPitch, done;
+
+ switch ( texFormat->TexelBytes ) {
+ case 1:
+ blit_format = RADEON_GMC_DST_8BPP_CI;
+ break;
+ case 2:
+ blit_format = RADEON_GMC_DST_16BPP;
+ break;
+ case 4:
+ blit_format = RADEON_GMC_DST_32BPP;
+ break;
+ default:
+ fprintf( stderr, "radeonUploadRectSubImage: unknown blit_format (texelbytes=%d)\n",
+ texFormat->TexelBytes);
+ return;
+ }
+
+ t->image[0][0].data = texImage->Data;
+
+ /* Currently don't need to cope with small pitches.
+ */
+ width = texImage->Width;
+ height = texImage->Height;
+ dstPitch = t->pp_txpitch + 32;
+
+ { /* FIXME: prefer AGP-texturing if possible */
+ /* Data not in agp memory, or bad pitch.
+ */
+ for (done = 0; done < height ; ) {
+ struct radeon_dma_region region;
+ int lines = MIN2( height - done, RADEON_BUFFER_SIZE / dstPitch );
+ int src_pitch;
+ char *tex;
+
+ src_pitch = texImage->RowStride * texFormat->TexelBytes;
+
+ tex = (char *)texImage->Data + done * src_pitch;
+
+ memset(&region, 0, sizeof(region));
+ radeonAllocDmaRegion( rmesa, &region, lines * dstPitch, 1024 );
+
+ /* Copy texdata to dma:
+ */
+ if (0)
+ fprintf(stderr, "%s: src_pitch %d dst_pitch %d\n",
+ __FUNCTION__, src_pitch, dstPitch);
+
+ if (src_pitch == dstPitch) {
+ memcpy( region.address, tex, lines * src_pitch );
+ }
+ else {
+ char *buf = region.address;
+ int i;
+ for (i = 0 ; i < lines ; i++) {
+ memcpy( buf, tex, src_pitch );
+ buf += dstPitch;
+ tex += src_pitch;
+ }
+ }
+
+ radeonEmitWait( rmesa, RADEON_WAIT_3D );
+
+
+
+ /* Blit to framebuffer
+ */
+ radeonEmitBlit( rmesa,
+ blit_format,
+ dstPitch, GET_START( &region ),
+ dstPitch, t->bufAddr,
+ 0, 0,
+ 0, done,
+ width, lines );
+
+ radeonEmitWait( rmesa, RADEON_WAIT_2D );
+
+ radeonReleaseDmaRegion( rmesa, &region, __FUNCTION__ );
+ done += lines;
+ }
+ }
+}
+
+
+/**
+ * Upload the texture image associated with texture \a t at the specified
+ * level at the address relative to \a start.
+ */
+static void uploadSubImage( radeonContextPtr rmesa, radeonTexObjPtr t,
+ GLint hwlevel,
+ GLint x, GLint y, GLint width, GLint height,
+ GLuint face )
+{
+ struct gl_texture_image *texImage = NULL;
+ GLuint offset;
+ GLint imageWidth, imageHeight;
+ GLint ret;
+ drmRadeonTexture tex;
+ drmRadeonTexImage tmp;
+ const int level = hwlevel + t->base.firstLevel;
+
+ if ( RADEON_DEBUG & DEBUG_TEXTURE ) {
+ fprintf( stderr, "%s( %p, %p ) level/width/height/face = %d/%d/%d/%u\n",
+ __FUNCTION__, t, t->base.tObj, level, width, height, face );
+ }
+
+ ASSERT(face < 6);
+
+ /* Ensure we have a valid texture to upload */
+ if ( ( hwlevel < 0 ) || ( hwlevel >= RADEON_MAX_TEXTURE_LEVELS ) ) {
+ _mesa_problem(NULL, "bad texture level in %s", __FUNCTION__);
+ return;
+ }
+
+ switch (face) {
+ case 0:
+ texImage = t->base.tObj->Image[level];
+ break;
+ case 1:
+ texImage = t->base.tObj->NegX[level];
+ break;
+ case 2:
+ texImage = t->base.tObj->PosY[level];
+ break;
+ case 3:
+ texImage = t->base.tObj->NegY[level];
+ break;
+ case 4:
+ texImage = t->base.tObj->PosZ[level];
+ break;
+ case 5:
+ texImage = t->base.tObj->NegZ[level];
+ break;
+ }
+
+ if ( !texImage ) {
+ if ( RADEON_DEBUG & DEBUG_TEXTURE )
+ fprintf( stderr, "%s: texImage %d is NULL!\n", __FUNCTION__, level );
+ return;
+ }
+ if ( !texImage->Data ) {
+ if ( RADEON_DEBUG & DEBUG_TEXTURE )
+ fprintf( stderr, "%s: image data is NULL!\n", __FUNCTION__ );
+ return;
+ }
+
+
+ if (t->base.tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
+ assert(level == 0);
+ assert(hwlevel == 0);
+ if ( RADEON_DEBUG & DEBUG_TEXTURE )
+ fprintf( stderr, "%s: image data is rectangular\n", __FUNCTION__);
+ radeonUploadRectSubImage( rmesa, t, texImage, x, y, width, height );
+ return;
+ }
+
+ imageWidth = texImage->Width;
+ imageHeight = texImage->Height;
+
+ offset = t->bufAddr;
+
+ if ( RADEON_DEBUG & (DEBUG_TEXTURE|DEBUG_IOCTL) ) {
+ GLint imageX = 0;
+ GLint imageY = 0;
+ GLint blitX = t->image[face][hwlevel].x;
+ GLint blitY = t->image[face][hwlevel].y;
+ GLint blitWidth = t->image[face][hwlevel].width;
+ GLint blitHeight = t->image[face][hwlevel].height;
+ fprintf( stderr, " upload image: %d,%d at %d,%d\n",
+ imageWidth, imageHeight, imageX, imageY );
+ fprintf( stderr, " upload blit: %d,%d at %d,%d\n",
+ blitWidth, blitHeight, blitX, blitY );
+ fprintf( stderr, " blit ofs: 0x%07x level: %d/%d\n",
+ (GLuint)offset, hwlevel, level );
+ }
+
+ t->image[face][hwlevel].data = texImage->Data;
+
+ /* Init the DRM_RADEON_TEXTURE command / drmRadeonTexture struct.
+ * NOTE: we're always use a 1KB-wide blit and I8 texture format.
+ * We used to use 1, 2 and 4-byte texels and used to use the texture
+ * width to dictate the blit width - but that won't work for compressed
+ * textures. (Brian)
+ */
+ tex.offset = offset;
+ tex.pitch = BLIT_WIDTH_BYTES / 64;
+ tex.format = RADEON_TXFORMAT_I8; /* any 1-byte texel format */
+ if (texImage->TexFormat->TexelBytes) {
+ tex.width = imageWidth * texImage->TexFormat->TexelBytes; /* in bytes */
+ tex.height = imageHeight;
+ }
+ else {
+ tex.width = imageWidth; /* compressed */
+ tex.height = imageHeight;
+ if (tex.height < 4)
+ tex.height = 4;
+ }
+ tex.image = &tmp;
+
+ /* copy (x,y,width,height,data) */
+ memcpy( &tmp, &t->image[face][hwlevel], sizeof(drmRadeonTexImage) );
+
+ LOCK_HARDWARE( rmesa );
+ do {
+ ret = drmCommandWriteRead( rmesa->dri.fd, DRM_RADEON_TEXTURE,
+ &tex, sizeof(drmRadeonTexture) );
+ } while ( ret && errno == EAGAIN );
+
+ UNLOCK_HARDWARE( rmesa );
+
+ if ( ret ) {
+ fprintf( stderr, "DRM_RADEON_TEXTURE: return = %d\n", ret );
+ fprintf( stderr, " offset=0x%08x\n",
+ offset );
+ fprintf( stderr, " image width=%d height=%d\n",
+ imageWidth, imageHeight );
+ fprintf( stderr, " blit width=%d height=%d data=%p\n",
+ t->image[face][hwlevel].width, t->image[face][hwlevel].height,
+ t->image[face][hwlevel].data );
+ exit( 1 );
+ }
+}
+
+
+/**
+ * Upload the texture images associated with texture \a t. This might
+ * require the allocation of texture memory.
+ *
+ * \param rmesa Context pointer
+ * \param t Texture to be uploaded
+ * \param face Cube map face to be uploaded. Zero for non-cube maps.
+ */
+
+int radeonUploadTexImages( radeonContextPtr rmesa, radeonTexObjPtr t, GLuint face )
+{
+ const int numLevels = t->base.lastLevel - t->base.firstLevel + 1;
+
+ if ( RADEON_DEBUG & (DEBUG_TEXTURE|DEBUG_IOCTL) ) {
+ fprintf( stderr, "%s( %p, %p ) sz=%d lvls=%d-%d\n", __FUNCTION__,
+ rmesa->glCtx, t->base.tObj, t->base.totalSize,
+ t->base.firstLevel, t->base.lastLevel );
+ }
+
+ if ( !t || t->base.totalSize == 0 )
+ return 0;
+
+ LOCK_HARDWARE( rmesa );
+
+ if ( t->base.memBlock == NULL ) {
+ int heap;
+
+ heap = driAllocateTexture( rmesa->texture_heaps, rmesa->nr_heaps,
+ (driTextureObject *) t );
+ if ( heap == -1 ) {
+ UNLOCK_HARDWARE( rmesa );
+ return -1;
+ }
+
+ /* Set the base offset of the texture image */
+ t->bufAddr = rmesa->radeonScreen->texOffset[heap]
+ + t->base.memBlock->ofs;
+ t->pp_txoffset = t->bufAddr;
+
+
+ /* Mark this texobj as dirty on all units:
+ */
+ t->dirty_state = TEX_ALL;
+ }
+
+
+ /* Let the world know we've used this memory recently.
+ */
+ driUpdateTextureLRU( (driTextureObject *) t );
+ UNLOCK_HARDWARE( rmesa );
+
+
+ /* Upload any images that are new */
+ if (t->base.dirty_images[face]) {
+ int i;
+ for ( i = 0 ; i < numLevels ; i++ ) {
+ if ( (t->base.dirty_images[face] & (1 << (i+t->base.firstLevel))) != 0 ) {
+ uploadSubImage( rmesa, t, i, 0, 0, t->image[face][i].width,
+ t->image[face][i].height, face );
+ }
+ }
+ t->base.dirty_images[face] = 0;
+ }
+
+ return 0;
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_texstate.c b/src/mesa/drivers/dri/radeon/radeon_texstate.c
new file mode 100644
index 0000000000..6dccd31180
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_texstate.c
@@ -0,0 +1,1628 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_texstate.c,v 1.6 2002/12/16 16:18:59 dawes 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 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 THE COPYRIGHT OWNER(S) 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:
+ * Kevin E. Martin <martin@valinux.com>
+ * Gareth Hughes <gareth@valinux.com>
+ */
+
+#include "glheader.h"
+#include "imports.h"
+#include "colormac.h"
+#include "context.h"
+#include "macros.h"
+#include "texformat.h"
+#include "enums.h"
+
+#include "radeon_context.h"
+#include "radeon_state.h"
+#include "radeon_ioctl.h"
+#include "radeon_swtcl.h"
+#include "radeon_tex.h"
+#include "radeon_tcl.h"
+
+
+#define RADEON_TXFORMAT_AL88 RADEON_TXFORMAT_AI88
+#define RADEON_TXFORMAT_YCBCR RADEON_TXFORMAT_YVYU422
+#define RADEON_TXFORMAT_YCBCR_REV RADEON_TXFORMAT_VYUY422
+
+#define _COLOR(f) \
+ [ MESA_FORMAT_ ## f ] = { RADEON_TXFORMAT_ ## f, 0 }
+#define _ALPHA(f) \
+ [ MESA_FORMAT_ ## f ] = { RADEON_TXFORMAT_ ## f | RADEON_TXFORMAT_ALPHA_IN_MAP, 0 }
+#define _YUV(f) \
+ [ MESA_FORMAT_ ## f ] = { RADEON_TXFORMAT_ ## f, RADEON_YUV_TO_RGB }
+#define _INVALID(f) \
+ [ MESA_FORMAT_ ## f ] = { 0xffffffff, 0 }
+#define VALID_FORMAT(f) ( ((f) <= MESA_FORMAT_YCBCR_REV) \
+ && (tx_table[f].format != 0xffffffff) )
+
+static const struct {
+ GLuint format, filter;
+}
+tx_table[] =
+{
+ _ALPHA(RGBA8888),
+ _ALPHA(ARGB8888),
+ _INVALID(RGB888),
+ _COLOR(RGB565),
+ _ALPHA(ARGB4444),
+ _ALPHA(ARGB1555),
+ _ALPHA(AL88),
+ _INVALID(A8),
+ _INVALID(L8),
+ _COLOR(I8),
+ _INVALID(CI8),
+ _YUV(YCBCR),
+ _YUV(YCBCR_REV),
+};
+
+#undef _COLOR
+#undef _ALPHA
+#undef _INVALID
+
+/**
+ * This function computes the number of bytes of storage needed for
+ * the given texture object (all mipmap levels, all cube faces).
+ * The \c image[face][level].x/y/width/height parameters for upload/blitting
+ * are computed here. \c pp_txfilter, \c pp_txformat, etc. will be set here
+ * too.
+ *
+ * \param rmesa Context pointer
+ * \param tObj GL texture object whose images are to be posted to
+ * hardware state.
+ */
+static void radeonSetTexImages( radeonContextPtr rmesa,
+ struct gl_texture_object *tObj )
+{
+ radeonTexObjPtr t = (radeonTexObjPtr)tObj->DriverData;
+ const struct gl_texture_image *baseImage = tObj->Image[tObj->BaseLevel];
+ GLint curOffset;
+ GLint i;
+ GLint firstLevel=0, lastLevel=0, numLevels;
+ GLint log2Width, log2Height, log2Depth;
+
+ /* Set the hardware texture format
+ */
+
+ t->pp_txformat &= ~(RADEON_TXFORMAT_FORMAT_MASK |
+ RADEON_TXFORMAT_ALPHA_IN_MAP);
+ t->pp_txfilter &= ~RADEON_YUV_TO_RGB;
+
+ if ( VALID_FORMAT( baseImage->TexFormat->MesaFormat ) ) {
+ t->pp_txformat |= tx_table[ baseImage->TexFormat->MesaFormat ].format;
+ t->pp_txfilter |= tx_table[ baseImage->TexFormat->MesaFormat ].filter;
+ }
+ else {
+ _mesa_problem(NULL, "unexpected texture format in %s", __FUNCTION__);
+ return;
+ }
+
+
+
+ /* Compute which mipmap levels we really want to send to the hardware.
+ * This depends on the base image size, GL_TEXTURE_MIN_LOD,
+ * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
+ * Yes, this looks overly complicated, but it's all needed.
+ */
+ switch (tObj->Target) {
+ case GL_TEXTURE_1D:
+ case GL_TEXTURE_2D:
+ firstLevel = tObj->BaseLevel + (GLint)(tObj->MinLod + 0.5);
+ firstLevel = MAX2(firstLevel, tObj->BaseLevel);
+ lastLevel = tObj->BaseLevel + (GLint)(tObj->MaxLod + 0.5);
+ lastLevel = MAX2(lastLevel, tObj->BaseLevel);
+ lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2);
+ lastLevel = MIN2(lastLevel, tObj->MaxLevel);
+ lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */
+ log2Width = tObj->Image[firstLevel]->WidthLog2;
+ log2Height = tObj->Image[firstLevel]->HeightLog2;
+ log2Depth = 0;
+ break;
+ case GL_TEXTURE_RECTANGLE_NV:
+ firstLevel = lastLevel = 0;
+ log2Width = log2Height = 1; /* ? */
+ log2Depth = 0;
+ break;
+ default:
+ return;
+ }
+
+ /* save these values */
+ t->base.firstLevel = firstLevel;
+ t->base.lastLevel = lastLevel;
+
+ numLevels = lastLevel - firstLevel + 1;
+
+ assert(numLevels <= RADEON_MAX_TEXTURE_LEVELS);
+
+ /* Calculate mipmap offsets and dimensions for blitting (uploading)
+ * The idea is that we lay out the mipmap levels within a block of
+ * memory organized as a rectangle of width BLIT_WIDTH_BYTES.
+ */
+ curOffset = 0;
+
+ for (i = 0; i < numLevels; i++) {
+ const struct gl_texture_image *texImage;
+ GLuint size;
+
+ texImage = tObj->Image[i + firstLevel];
+ if ( !texImage )
+ break;
+
+ /* find image size in bytes */
+ if (texImage->IsCompressed) {
+ size = texImage->CompressedSize;
+ }
+ else if (tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
+ size = ((texImage->Width * texImage->TexFormat->TexelBytes + 63)
+ & ~63) * texImage->Height;
+ }
+ else {
+ int w = texImage->Width * texImage->TexFormat->TexelBytes;
+ if (w < 32)
+ w = 32;
+ size = w * texImage->Height * texImage->Depth;
+ }
+ assert(size > 0);
+
+ if (curOffset & 0x1f) {
+ /* align to 32-byte offset */
+ curOffset = (curOffset + 0x1f) & ~0x1f;
+ }
+
+ t->image[0][i].x = curOffset % BLIT_WIDTH_BYTES;
+ t->image[0][i].y = curOffset / BLIT_WIDTH_BYTES;
+ t->image[0][i].width = MIN2(size, BLIT_WIDTH_BYTES);
+ t->image[0][i].height = size / t->image[0][i].width;
+
+#if 0
+ /* for debugging only and only applicable to non-rectangle targets */
+ assert(size % t->image[0][i].width == 0);
+ assert(t->image[0][i].x == 0
+ || (size < BLIT_WIDTH_BYTES && t->image[0][i].height == 1));
+#endif
+
+ if (0)
+ fprintf(stderr,
+ "level %d: %dx%d x=%d y=%d w=%d h=%d size=%d at %d\n",
+ i, texImage->Width, texImage->Height,
+ t->image[0][i].x, t->image[0][i].y,
+ t->image[0][i].width, t->image[0][i].height, size, curOffset);
+
+ curOffset += size;
+
+ }
+
+ /* Align the total size of texture memory block.
+ */
+ t->base.totalSize = (curOffset + RADEON_OFFSET_MASK) & ~RADEON_OFFSET_MASK;
+
+ /* Hardware state:
+ */
+ t->pp_txfilter &= ~RADEON_MAX_MIP_LEVEL_MASK;
+ t->pp_txfilter |= (numLevels - 1) << RADEON_MAX_MIP_LEVEL_SHIFT;
+
+ t->pp_txformat &= ~(RADEON_TXFORMAT_WIDTH_MASK |
+ RADEON_TXFORMAT_HEIGHT_MASK |
+ RADEON_TXFORMAT_CUBIC_MAP_ENABLE);
+ t->pp_txformat |= ((log2Width << RADEON_TXFORMAT_WIDTH_SHIFT) |
+ (log2Height << RADEON_TXFORMAT_HEIGHT_SHIFT));
+
+ t->pp_txsize = (((tObj->Image[firstLevel]->Width - 1) << 0) |
+ ((tObj->Image[firstLevel]->Height - 1) << 16));
+
+ /* Only need to round to nearest 32 for textures, but the blitter
+ * requires 64-byte aligned pitches, and we may/may not need the
+ * blitter. NPOT only!
+ */
+ if (baseImage->IsCompressed)
+ t->pp_txpitch = (tObj->Image[firstLevel]->Width + 63) & ~(63);
+ else
+ t->pp_txpitch = ((tObj->Image[firstLevel]->Width * baseImage->TexFormat->TexelBytes) + 63) & ~(63);
+ t->pp_txpitch -= 32;
+
+ t->dirty_state = TEX_ALL;
+
+ /* FYI: radeonUploadTexImages( rmesa, t ); used to be called here */
+}
+
+
+
+/* ================================================================
+ * Texture combine functions
+ */
+
+#define RADEON_DISABLE 0
+#define RADEON_REPLACE 1
+#define RADEON_MODULATE 2
+#define RADEON_DECAL 3
+#define RADEON_BLEND 4
+#define RADEON_ADD 5
+#define RADEON_MAX_COMBFUNC 6
+
+static GLuint radeon_color_combine[][RADEON_MAX_COMBFUNC] =
+{
+ /* Unit 0:
+ */
+ {
+ /* Disable combiner stage
+ */
+ (RADEON_COLOR_ARG_A_ZERO |
+ RADEON_COLOR_ARG_B_ZERO |
+ RADEON_COLOR_ARG_C_CURRENT_COLOR |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+
+ /* GL_REPLACE = 0x00802800
+ */
+ (RADEON_COLOR_ARG_A_ZERO |
+ RADEON_COLOR_ARG_B_ZERO |
+ RADEON_COLOR_ARG_C_T0_COLOR |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+
+ /* GL_MODULATE = 0x00800142
+ */
+ (RADEON_COLOR_ARG_A_CURRENT_COLOR |
+ RADEON_COLOR_ARG_B_T0_COLOR |
+ RADEON_COLOR_ARG_C_ZERO |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+
+ /* GL_DECAL = 0x008c2d42
+ */
+ (RADEON_COLOR_ARG_A_CURRENT_COLOR |
+ RADEON_COLOR_ARG_B_T0_COLOR |
+ RADEON_COLOR_ARG_C_T0_ALPHA |
+ RADEON_BLEND_CTL_BLEND |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+
+ /* GL_BLEND = 0x008c2902
+ */
+ (RADEON_COLOR_ARG_A_CURRENT_COLOR |
+ RADEON_COLOR_ARG_B_TFACTOR_COLOR |
+ RADEON_COLOR_ARG_C_T0_COLOR |
+ RADEON_BLEND_CTL_BLEND |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+
+ /* GL_ADD = 0x00812802
+ */
+ (RADEON_COLOR_ARG_A_CURRENT_COLOR |
+ RADEON_COLOR_ARG_B_ZERO |
+ RADEON_COLOR_ARG_C_T0_COLOR |
+ RADEON_COMP_ARG_B |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+ },
+
+ /* Unit 1:
+ */
+ {
+ /* Disable combiner stage
+ */
+ (RADEON_COLOR_ARG_A_ZERO |
+ RADEON_COLOR_ARG_B_ZERO |
+ RADEON_COLOR_ARG_C_CURRENT_COLOR |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+
+ /* GL_REPLACE = 0x00803000
+ */
+ (RADEON_COLOR_ARG_A_ZERO |
+ RADEON_COLOR_ARG_B_ZERO |
+ RADEON_COLOR_ARG_C_T1_COLOR |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+
+ /* GL_MODULATE = 0x00800182
+ */
+ (RADEON_COLOR_ARG_A_CURRENT_COLOR |
+ RADEON_COLOR_ARG_B_T1_COLOR |
+ RADEON_COLOR_ARG_C_ZERO |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+
+ /* GL_DECAL = 0x008c3582
+ */
+ (RADEON_COLOR_ARG_A_CURRENT_COLOR |
+ RADEON_COLOR_ARG_B_T1_COLOR |
+ RADEON_COLOR_ARG_C_T1_ALPHA |
+ RADEON_BLEND_CTL_BLEND |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+
+ /* GL_BLEND = 0x008c3102
+ */
+ (RADEON_COLOR_ARG_A_CURRENT_COLOR |
+ RADEON_COLOR_ARG_B_TFACTOR_COLOR |
+ RADEON_COLOR_ARG_C_T1_COLOR |
+ RADEON_BLEND_CTL_BLEND |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+
+ /* GL_ADD = 0x00813002
+ */
+ (RADEON_COLOR_ARG_A_CURRENT_COLOR |
+ RADEON_COLOR_ARG_B_ZERO |
+ RADEON_COLOR_ARG_C_T1_COLOR |
+ RADEON_COMP_ARG_B |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+ },
+
+ /* Unit 2:
+ */
+ {
+ /* Disable combiner stage
+ */
+ (RADEON_COLOR_ARG_A_ZERO |
+ RADEON_COLOR_ARG_B_ZERO |
+ RADEON_COLOR_ARG_C_CURRENT_COLOR |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+
+ /* GL_REPLACE = 0x00803800
+ */
+ (RADEON_COLOR_ARG_A_ZERO |
+ RADEON_COLOR_ARG_B_ZERO |
+ RADEON_COLOR_ARG_C_T2_COLOR |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+
+ /* GL_MODULATE = 0x008001c2
+ */
+ (RADEON_COLOR_ARG_A_CURRENT_COLOR |
+ RADEON_COLOR_ARG_B_T2_COLOR |
+ RADEON_COLOR_ARG_C_ZERO |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+
+ /* GL_DECAL = 0x008c3dc2
+ */
+ (RADEON_COLOR_ARG_A_CURRENT_COLOR |
+ RADEON_COLOR_ARG_B_T2_COLOR |
+ RADEON_COLOR_ARG_C_T2_ALPHA |
+ RADEON_BLEND_CTL_BLEND |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+
+ /* GL_BLEND = 0x008c3902
+ */
+ (RADEON_COLOR_ARG_A_CURRENT_COLOR |
+ RADEON_COLOR_ARG_B_TFACTOR_COLOR |
+ RADEON_COLOR_ARG_C_T2_COLOR |
+ RADEON_BLEND_CTL_BLEND |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+
+ /* GL_ADD = 0x00813802
+ */
+ (RADEON_COLOR_ARG_A_CURRENT_COLOR |
+ RADEON_COLOR_ARG_B_ZERO |
+ RADEON_COLOR_ARG_C_T2_COLOR |
+ RADEON_COMP_ARG_B |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+ }
+};
+
+static GLuint radeon_alpha_combine[][RADEON_MAX_COMBFUNC] =
+{
+ /* Unit 0:
+ */
+ {
+ /* Disable combiner stage
+ */
+ (RADEON_ALPHA_ARG_A_ZERO |
+ RADEON_ALPHA_ARG_B_ZERO |
+ RADEON_ALPHA_ARG_C_CURRENT_ALPHA |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+
+ /* GL_REPLACE = 0x00800500
+ */
+ (RADEON_ALPHA_ARG_A_ZERO |
+ RADEON_ALPHA_ARG_B_ZERO |
+ RADEON_ALPHA_ARG_C_T0_ALPHA |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+
+ /* GL_MODULATE = 0x00800051
+ */
+ (RADEON_ALPHA_ARG_A_CURRENT_ALPHA |
+ RADEON_ALPHA_ARG_B_T0_ALPHA |
+ RADEON_ALPHA_ARG_C_ZERO |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+
+ /* GL_DECAL = 0x00800100
+ */
+ (RADEON_ALPHA_ARG_A_ZERO |
+ RADEON_ALPHA_ARG_B_ZERO |
+ RADEON_ALPHA_ARG_C_CURRENT_ALPHA |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+
+ /* GL_BLEND = 0x00800051
+ */
+ (RADEON_ALPHA_ARG_A_CURRENT_ALPHA |
+ RADEON_ALPHA_ARG_B_TFACTOR_ALPHA |
+ RADEON_ALPHA_ARG_C_T0_ALPHA |
+ RADEON_BLEND_CTL_BLEND |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+
+ /* GL_ADD = 0x00800051
+ */
+ (RADEON_ALPHA_ARG_A_CURRENT_ALPHA |
+ RADEON_ALPHA_ARG_B_ZERO |
+ RADEON_ALPHA_ARG_C_T0_ALPHA |
+ RADEON_COMP_ARG_B |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+ },
+
+ /* Unit 1:
+ */
+ {
+ /* Disable combiner stage
+ */
+ (RADEON_ALPHA_ARG_A_ZERO |
+ RADEON_ALPHA_ARG_B_ZERO |
+ RADEON_ALPHA_ARG_C_CURRENT_ALPHA |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+
+ /* GL_REPLACE = 0x00800600
+ */
+ (RADEON_ALPHA_ARG_A_ZERO |
+ RADEON_ALPHA_ARG_B_ZERO |
+ RADEON_ALPHA_ARG_C_T1_ALPHA |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+
+ /* GL_MODULATE = 0x00800061
+ */
+ (RADEON_ALPHA_ARG_A_CURRENT_ALPHA |
+ RADEON_ALPHA_ARG_B_T1_ALPHA |
+ RADEON_ALPHA_ARG_C_ZERO |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+
+ /* GL_DECAL = 0x00800100
+ */
+ (RADEON_ALPHA_ARG_A_ZERO |
+ RADEON_ALPHA_ARG_B_ZERO |
+ RADEON_ALPHA_ARG_C_CURRENT_ALPHA |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+
+ /* GL_BLEND = 0x00800061
+ */
+ (RADEON_ALPHA_ARG_A_CURRENT_ALPHA |
+ RADEON_ALPHA_ARG_B_TFACTOR_ALPHA |
+ RADEON_ALPHA_ARG_C_T1_ALPHA |
+ RADEON_BLEND_CTL_BLEND |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+
+ /* GL_ADD = 0x00800061
+ */
+ (RADEON_ALPHA_ARG_A_CURRENT_ALPHA |
+ RADEON_ALPHA_ARG_B_ZERO |
+ RADEON_ALPHA_ARG_C_T1_ALPHA |
+ RADEON_COMP_ARG_B |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+ },
+
+ /* Unit 2:
+ */
+ {
+ /* Disable combiner stage
+ */
+ (RADEON_ALPHA_ARG_A_ZERO |
+ RADEON_ALPHA_ARG_B_ZERO |
+ RADEON_ALPHA_ARG_C_CURRENT_ALPHA |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+
+ /* GL_REPLACE = 0x00800700
+ */
+ (RADEON_ALPHA_ARG_A_ZERO |
+ RADEON_ALPHA_ARG_B_ZERO |
+ RADEON_ALPHA_ARG_C_T2_ALPHA |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+
+ /* GL_MODULATE = 0x00800071
+ */
+ (RADEON_ALPHA_ARG_A_CURRENT_ALPHA |
+ RADEON_ALPHA_ARG_B_T2_ALPHA |
+ RADEON_ALPHA_ARG_C_ZERO |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+
+ /* GL_DECAL = 0x00800100
+ */
+ (RADEON_ALPHA_ARG_A_ZERO |
+ RADEON_ALPHA_ARG_B_ZERO |
+ RADEON_ALPHA_ARG_C_CURRENT_ALPHA |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+
+ /* GL_BLEND = 0x00800071
+ */
+ (RADEON_ALPHA_ARG_A_CURRENT_ALPHA |
+ RADEON_ALPHA_ARG_B_TFACTOR_ALPHA |
+ RADEON_ALPHA_ARG_C_T2_ALPHA |
+ RADEON_BLEND_CTL_BLEND |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+
+ /* GL_ADD = 0x00800021
+ */
+ (RADEON_ALPHA_ARG_A_CURRENT_ALPHA |
+ RADEON_ALPHA_ARG_B_ZERO |
+ RADEON_ALPHA_ARG_C_T2_ALPHA |
+ RADEON_COMP_ARG_B |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_SCALE_1X |
+ RADEON_CLAMP_TX),
+ }
+};
+
+
+/* GL_ARB_texture_env_combine support
+ */
+
+/* The color tables have combine functions for GL_SRC_COLOR,
+ * GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
+ */
+static GLuint radeon_texture_color[][RADEON_MAX_TEXTURE_UNITS] =
+{
+ {
+ RADEON_COLOR_ARG_A_T0_COLOR,
+ RADEON_COLOR_ARG_A_T1_COLOR,
+ RADEON_COLOR_ARG_A_T2_COLOR
+ },
+ {
+ RADEON_COLOR_ARG_A_T0_COLOR | RADEON_COMP_ARG_A,
+ RADEON_COLOR_ARG_A_T1_COLOR | RADEON_COMP_ARG_A,
+ RADEON_COLOR_ARG_A_T2_COLOR | RADEON_COMP_ARG_A
+ },
+ {
+ RADEON_COLOR_ARG_A_T0_ALPHA,
+ RADEON_COLOR_ARG_A_T1_ALPHA,
+ RADEON_COLOR_ARG_A_T2_ALPHA
+ },
+ {
+ RADEON_COLOR_ARG_A_T0_ALPHA | RADEON_COMP_ARG_A,
+ RADEON_COLOR_ARG_A_T1_ALPHA | RADEON_COMP_ARG_A,
+ RADEON_COLOR_ARG_A_T2_ALPHA | RADEON_COMP_ARG_A
+ },
+};
+
+static GLuint radeon_tfactor_color[] =
+{
+ RADEON_COLOR_ARG_A_TFACTOR_COLOR,
+ RADEON_COLOR_ARG_A_TFACTOR_COLOR | RADEON_COMP_ARG_A,
+ RADEON_COLOR_ARG_A_TFACTOR_ALPHA,
+ RADEON_COLOR_ARG_A_TFACTOR_ALPHA | RADEON_COMP_ARG_A
+};
+
+static GLuint radeon_primary_color[] =
+{
+ RADEON_COLOR_ARG_A_DIFFUSE_COLOR,
+ RADEON_COLOR_ARG_A_DIFFUSE_COLOR | RADEON_COMP_ARG_A,
+ RADEON_COLOR_ARG_A_DIFFUSE_ALPHA,
+ RADEON_COLOR_ARG_A_DIFFUSE_ALPHA | RADEON_COMP_ARG_A
+};
+
+static GLuint radeon_previous_color[] =
+{
+ RADEON_COLOR_ARG_A_CURRENT_COLOR,
+ RADEON_COLOR_ARG_A_CURRENT_COLOR | RADEON_COMP_ARG_A,
+ RADEON_COLOR_ARG_A_CURRENT_ALPHA,
+ RADEON_COLOR_ARG_A_CURRENT_ALPHA | RADEON_COMP_ARG_A
+};
+
+/* GL_ZERO table - indices 0-3
+ * GL_ONE table - indices 1-4
+ */
+static GLuint radeon_zero_color[] =
+{
+ RADEON_COLOR_ARG_A_ZERO,
+ RADEON_COLOR_ARG_A_ZERO | RADEON_COMP_ARG_A,
+ RADEON_COLOR_ARG_A_ZERO,
+ RADEON_COLOR_ARG_A_ZERO | RADEON_COMP_ARG_A,
+ RADEON_COLOR_ARG_A_ZERO
+};
+
+
+/* The alpha tables only have GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
+ */
+static GLuint radeon_texture_alpha[][RADEON_MAX_TEXTURE_UNITS] =
+{
+ {
+ RADEON_ALPHA_ARG_A_T0_ALPHA,
+ RADEON_ALPHA_ARG_A_T1_ALPHA,
+ RADEON_ALPHA_ARG_A_T2_ALPHA
+ },
+ {
+ RADEON_ALPHA_ARG_A_T0_ALPHA | RADEON_COMP_ARG_A,
+ RADEON_ALPHA_ARG_A_T1_ALPHA | RADEON_COMP_ARG_A,
+ RADEON_ALPHA_ARG_A_T2_ALPHA | RADEON_COMP_ARG_A
+ },
+};
+
+static GLuint radeon_tfactor_alpha[] =
+{
+ RADEON_ALPHA_ARG_A_TFACTOR_ALPHA,
+ RADEON_ALPHA_ARG_A_TFACTOR_ALPHA | RADEON_COMP_ARG_A
+};
+
+static GLuint radeon_primary_alpha[] =
+{
+ RADEON_ALPHA_ARG_A_DIFFUSE_ALPHA,
+ RADEON_ALPHA_ARG_A_DIFFUSE_ALPHA | RADEON_COMP_ARG_A
+};
+
+static GLuint radeon_previous_alpha[] =
+{
+ RADEON_ALPHA_ARG_A_CURRENT_ALPHA,
+ RADEON_ALPHA_ARG_A_CURRENT_ALPHA | RADEON_COMP_ARG_A
+};
+
+/* GL_ZERO table - indices 0-1
+ * GL_ONE table - indices 1-2
+ */
+static GLuint radeon_zero_alpha[] =
+{
+ RADEON_ALPHA_ARG_A_ZERO,
+ RADEON_ALPHA_ARG_A_ZERO | RADEON_COMP_ARG_A,
+ RADEON_ALPHA_ARG_A_ZERO
+};
+
+
+/* Extract the arg from slot A, shift it into the correct argument slot
+ * and set the corresponding complement bit.
+ */
+#define RADEON_COLOR_ARG( n, arg ) \
+do { \
+ color_combine |= \
+ ((color_arg[n] & RADEON_COLOR_ARG_MASK) \
+ << RADEON_COLOR_ARG_##arg##_SHIFT); \
+ color_combine |= \
+ ((color_arg[n] >> RADEON_COMP_ARG_SHIFT) \
+ << RADEON_COMP_ARG_##arg##_SHIFT); \
+} while (0)
+
+#define RADEON_ALPHA_ARG( n, arg ) \
+do { \
+ alpha_combine |= \
+ ((alpha_arg[n] & RADEON_ALPHA_ARG_MASK) \
+ << RADEON_ALPHA_ARG_##arg##_SHIFT); \
+ alpha_combine |= \
+ ((alpha_arg[n] >> RADEON_COMP_ARG_SHIFT) \
+ << RADEON_COMP_ARG_##arg##_SHIFT); \
+} while (0)
+
+
+/* ================================================================
+ * Texture unit state management
+ */
+
+static GLboolean radeonUpdateTextureEnv( GLcontext *ctx, int unit )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+ GLuint color_combine, alpha_combine;
+
+ /* texUnit->_Current can be NULL if and only if the texture unit is
+ * not actually enabled.
+ */
+ assert( (texUnit->_ReallyEnabled == 0)
+ || (texUnit->_Current != NULL) );
+
+ if ( RADEON_DEBUG & DEBUG_TEXTURE ) {
+ fprintf( stderr, "%s( %p, %d )\n", __FUNCTION__, ctx, unit );
+ }
+
+ /* Set the texture environment state. Isn't this nice and clean?
+ * The chip will automagically set the texture alpha to 0xff when
+ * the texture format does not include an alpha component. This
+ * reduces the amount of special-casing we have to do, alpha-only
+ * textures being a notable exception.
+ */
+ if ( !texUnit->_ReallyEnabled ) {
+ /* Don't cache these results.
+ */
+ rmesa->state.texture.unit[unit].format = 0;
+ rmesa->state.texture.unit[unit].envMode = 0;
+ color_combine = radeon_color_combine[unit][RADEON_DISABLE];
+ alpha_combine = radeon_alpha_combine[unit][RADEON_DISABLE];
+ }
+ else {
+ const struct gl_texture_object *tObj = texUnit->_Current;
+ const GLenum format = tObj->Image[tObj->BaseLevel]->Format;
+ GLuint color_arg[3], alpha_arg[3];
+ GLuint i, numColorArgs = 0, numAlphaArgs = 0;
+ GLuint RGBshift = texUnit->CombineScaleShiftRGB;
+ GLuint Ashift = texUnit->CombineScaleShiftA;
+
+ switch ( texUnit->EnvMode ) {
+ case GL_REPLACE:
+ switch ( format ) {
+ case GL_RGBA:
+ case GL_LUMINANCE_ALPHA:
+ case GL_INTENSITY:
+ color_combine = radeon_color_combine[unit][RADEON_REPLACE];
+ alpha_combine = radeon_alpha_combine[unit][RADEON_REPLACE];
+ break;
+ case GL_ALPHA:
+ color_combine = radeon_color_combine[unit][RADEON_DISABLE];
+ alpha_combine = radeon_alpha_combine[unit][RADEON_REPLACE];
+ break;
+ case GL_LUMINANCE:
+ case GL_RGB:
+ case GL_YCBCR_MESA:
+ color_combine = radeon_color_combine[unit][RADEON_REPLACE];
+ alpha_combine = radeon_alpha_combine[unit][RADEON_DISABLE];
+ break;
+ case GL_COLOR_INDEX:
+ default:
+ return GL_FALSE;
+ }
+ break;
+
+ case GL_MODULATE:
+ switch ( format ) {
+ case GL_RGBA:
+ case GL_LUMINANCE_ALPHA:
+ case GL_INTENSITY:
+ color_combine = radeon_color_combine[unit][RADEON_MODULATE];
+ alpha_combine = radeon_alpha_combine[unit][RADEON_MODULATE];
+ break;
+ case GL_ALPHA:
+ color_combine = radeon_color_combine[unit][RADEON_DISABLE];
+ alpha_combine = radeon_alpha_combine[unit][RADEON_MODULATE];
+ break;
+ case GL_RGB:
+ case GL_LUMINANCE:
+ case GL_YCBCR_MESA:
+ color_combine = radeon_color_combine[unit][RADEON_MODULATE];
+ alpha_combine = radeon_alpha_combine[unit][RADEON_DISABLE];
+ break;
+ case GL_COLOR_INDEX:
+ default:
+ return GL_FALSE;
+ }
+ break;
+
+ case GL_DECAL:
+ switch ( format ) {
+ case GL_RGBA:
+ case GL_RGB:
+ case GL_YCBCR_MESA:
+ color_combine = radeon_color_combine[unit][RADEON_DECAL];
+ alpha_combine = radeon_alpha_combine[unit][RADEON_DISABLE];
+ break;
+ case GL_ALPHA:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ case GL_INTENSITY:
+ color_combine = radeon_color_combine[unit][RADEON_DISABLE];
+ alpha_combine = radeon_alpha_combine[unit][RADEON_DISABLE];
+ break;
+ case GL_COLOR_INDEX:
+ default:
+ return GL_FALSE;
+ }
+ break;
+
+ case GL_BLEND:
+ switch ( format ) {
+ case GL_RGBA:
+ case GL_RGB:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ case GL_YCBCR_MESA:
+ color_combine = radeon_color_combine[unit][RADEON_BLEND];
+ alpha_combine = radeon_alpha_combine[unit][RADEON_MODULATE];
+ break;
+ case GL_ALPHA:
+ color_combine = radeon_color_combine[unit][RADEON_DISABLE];
+ alpha_combine = radeon_alpha_combine[unit][RADEON_MODULATE];
+ break;
+ case GL_INTENSITY:
+ color_combine = radeon_color_combine[unit][RADEON_BLEND];
+ alpha_combine = radeon_alpha_combine[unit][RADEON_BLEND];
+ break;
+ case GL_COLOR_INDEX:
+ default:
+ return GL_FALSE;
+ }
+ break;
+
+ case GL_ADD:
+ switch ( format ) {
+ case GL_RGBA:
+ case GL_RGB:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ case GL_YCBCR_MESA:
+ color_combine = radeon_color_combine[unit][RADEON_ADD];
+ alpha_combine = radeon_alpha_combine[unit][RADEON_MODULATE];
+ break;
+ case GL_ALPHA:
+ color_combine = radeon_color_combine[unit][RADEON_DISABLE];
+ alpha_combine = radeon_alpha_combine[unit][RADEON_MODULATE];
+ break;
+ case GL_INTENSITY:
+ color_combine = radeon_color_combine[unit][RADEON_ADD];
+ alpha_combine = radeon_alpha_combine[unit][RADEON_ADD];
+ break;
+ case GL_COLOR_INDEX:
+ default:
+ return GL_FALSE;
+ }
+ break;
+
+ case GL_COMBINE:
+ /* Don't cache these results.
+ */
+ rmesa->state.texture.unit[unit].format = 0;
+ rmesa->state.texture.unit[unit].envMode = 0;
+
+ /* Step 0:
+ * Calculate how many arguments we need to process.
+ */
+ switch ( texUnit->CombineModeRGB ) {
+ case GL_REPLACE:
+ numColorArgs = 1;
+ break;
+ case GL_MODULATE:
+ case GL_ADD:
+ case GL_ADD_SIGNED:
+ case GL_SUBTRACT:
+ case GL_DOT3_RGB:
+ case GL_DOT3_RGBA:
+ case GL_DOT3_RGB_EXT:
+ case GL_DOT3_RGBA_EXT:
+ 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->CombineModeA ) {
+ case GL_REPLACE:
+ numAlphaArgs = 1;
+ break;
+ case GL_MODULATE:
+ case GL_ADD:
+ case GL_ADD_SIGNED:
+ case GL_SUBTRACT:
+ numAlphaArgs = 2;
+ break;
+ case GL_INTERPOLATE:
+ case GL_MODULATE_ADD_ATI:
+ case GL_MODULATE_SIGNED_ADD_ATI:
+ case GL_MODULATE_SUBTRACT_ATI:
+ numAlphaArgs = 3;
+ break;
+ default:
+ return GL_FALSE;
+ }
+
+ /* Step 1:
+ * Extract the color and alpha combine function arguments.
+ */
+ for ( i = 0 ; i < numColorArgs ; i++ ) {
+ const GLuint op = texUnit->CombineOperandRGB[i] - GL_SRC_COLOR;
+ assert(op >= 0);
+ assert(op <= 3);
+ switch ( texUnit->CombineSourceRGB[i] ) {
+ case GL_TEXTURE:
+ color_arg[i] = radeon_texture_color[op][unit];
+ break;
+ case GL_CONSTANT:
+ color_arg[i] = radeon_tfactor_color[op];
+ break;
+ case GL_PRIMARY_COLOR:
+ color_arg[i] = radeon_primary_color[op];
+ break;
+ case GL_PREVIOUS:
+ color_arg[i] = radeon_previous_color[op];
+ break;
+ case GL_ZERO:
+ color_arg[i] = radeon_zero_color[op];
+ break;
+ case GL_ONE:
+ color_arg[i] = radeon_zero_color[op+1];
+ break;
+ default:
+ return GL_FALSE;
+ }
+ }
+
+ for ( i = 0 ; i < numAlphaArgs ; i++ ) {
+ const GLuint op = texUnit->CombineOperandA[i] - GL_SRC_ALPHA;
+ assert(op >= 0);
+ assert(op <= 1);
+ switch ( texUnit->CombineSourceA[i] ) {
+ case GL_TEXTURE:
+ alpha_arg[i] = radeon_texture_alpha[op][unit];
+ break;
+ case GL_CONSTANT:
+ alpha_arg[i] = radeon_tfactor_alpha[op];
+ break;
+ case GL_PRIMARY_COLOR:
+ alpha_arg[i] = radeon_primary_alpha[op];
+ break;
+ case GL_PREVIOUS:
+ alpha_arg[i] = radeon_previous_alpha[op];
+ break;
+ case GL_ZERO:
+ alpha_arg[i] = radeon_zero_alpha[op];
+ break;
+ case GL_ONE:
+ alpha_arg[i] = radeon_zero_alpha[op+1];
+ break;
+ default:
+ return GL_FALSE;
+ }
+ }
+
+ /* Step 2:
+ * Build up the color and alpha combine functions.
+ */
+ switch ( texUnit->CombineModeRGB ) {
+ case GL_REPLACE:
+ color_combine = (RADEON_COLOR_ARG_A_ZERO |
+ RADEON_COLOR_ARG_B_ZERO |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_CLAMP_TX);
+ RADEON_COLOR_ARG( 0, C );
+ break;
+ case GL_MODULATE:
+ color_combine = (RADEON_COLOR_ARG_C_ZERO |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_CLAMP_TX);
+ RADEON_COLOR_ARG( 0, A );
+ RADEON_COLOR_ARG( 1, B );
+ break;
+ case GL_ADD:
+ color_combine = (RADEON_COLOR_ARG_B_ZERO |
+ RADEON_COMP_ARG_B |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_CLAMP_TX);
+ RADEON_COLOR_ARG( 0, A );
+ RADEON_COLOR_ARG( 1, C );
+ break;
+ case GL_ADD_SIGNED:
+ color_combine = (RADEON_COLOR_ARG_B_ZERO |
+ RADEON_COMP_ARG_B |
+ RADEON_BLEND_CTL_ADDSIGNED |
+ RADEON_CLAMP_TX);
+ RADEON_COLOR_ARG( 0, A );
+ RADEON_COLOR_ARG( 1, C );
+ break;
+ case GL_SUBTRACT:
+ color_combine = (RADEON_COLOR_ARG_B_ZERO |
+ RADEON_COMP_ARG_B |
+ RADEON_BLEND_CTL_SUBTRACT |
+ RADEON_CLAMP_TX);
+ RADEON_COLOR_ARG( 0, A );
+ RADEON_COLOR_ARG( 1, C );
+ break;
+ case GL_INTERPOLATE:
+ color_combine = (RADEON_BLEND_CTL_BLEND |
+ RADEON_CLAMP_TX);
+ RADEON_COLOR_ARG( 0, B );
+ RADEON_COLOR_ARG( 1, A );
+ RADEON_COLOR_ARG( 2, C );
+ break;
+
+ case GL_DOT3_RGB_EXT:
+ case GL_DOT3_RGBA_EXT:
+ /* The EXT version of the DOT3 extension does not support the
+ * scale factor, but the ARB version (and the version in OpenGL
+ * 1.3) does.
+ */
+ RGBshift = 0;
+ Ashift = 0;
+ /* FALLTHROUGH */
+
+ case GL_DOT3_RGB:
+ case GL_DOT3_RGBA:
+ /* The R100 / RV200 only support a 1X multiplier in hardware
+ * w/the ARB version.
+ */
+ if ( RGBshift != (RADEON_SCALE_1X >> RADEON_SCALE_SHIFT) ) {
+ return GL_FALSE;
+ }
+
+ RGBshift += 2;
+ Ashift = RGBshift;
+
+ color_combine = (RADEON_COLOR_ARG_C_ZERO |
+ RADEON_BLEND_CTL_DOT3 |
+ RADEON_CLAMP_TX);
+ RADEON_COLOR_ARG( 0, A );
+ RADEON_COLOR_ARG( 1, B );
+ break;
+
+ case GL_MODULATE_ADD_ATI:
+ color_combine = (RADEON_BLEND_CTL_ADD |
+ RADEON_CLAMP_TX);
+ RADEON_COLOR_ARG( 0, A );
+ RADEON_COLOR_ARG( 1, C );
+ RADEON_COLOR_ARG( 2, B );
+ break;
+ case GL_MODULATE_SIGNED_ADD_ATI:
+ color_combine = (RADEON_BLEND_CTL_ADDSIGNED |
+ RADEON_CLAMP_TX);
+ RADEON_COLOR_ARG( 0, A );
+ RADEON_COLOR_ARG( 1, C );
+ RADEON_COLOR_ARG( 2, B );
+ break;
+ case GL_MODULATE_SUBTRACT_ATI:
+ color_combine = (RADEON_BLEND_CTL_SUBTRACT |
+ RADEON_CLAMP_TX);
+ RADEON_COLOR_ARG( 0, A );
+ RADEON_COLOR_ARG( 1, C );
+ RADEON_COLOR_ARG( 2, B );
+ break;
+ default:
+ return GL_FALSE;
+ }
+
+ switch ( texUnit->CombineModeA ) {
+ case GL_REPLACE:
+ alpha_combine = (RADEON_ALPHA_ARG_A_ZERO |
+ RADEON_ALPHA_ARG_B_ZERO |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_CLAMP_TX);
+ RADEON_ALPHA_ARG( 0, C );
+ break;
+ case GL_MODULATE:
+ alpha_combine = (RADEON_ALPHA_ARG_C_ZERO |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_CLAMP_TX);
+ RADEON_ALPHA_ARG( 0, A );
+ RADEON_ALPHA_ARG( 1, B );
+ break;
+ case GL_ADD:
+ alpha_combine = (RADEON_ALPHA_ARG_B_ZERO |
+ RADEON_COMP_ARG_B |
+ RADEON_BLEND_CTL_ADD |
+ RADEON_CLAMP_TX);
+ RADEON_ALPHA_ARG( 0, A );
+ RADEON_ALPHA_ARG( 1, C );
+ break;
+ case GL_ADD_SIGNED:
+ alpha_combine = (RADEON_ALPHA_ARG_B_ZERO |
+ RADEON_COMP_ARG_B |
+ RADEON_BLEND_CTL_ADDSIGNED |
+ RADEON_CLAMP_TX);
+ RADEON_ALPHA_ARG( 0, A );
+ RADEON_ALPHA_ARG( 1, C );
+ break;
+ case GL_SUBTRACT:
+ alpha_combine = (RADEON_COLOR_ARG_B_ZERO |
+ RADEON_COMP_ARG_B |
+ RADEON_BLEND_CTL_SUBTRACT |
+ RADEON_CLAMP_TX);
+ RADEON_ALPHA_ARG( 0, A );
+ RADEON_ALPHA_ARG( 1, C );
+ break;
+ case GL_INTERPOLATE:
+ alpha_combine = (RADEON_BLEND_CTL_BLEND |
+ RADEON_CLAMP_TX);
+ RADEON_ALPHA_ARG( 0, B );
+ RADEON_ALPHA_ARG( 1, A );
+ RADEON_ALPHA_ARG( 2, C );
+ break;
+
+ case GL_MODULATE_ADD_ATI:
+ alpha_combine = (RADEON_BLEND_CTL_ADD |
+ RADEON_CLAMP_TX);
+ RADEON_ALPHA_ARG( 0, A );
+ RADEON_ALPHA_ARG( 1, C );
+ RADEON_ALPHA_ARG( 2, B );
+ break;
+ case GL_MODULATE_SIGNED_ADD_ATI:
+ alpha_combine = (RADEON_BLEND_CTL_ADDSIGNED |
+ RADEON_CLAMP_TX);
+ RADEON_ALPHA_ARG( 0, A );
+ RADEON_ALPHA_ARG( 1, C );
+ RADEON_ALPHA_ARG( 2, B );
+ break;
+ case GL_MODULATE_SUBTRACT_ATI:
+ alpha_combine = (RADEON_BLEND_CTL_SUBTRACT |
+ RADEON_CLAMP_TX);
+ RADEON_ALPHA_ARG( 0, A );
+ RADEON_ALPHA_ARG( 1, C );
+ RADEON_ALPHA_ARG( 2, B );
+ break;
+ default:
+ return GL_FALSE;
+ }
+
+ if ( (texUnit->CombineModeRGB == GL_DOT3_RGB_EXT)
+ || (texUnit->CombineModeRGB == GL_DOT3_RGB) ) {
+ alpha_combine |= RADEON_DOT_ALPHA_DONT_REPLICATE;
+ }
+
+ /* Step 3:
+ * Apply the scale factor.
+ */
+ color_combine |= (RGBshift << RADEON_SCALE_SHIFT);
+ alpha_combine |= (Ashift << RADEON_SCALE_SHIFT);
+
+ /* All done!
+ */
+ break;
+
+ default:
+ return GL_FALSE;
+ }
+ }
+
+ if ( rmesa->hw.tex[unit].cmd[TEX_PP_TXCBLEND] != color_combine ||
+ rmesa->hw.tex[unit].cmd[TEX_PP_TXABLEND] != alpha_combine ) {
+ RADEON_STATECHANGE( rmesa, tex[unit] );
+ rmesa->hw.tex[unit].cmd[TEX_PP_TXCBLEND] = color_combine;
+ rmesa->hw.tex[unit].cmd[TEX_PP_TXABLEND] = alpha_combine;
+ }
+
+ return GL_TRUE;
+}
+
+#define TEXOBJ_TXFILTER_MASK (RADEON_MAX_MIP_LEVEL_MASK | \
+ RADEON_MIN_FILTER_MASK | \
+ RADEON_MAG_FILTER_MASK | \
+ RADEON_MAX_ANISO_MASK | \
+ RADEON_YUV_TO_RGB | \
+ RADEON_YUV_TEMPERATURE_MASK | \
+ RADEON_CLAMP_S_MASK | \
+ RADEON_CLAMP_T_MASK | \
+ RADEON_BORDER_MODE_D3D )
+
+#define TEXOBJ_TXFORMAT_MASK (RADEON_TXFORMAT_WIDTH_MASK | \
+ RADEON_TXFORMAT_HEIGHT_MASK | \
+ RADEON_TXFORMAT_FORMAT_MASK | \
+ RADEON_TXFORMAT_F5_WIDTH_MASK | \
+ RADEON_TXFORMAT_F5_HEIGHT_MASK | \
+ RADEON_TXFORMAT_ALPHA_IN_MAP | \
+ RADEON_TXFORMAT_CUBIC_MAP_ENABLE | \
+ RADEON_TXFORMAT_NON_POWER2)
+
+
+static void import_tex_obj_state( radeonContextPtr rmesa,
+ int unit,
+ radeonTexObjPtr texobj )
+{
+ GLuint *cmd = RADEON_DB_STATE( tex[unit] );
+
+ cmd[TEX_PP_TXFILTER] &= ~TEXOBJ_TXFILTER_MASK;
+ cmd[TEX_PP_TXFILTER] |= texobj->pp_txfilter & TEXOBJ_TXFILTER_MASK;
+ cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
+ cmd[TEX_PP_TXFORMAT] |= texobj->pp_txformat & TEXOBJ_TXFORMAT_MASK;
+ cmd[TEX_PP_TXOFFSET] = texobj->pp_txoffset;
+ cmd[TEX_PP_BORDER_COLOR] = texobj->pp_border_color;
+ RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.tex[unit] );
+
+ if (texobj->base.tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
+ GLuint *txr_cmd = RADEON_DB_STATE( txr[unit] );
+ txr_cmd[TXR_PP_TEX_SIZE] = texobj->pp_txsize; /* NPOT only! */
+ txr_cmd[TXR_PP_TEX_PITCH] = texobj->pp_txpitch; /* NPOT only! */
+ RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.txr[unit] );
+ }
+
+ texobj->dirty_state &= ~(1<<unit);
+}
+
+
+
+
+static void set_texgen_matrix( radeonContextPtr rmesa,
+ GLuint unit,
+ const GLfloat *s_plane,
+ const GLfloat *t_plane )
+{
+ static const GLfloat scale_identity[4] = { 1,1,1,1 };
+
+ if (!TEST_EQ_4V( s_plane, scale_identity) ||
+ !TEST_EQ_4V( t_plane, scale_identity)) {
+ rmesa->TexGenEnabled |= RADEON_TEXMAT_0_ENABLE<<unit;
+ rmesa->TexGenMatrix[unit].m[0] = s_plane[0];
+ rmesa->TexGenMatrix[unit].m[4] = s_plane[1];
+ rmesa->TexGenMatrix[unit].m[8] = s_plane[2];
+ rmesa->TexGenMatrix[unit].m[12] = s_plane[3];
+
+ rmesa->TexGenMatrix[unit].m[1] = t_plane[0];
+ rmesa->TexGenMatrix[unit].m[5] = t_plane[1];
+ rmesa->TexGenMatrix[unit].m[9] = t_plane[2];
+ rmesa->TexGenMatrix[unit].m[13] = t_plane[3];
+ rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
+ }
+}
+
+/* Ignoring the Q texcoord for now.
+ *
+ * Returns GL_FALSE if fallback required.
+ */
+static GLboolean radeon_validate_texgen( GLcontext *ctx, GLuint unit )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+ GLuint inputshift = RADEON_TEXGEN_0_INPUT_SHIFT + unit*4;
+ GLuint tmp = rmesa->TexGenEnabled;
+
+ rmesa->TexGenEnabled &= ~(RADEON_TEXGEN_TEXMAT_0_ENABLE<<unit);
+ rmesa->TexGenEnabled &= ~(RADEON_TEXMAT_0_ENABLE<<unit);
+ rmesa->TexGenEnabled &= ~(RADEON_TEXGEN_INPUT_MASK<<inputshift);
+ rmesa->TexGenNeedNormals[unit] = 0;
+
+ if ((texUnit->TexGenEnabled & (S_BIT|T_BIT)) == 0) {
+ /* Disabled, no fallback:
+ */
+ rmesa->TexGenEnabled |=
+ (RADEON_TEXGEN_INPUT_TEXCOORD_0+unit) << inputshift;
+ return GL_TRUE;
+ }
+ else if (texUnit->TexGenEnabled & Q_BIT) {
+ /* Very easy to do this, in fact would remove a fallback case
+ * elsewhere, but I haven't done it yet... Fallback:
+ */
+ fprintf(stderr, "fallback Q_BIT\n");
+ return GL_FALSE;
+ }
+ else if ((texUnit->TexGenEnabled & (S_BIT|T_BIT)) != (S_BIT|T_BIT) ||
+ texUnit->GenModeS != texUnit->GenModeT) {
+ /* Mixed modes, fallback:
+ */
+ /* fprintf(stderr, "fallback mixed texgen\n"); */
+ return GL_FALSE;
+ }
+ else
+ rmesa->TexGenEnabled |= RADEON_TEXGEN_TEXMAT_0_ENABLE << unit;
+
+ switch (texUnit->GenModeS) {
+ case GL_OBJECT_LINEAR:
+ rmesa->TexGenEnabled |= RADEON_TEXGEN_INPUT_OBJ << inputshift;
+ set_texgen_matrix( rmesa, unit,
+ texUnit->ObjectPlaneS,
+ texUnit->ObjectPlaneT);
+ break;
+
+ case GL_EYE_LINEAR:
+ rmesa->TexGenEnabled |= RADEON_TEXGEN_INPUT_EYE << inputshift;
+ set_texgen_matrix( rmesa, unit,
+ texUnit->EyePlaneS,
+ texUnit->EyePlaneT);
+ break;
+
+ case GL_REFLECTION_MAP_NV:
+ rmesa->TexGenNeedNormals[unit] = GL_TRUE;
+ rmesa->TexGenEnabled |= RADEON_TEXGEN_INPUT_EYE_REFLECT<<inputshift;
+ break;
+
+ case GL_NORMAL_MAP_NV:
+ rmesa->TexGenNeedNormals[unit] = GL_TRUE;
+ rmesa->TexGenEnabled |= RADEON_TEXGEN_INPUT_EYE_NORMAL<<inputshift;
+ break;
+
+ case GL_SPHERE_MAP:
+ default:
+ /* Unsupported mode, fallback:
+ */
+ /* fprintf(stderr, "fallback unsupported texgen\n"); */
+ return GL_FALSE;
+ }
+
+ if (tmp != rmesa->TexGenEnabled) {
+ rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
+ }
+
+ return GL_TRUE;
+}
+
+
+static void disable_tex( GLcontext *ctx, int unit )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ if (rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (RADEON_TEX_0_ENABLE<<unit)) {
+ /* Texture unit disabled */
+ if ( rmesa->state.texture.unit[unit].texobj != NULL ) {
+ /* The old texture is no longer bound to this texture unit.
+ * Mark it as such.
+ */
+
+ rmesa->state.texture.unit[unit].texobj->base.bound &= ~(1UL << unit);
+ rmesa->state.texture.unit[unit].texobj = NULL;
+ }
+
+ RADEON_STATECHANGE( rmesa, ctx );
+ rmesa->hw.ctx.cmd[CTX_PP_CNTL] &=
+ ~((RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE) << unit);
+
+ RADEON_STATECHANGE( rmesa, tcl );
+ switch (unit) {
+ case 0:
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~(RADEON_TCL_VTX_ST0 |
+ RADEON_TCL_VTX_Q0);
+ break;
+ case 1:
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~(RADEON_TCL_VTX_ST1 |
+ RADEON_TCL_VTX_Q1);
+ break;
+ default:
+ break;
+ }
+
+
+ if (rmesa->TclFallback & (RADEON_TCL_FALLBACK_TEXGEN_0<<unit)) {
+ TCL_FALLBACK( ctx, (RADEON_TCL_FALLBACK_TEXGEN_0<<unit), GL_FALSE);
+ rmesa->recheck_texgen[unit] = GL_TRUE;
+ }
+
+
+
+ {
+ GLuint inputshift = RADEON_TEXGEN_0_INPUT_SHIFT + unit*4;
+ GLuint tmp = rmesa->TexGenEnabled;
+
+ rmesa->TexGenEnabled &= ~(RADEON_TEXGEN_TEXMAT_0_ENABLE<<unit);
+ rmesa->TexGenEnabled &= ~(RADEON_TEXMAT_0_ENABLE<<unit);
+ rmesa->TexGenEnabled &= ~(RADEON_TEXGEN_INPUT_MASK<<inputshift);
+ rmesa->TexGenNeedNormals[unit] = 0;
+ rmesa->TexGenEnabled |=
+ (RADEON_TEXGEN_INPUT_TEXCOORD_0+unit) << inputshift;
+
+ if (tmp != rmesa->TexGenEnabled) {
+ rmesa->recheck_texgen[unit] = GL_TRUE;
+ rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
+ }
+ }
+ }
+}
+
+static GLboolean enable_tex_2d( GLcontext *ctx, int unit )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+ struct gl_texture_object *tObj = texUnit->_Current;
+ radeonTexObjPtr t = (radeonTexObjPtr) tObj->DriverData;
+
+ /* Need to load the 2d images associated with this unit.
+ */
+ if (t->pp_txformat & RADEON_TXFORMAT_NON_POWER2) {
+ t->pp_txformat &= ~RADEON_TXFORMAT_NON_POWER2;
+ t->base.dirty_images[0] = ~0;
+ }
+
+ ASSERT(tObj->Target == GL_TEXTURE_2D || tObj->Target == GL_TEXTURE_1D);
+
+ if ( t->base.dirty_images[0] ) {
+ RADEON_FIREVERTICES( rmesa );
+ radeonSetTexImages( rmesa, tObj );
+ radeonUploadTexImages( rmesa, (radeonTexObjPtr) tObj->DriverData, 0 );
+ if ( !t->base.memBlock )
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+static GLboolean enable_tex_rect( GLcontext *ctx, int unit )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+ struct gl_texture_object *tObj = texUnit->_Current;
+ radeonTexObjPtr t = (radeonTexObjPtr) tObj->DriverData;
+
+ if (!(t->pp_txformat & RADEON_TXFORMAT_NON_POWER2)) {
+ t->pp_txformat |= RADEON_TXFORMAT_NON_POWER2;
+ t->base.dirty_images[0] = ~0;
+ }
+
+ ASSERT(tObj->Target == GL_TEXTURE_RECTANGLE_NV);
+
+ if ( t->base.dirty_images[0] ) {
+ RADEON_FIREVERTICES( rmesa );
+ radeonSetTexImages( rmesa, tObj );
+ radeonUploadTexImages( rmesa, (radeonTexObjPtr) tObj->DriverData, 0 );
+ if ( !t->base.memBlock /* && !rmesa->prefer_agp_client_texturing FIXME */ ) {
+ fprintf(stderr, "%s: upload failed\n", __FUNCTION__);
+ return GL_FALSE;
+ }
+ }
+
+ return GL_TRUE;
+}
+
+
+static GLboolean update_tex_common( GLcontext *ctx, int unit )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+ struct gl_texture_object *tObj = texUnit->_Current;
+ radeonTexObjPtr t = (radeonTexObjPtr) tObj->DriverData;
+ GLenum format;
+
+ /* Fallback if there's a texture border */
+ if ( tObj->Image[tObj->BaseLevel]->Border > 0 ) {
+ fprintf(stderr, "%s: border\n", __FUNCTION__);
+ return GL_FALSE;
+ }
+
+ /* Update state if this is a different texture object to last
+ * time.
+ */
+ if ( rmesa->state.texture.unit[unit].texobj != t ) {
+ if ( rmesa->state.texture.unit[unit].texobj != NULL ) {
+ /* The old texture is no longer bound to this texture unit.
+ * Mark it as such.
+ */
+
+ rmesa->state.texture.unit[unit].texobj->base.bound &=
+ ~(1UL << unit);
+ }
+
+ rmesa->state.texture.unit[unit].texobj = t;
+ t->base.bound |= (1UL << unit);
+ t->dirty_state |= 1<<unit;
+ driUpdateTextureLRU( (driTextureObject *) t ); /* XXX: should be locked! */
+ }
+
+
+ /* Newly enabled?
+ */
+ if ( !(rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (RADEON_TEX_0_ENABLE<<unit))) {
+ RADEON_STATECHANGE( rmesa, ctx );
+ rmesa->hw.ctx.cmd[CTX_PP_CNTL] |=
+ (RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE) << unit;
+
+ RADEON_STATECHANGE( rmesa, tcl );
+
+ if (unit == 0)
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_ST0;
+ else
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_ST1;
+
+ rmesa->recheck_texgen[unit] = GL_TRUE;
+ }
+
+ if (t->dirty_state & (1<<unit)) {
+ import_tex_obj_state( rmesa, unit, t );
+ }
+
+ if (rmesa->recheck_texgen[unit]) {
+ GLboolean fallback = !radeon_validate_texgen( ctx, unit );
+ TCL_FALLBACK( ctx, (RADEON_TCL_FALLBACK_TEXGEN_0<<unit), fallback);
+ rmesa->recheck_texgen[unit] = 0;
+ rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
+ }
+
+ format = tObj->Image[tObj->BaseLevel]->Format;
+ if ( rmesa->state.texture.unit[unit].format != format ||
+ rmesa->state.texture.unit[unit].envMode != texUnit->EnvMode ) {
+ rmesa->state.texture.unit[unit].format = format;
+ rmesa->state.texture.unit[unit].envMode = texUnit->EnvMode;
+ if ( ! radeonUpdateTextureEnv( ctx, unit ) ) {
+ return GL_FALSE;
+ }
+ }
+
+ FALLBACK( rmesa, RADEON_FALLBACK_BORDER_MODE, t->border_fallback );
+ return !t->border_fallback;
+}
+
+
+
+static GLboolean radeonUpdateTextureUnit( GLcontext *ctx, int unit )
+{
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+
+ TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_TEXRECT_0 << unit, 0 );
+
+ if ( texUnit->_ReallyEnabled & (TEXTURE_RECT_BIT) ) {
+ TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_TEXRECT_0 << unit, 1 );
+
+ return (enable_tex_rect( ctx, unit ) &&
+ update_tex_common( ctx, unit ));
+ }
+ else if ( texUnit->_ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT) ) {
+ return (enable_tex_2d( ctx, unit ) &&
+ update_tex_common( ctx, unit ));
+ }
+ else if ( texUnit->_ReallyEnabled ) {
+ return GL_FALSE;
+ }
+ else {
+ disable_tex( ctx, unit );
+ return GL_TRUE;
+ }
+}
+
+void radeonUpdateTextureState( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLboolean ok;
+
+ ok = (radeonUpdateTextureUnit( ctx, 0 ) &&
+ radeonUpdateTextureUnit( ctx, 1 ));
+
+ FALLBACK( rmesa, RADEON_FALLBACK_TEXTURE, !ok );
+
+ if (rmesa->TclFallback)
+ radeonChooseVertexState( ctx );
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_vtxfmt.c b/src/mesa/drivers/dri/radeon/radeon_vtxfmt.c
new file mode 100644
index 0000000000..b613e9eb43
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_vtxfmt.c
@@ -0,0 +1,1089 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_vtxfmt.c,v 1.5 2002/12/16 16:18:59 dawes Exp $ */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+ Tungsten Graphics Inc., Cedar Park, Texas.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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 "glheader.h"
+#include "imports.h"
+#include "api_noop.h"
+#include "api_arrayelt.h"
+#include "context.h"
+#include "mtypes.h"
+#include "enums.h"
+#include "glapi.h"
+#include "colormac.h"
+#include "light.h"
+#include "state.h"
+#include "vtxfmt.h"
+
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_array_api.h"
+
+#include "radeon_context.h"
+#include "radeon_state.h"
+#include "radeon_ioctl.h"
+#include "radeon_tex.h"
+#include "radeon_tcl.h"
+#include "radeon_swtcl.h"
+#include "radeon_vtxfmt.h"
+
+static void radeonVtxfmtFlushVertices( GLcontext *, GLuint );
+
+static void count_func( const char *name, struct dynfn *l )
+{
+ int i = 0;
+ struct dynfn *f;
+ foreach (f, l) i++;
+ if (i) fprintf(stderr, "%s: %d\n", name, i );
+}
+
+static void count_funcs( radeonContextPtr rmesa )
+{
+ count_func( "Vertex2f", &rmesa->vb.dfn_cache.Vertex2f );
+ count_func( "Vertex2fv", &rmesa->vb.dfn_cache.Vertex2fv );
+ count_func( "Vertex3f", &rmesa->vb.dfn_cache.Vertex3f );
+ count_func( "Vertex3fv", &rmesa->vb.dfn_cache.Vertex3fv );
+ count_func( "Color4ub", &rmesa->vb.dfn_cache.Color4ub );
+ count_func( "Color4ubv", &rmesa->vb.dfn_cache.Color4ubv );
+ count_func( "Color3ub", &rmesa->vb.dfn_cache.Color3ub );
+ count_func( "Color3ubv", &rmesa->vb.dfn_cache.Color3ubv );
+ count_func( "Color4f", &rmesa->vb.dfn_cache.Color4f );
+ count_func( "Color4fv", &rmesa->vb.dfn_cache.Color4fv );
+ count_func( "Color3f", &rmesa->vb.dfn_cache.Color3f );
+ count_func( "Color3fv", &rmesa->vb.dfn_cache.Color3fv );
+ count_func( "SecondaryColor3f", &rmesa->vb.dfn_cache.SecondaryColor3fEXT );
+ count_func( "SecondaryColor3fv", &rmesa->vb.dfn_cache.SecondaryColor3fvEXT );
+ count_func( "SecondaryColor3ub", &rmesa->vb.dfn_cache.SecondaryColor3ubEXT );
+ count_func( "SecondaryColor3ubv", &rmesa->vb.dfn_cache.SecondaryColor3ubvEXT );
+ count_func( "Normal3f", &rmesa->vb.dfn_cache.Normal3f );
+ count_func( "Normal3fv", &rmesa->vb.dfn_cache.Normal3fv );
+ count_func( "TexCoord2f", &rmesa->vb.dfn_cache.TexCoord2f );
+ count_func( "TexCoord2fv", &rmesa->vb.dfn_cache.TexCoord2fv );
+ count_func( "TexCoord1f", &rmesa->vb.dfn_cache.TexCoord1f );
+ count_func( "TexCoord1fv", &rmesa->vb.dfn_cache.TexCoord1fv );
+ count_func( "MultiTexCoord2fARB", &rmesa->vb.dfn_cache.MultiTexCoord2fARB );
+ count_func( "MultiTexCoord2fvARB", &rmesa->vb.dfn_cache.MultiTexCoord2fvARB );
+ count_func( "MultiTexCoord1fARB", &rmesa->vb.dfn_cache.MultiTexCoord1fARB );
+ count_func( "MultiTexCoord1fvARB", &rmesa->vb.dfn_cache.MultiTexCoord1fvARB );
+}
+
+
+void radeon_copy_to_current( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ assert(ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT);
+
+ if (rmesa->vb.vertex_format & RADEON_CP_VC_FRMT_N0) {
+ ctx->Current.Attrib[VERT_ATTRIB_NORMAL][0] = rmesa->vb.normalptr[0];
+ ctx->Current.Attrib[VERT_ATTRIB_NORMAL][1] = rmesa->vb.normalptr[1];
+ ctx->Current.Attrib[VERT_ATTRIB_NORMAL][2] = rmesa->vb.normalptr[2];
+ }
+
+ if (rmesa->vb.vertex_format & RADEON_CP_VC_FRMT_PKCOLOR) {
+ ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0] = UBYTE_TO_FLOAT( rmesa->vb.colorptr->red );
+ ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1] = UBYTE_TO_FLOAT( rmesa->vb.colorptr->green );
+ ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2] = UBYTE_TO_FLOAT( rmesa->vb.colorptr->blue );
+ ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3] = UBYTE_TO_FLOAT( rmesa->vb.colorptr->alpha );
+ }
+
+ if (rmesa->vb.vertex_format & RADEON_CP_VC_FRMT_FPCOLOR) {
+ ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0] = rmesa->vb.floatcolorptr[0];
+ ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1] = rmesa->vb.floatcolorptr[1];
+ ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2] = rmesa->vb.floatcolorptr[2];
+ }
+
+ if (rmesa->vb.vertex_format & RADEON_CP_VC_FRMT_FPALPHA)
+ ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3] = rmesa->vb.floatcolorptr[3];
+
+ if (rmesa->vb.vertex_format & RADEON_CP_VC_FRMT_PKSPEC) {
+ ctx->Current.Attrib[VERT_ATTRIB_COLOR1][0] = UBYTE_TO_FLOAT( rmesa->vb.specptr->red );
+ ctx->Current.Attrib[VERT_ATTRIB_COLOR1][1] = UBYTE_TO_FLOAT( rmesa->vb.specptr->green );
+ ctx->Current.Attrib[VERT_ATTRIB_COLOR1][2] = UBYTE_TO_FLOAT( rmesa->vb.specptr->blue );
+ }
+
+ if (rmesa->vb.vertex_format & RADEON_CP_VC_FRMT_ST0) {
+ ctx->Current.Attrib[VERT_ATTRIB_TEX0][0] = rmesa->vb.texcoordptr[0][0];
+ ctx->Current.Attrib[VERT_ATTRIB_TEX0][1] = rmesa->vb.texcoordptr[0][1];
+ ctx->Current.Attrib[VERT_ATTRIB_TEX0][2] = 0.0F;
+ ctx->Current.Attrib[VERT_ATTRIB_TEX0][3] = 1.0F;
+ }
+
+ if (rmesa->vb.vertex_format & RADEON_CP_VC_FRMT_ST1) {
+ ctx->Current.Attrib[VERT_ATTRIB_TEX1][0] = rmesa->vb.texcoordptr[1][0];
+ ctx->Current.Attrib[VERT_ATTRIB_TEX1][1] = rmesa->vb.texcoordptr[1][1];
+ ctx->Current.Attrib[VERT_ATTRIB_TEX1][2] = 0.0F;
+ ctx->Current.Attrib[VERT_ATTRIB_TEX1][3] = 1.0F;
+ }
+
+ ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT;
+}
+
+static GLboolean discreet_gl_prim[GL_POLYGON+1] = {
+ 1, /* 0 points */
+ 1, /* 1 lines */
+ 0, /* 2 line_strip */
+ 0, /* 3 line_loop */
+ 1, /* 4 tris */
+ 0, /* 5 tri_fan */
+ 0, /* 6 tri_strip */
+ 1, /* 7 quads */
+ 0, /* 8 quadstrip */
+ 0, /* 9 poly */
+};
+
+static void flush_prims( radeonContextPtr rmesa )
+{
+ int i,j;
+ struct radeon_dma_region tmp = rmesa->dma.current;
+
+ tmp.buf->refcount++;
+ tmp.aos_size = rmesa->vb.vertex_size;
+ tmp.aos_stride = rmesa->vb.vertex_size;
+ tmp.aos_start = GET_START(&tmp);
+
+ rmesa->dma.current.ptr = rmesa->dma.current.start +=
+ (rmesa->vb.initial_counter - rmesa->vb.counter) * rmesa->vb.vertex_size * 4;
+
+ rmesa->tcl.vertex_format = rmesa->vb.vertex_format;
+ rmesa->tcl.aos_components[0] = &tmp;
+ rmesa->tcl.nr_aos_components = 1;
+ rmesa->dma.flush = 0;
+
+ /* Optimize the primitive list:
+ */
+ if (rmesa->vb.nrprims > 1) {
+ for (j = 0, i = 1 ; i < rmesa->vb.nrprims; i++) {
+ int pj = rmesa->vb.primlist[j].prim & 0xf;
+ int pi = rmesa->vb.primlist[i].prim & 0xf;
+
+ if (pj == pi && discreet_gl_prim[pj] &&
+ rmesa->vb.primlist[i].start == rmesa->vb.primlist[j].end) {
+ rmesa->vb.primlist[j].end = rmesa->vb.primlist[i].end;
+ }
+ else {
+ j++;
+ if (j != i) rmesa->vb.primlist[j] = rmesa->vb.primlist[i];
+ }
+ }
+ rmesa->vb.nrprims = j+1;
+ }
+
+ for (i = 0 ; i < rmesa->vb.nrprims; i++) {
+ if (RADEON_DEBUG & DEBUG_PRIMS)
+ fprintf(stderr, "vtxfmt prim %d: %s %d..%d\n", i,
+ _mesa_lookup_enum_by_nr( rmesa->vb.primlist[i].prim &
+ PRIM_MODE_MASK ),
+ rmesa->vb.primlist[i].start,
+ rmesa->vb.primlist[i].end);
+
+ radeonEmitPrimitive( rmesa->glCtx,
+ rmesa->vb.primlist[i].start,
+ rmesa->vb.primlist[i].end,
+ rmesa->vb.primlist[i].prim );
+ }
+
+ rmesa->vb.nrprims = 0;
+ radeonReleaseDmaRegion( rmesa, &tmp, __FUNCTION__ );
+}
+
+
+static void start_prim( radeonContextPtr rmesa, GLuint mode )
+{
+ if (RADEON_DEBUG & DEBUG_VFMT)
+ fprintf(stderr, "%s %d\n", __FUNCTION__, rmesa->vb.initial_counter - rmesa->vb.counter);
+
+ rmesa->vb.primlist[rmesa->vb.nrprims].start = rmesa->vb.initial_counter - rmesa->vb.counter;
+ rmesa->vb.primlist[rmesa->vb.nrprims].prim = mode;
+}
+
+static void note_last_prim( radeonContextPtr rmesa, GLuint flags )
+{
+ if (RADEON_DEBUG & DEBUG_VFMT)
+ fprintf(stderr, "%s %d\n", __FUNCTION__, rmesa->vb.initial_counter - rmesa->vb.counter);
+
+ if (rmesa->vb.prim[0] != GL_POLYGON+1) {
+ rmesa->vb.primlist[rmesa->vb.nrprims].prim |= flags;
+ rmesa->vb.primlist[rmesa->vb.nrprims].end = rmesa->vb.initial_counter - rmesa->vb.counter;
+
+ if (++(rmesa->vb.nrprims) == RADEON_MAX_PRIMS)
+ flush_prims( rmesa );
+ }
+}
+
+
+static void copy_vertex( radeonContextPtr rmesa, GLuint n, GLfloat *dst )
+{
+ GLuint i;
+ GLfloat *src = (GLfloat *)(rmesa->dma.current.address +
+ rmesa->dma.current.ptr +
+ (rmesa->vb.primlist[rmesa->vb.nrprims].start + n) *
+ rmesa->vb.vertex_size * 4);
+
+ if (RADEON_DEBUG & DEBUG_VFMT)
+ fprintf(stderr, "copy_vertex %d\n", rmesa->vb.primlist[rmesa->vb.nrprims].start + n);
+
+ for (i = 0 ; i < rmesa->vb.vertex_size; i++) {
+ dst[i] = src[i];
+ }
+}
+
+/* NOTE: This actually reads the copied vertices back from uncached
+ * memory. Could also use the counter/notify mechanism to populate
+ * tmp on the fly as vertices are generated.
+ */
+static GLuint copy_dma_verts( radeonContextPtr rmesa, GLfloat (*tmp)[15] )
+{
+ GLuint ovf, i;
+ GLuint nr = (rmesa->vb.initial_counter - rmesa->vb.counter) - rmesa->vb.primlist[rmesa->vb.nrprims].start;
+
+ if (RADEON_DEBUG & DEBUG_VFMT)
+ fprintf(stderr, "%s %d verts\n", __FUNCTION__, nr);
+
+ switch( rmesa->vb.prim[0] )
+ {
+ case GL_POINTS:
+ return 0;
+ case GL_LINES:
+ ovf = nr&1;
+ for (i = 0 ; i < ovf ; i++)
+ copy_vertex( rmesa, nr-ovf+i, tmp[i] );
+ return i;
+ case GL_TRIANGLES:
+ ovf = nr%3;
+ for (i = 0 ; i < ovf ; i++)
+ copy_vertex( rmesa, nr-ovf+i, tmp[i] );
+ return i;
+ case GL_QUADS:
+ ovf = nr&3;
+ for (i = 0 ; i < ovf ; i++)
+ copy_vertex( rmesa, nr-ovf+i, tmp[i] );
+ return i;
+ case GL_LINE_STRIP:
+ if (nr == 0)
+ return 0;
+ copy_vertex( rmesa, nr-1, tmp[0] );
+ return 1;
+ case GL_LINE_LOOP:
+ case GL_TRIANGLE_FAN:
+ case GL_POLYGON:
+ if (nr == 0)
+ return 0;
+ else if (nr == 1) {
+ copy_vertex( rmesa, 0, tmp[0] );
+ return 1;
+ } else {
+ copy_vertex( rmesa, 0, tmp[0] );
+ copy_vertex( rmesa, nr-1, tmp[1] );
+ return 2;
+ }
+ case GL_TRIANGLE_STRIP:
+ ovf = MIN2(nr, 2);
+ for (i = 0 ; i < ovf ; i++)
+ copy_vertex( rmesa, nr-ovf+i, tmp[i] );
+ return i;
+ case GL_QUAD_STRIP:
+ switch (nr) {
+ case 0: ovf = 0; break;
+ case 1: ovf = 1; break;
+ default: ovf = 2 + (nr&1); break;
+ }
+ for (i = 0 ; i < ovf ; i++)
+ copy_vertex( rmesa, nr-ovf+i, tmp[i] );
+ return i;
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+static void VFMT_FALLBACK_OUTSIDE_BEGIN_END( const char *caller )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ if (RADEON_DEBUG & (DEBUG_VFMT|DEBUG_FALLBACKS))
+ fprintf(stderr, "%s from %s\n", __FUNCTION__, caller);
+
+ if (ctx->Driver.NeedFlush)
+ radeonVtxfmtFlushVertices( ctx, ctx->Driver.NeedFlush );
+
+ if (ctx->NewState)
+ _mesa_update_state( ctx ); /* clear state so fell_back sticks */
+
+ _tnl_wakeup_exec( ctx );
+ ctx->Driver.FlushVertices = radeonFlushVertices;
+
+ assert( rmesa->dma.flush == 0 );
+ rmesa->vb.fell_back = GL_TRUE;
+ rmesa->vb.installed = GL_FALSE;
+}
+
+
+static void VFMT_FALLBACK( const char *caller )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLfloat tmp[3][15];
+ GLuint i, prim;
+ GLuint ind = rmesa->vb.vertex_format;
+ GLuint nrverts;
+ GLfloat alpha = 1.0;
+
+ if (RADEON_DEBUG & (DEBUG_FALLBACKS|DEBUG_VFMT))
+ fprintf(stderr, "%s from %s\n", __FUNCTION__, caller);
+
+ if (rmesa->vb.prim[0] == GL_POLYGON+1) {
+ VFMT_FALLBACK_OUTSIDE_BEGIN_END( __FUNCTION__ );
+ return;
+ }
+
+ /* Copy vertices out of dma:
+ */
+ nrverts = copy_dma_verts( rmesa, tmp );
+
+ /* Finish the prim at this point:
+ */
+ note_last_prim( rmesa, 0 );
+ flush_prims( rmesa );
+
+ /* Update ctx->Driver.CurrentExecPrimitive and swap in swtnl.
+ */
+ prim = rmesa->vb.prim[0];
+ ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1;
+ _tnl_wakeup_exec( ctx );
+ ctx->Driver.FlushVertices = radeonFlushVertices;
+
+ assert(rmesa->dma.flush == 0);
+ rmesa->vb.fell_back = GL_TRUE;
+ rmesa->vb.installed = GL_FALSE;
+ glBegin( prim );
+
+ if (rmesa->vb.installed_color_3f_sz == 4)
+ alpha = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3];
+
+ /* Replay saved vertices
+ */
+ for (i = 0 ; i < nrverts; i++) {
+ GLuint offset = 3;
+ if (ind & RADEON_CP_VC_FRMT_N0) {
+ glNormal3fv( &tmp[i][offset] );
+ offset += 3;
+ }
+
+ if (ind & RADEON_CP_VC_FRMT_PKCOLOR) {
+ radeon_color_t *col = (radeon_color_t *)&tmp[i][offset];
+ glColor4ub( col->red, col->green, col->blue, col->alpha );
+ offset++;
+ }
+ else if (ind & RADEON_CP_VC_FRMT_FPALPHA) {
+ glColor4fv( &tmp[i][offset] );
+ offset+=4;
+ }
+ else if (ind & RADEON_CP_VC_FRMT_FPCOLOR) {
+ glColor3fv( &tmp[i][offset] );
+ offset+=3;
+ }
+
+ if (ind & RADEON_CP_VC_FRMT_PKSPEC) {
+ radeon_color_t *spec = (radeon_color_t *)&tmp[i][offset];
+ _glapi_Dispatch->SecondaryColor3ubEXT( spec->red, spec->green, spec->blue );
+ offset++;
+ }
+
+ if (ind & RADEON_CP_VC_FRMT_ST0) {
+ glTexCoord2fv( &tmp[i][offset] );
+ offset += 2;
+ }
+
+ if (ind & RADEON_CP_VC_FRMT_ST1) {
+ glMultiTexCoord2fvARB( GL_TEXTURE1_ARB, &tmp[i][offset] );
+ offset += 2;
+ }
+ glVertex3fv( &tmp[i][0] );
+ }
+
+ /* Replay current vertex
+ */
+ if (ind & RADEON_CP_VC_FRMT_N0)
+ glNormal3fv( rmesa->vb.normalptr );
+
+ if (ind & RADEON_CP_VC_FRMT_PKCOLOR)
+ glColor4ub( rmesa->vb.colorptr->red, rmesa->vb.colorptr->green, rmesa->vb.colorptr->blue, rmesa->vb.colorptr->alpha );
+ else if (ind & RADEON_CP_VC_FRMT_FPALPHA)
+ glColor4fv( rmesa->vb.floatcolorptr );
+ else if (ind & RADEON_CP_VC_FRMT_FPCOLOR) {
+ if (rmesa->vb.installed_color_3f_sz == 4 && alpha != 1.0)
+ glColor4f( rmesa->vb.floatcolorptr[0],
+ rmesa->vb.floatcolorptr[1],
+ rmesa->vb.floatcolorptr[2],
+ alpha );
+ else
+ glColor3fv( rmesa->vb.floatcolorptr );
+ }
+
+ if (ind & RADEON_CP_VC_FRMT_PKSPEC)
+ _glapi_Dispatch->SecondaryColor3ubEXT( rmesa->vb.specptr->red, rmesa->vb.specptr->green, rmesa->vb.specptr->blue );
+
+ if (ind & RADEON_CP_VC_FRMT_ST0)
+ glTexCoord2fv( rmesa->vb.texcoordptr[0] );
+
+ if (ind & RADEON_CP_VC_FRMT_ST1)
+ glMultiTexCoord2fvARB( GL_TEXTURE1_ARB, rmesa->vb.texcoordptr[1] );
+}
+
+
+
+static void wrap_buffer( void )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLfloat tmp[3][15];
+ GLuint i, nrverts;
+
+ if (RADEON_DEBUG & (DEBUG_VFMT|DEBUG_PRIMS))
+ fprintf(stderr, "%s %d\n", __FUNCTION__, rmesa->vb.initial_counter - rmesa->vb.counter);
+
+ /* Don't deal with parity.
+ */
+ if ((((rmesa->vb.initial_counter - rmesa->vb.counter) -
+ rmesa->vb.primlist[rmesa->vb.nrprims].start) & 1)) {
+ rmesa->vb.counter++;
+ rmesa->vb.initial_counter++;
+ return;
+ }
+
+ /* Copy vertices out of dma:
+ */
+ if (rmesa->vb.prim[0] == GL_POLYGON+1)
+ nrverts = 0;
+ else {
+ nrverts = copy_dma_verts( rmesa, tmp );
+
+ if (RADEON_DEBUG & DEBUG_VFMT)
+ fprintf(stderr, "%d vertices to copy\n", nrverts);
+
+ /* Finish the prim at this point:
+ */
+ note_last_prim( rmesa, 0 );
+ }
+
+ /* Fire any buffered primitives
+ */
+ flush_prims( rmesa );
+
+ /* Get new buffer
+ */
+ radeonRefillCurrentDmaRegion( rmesa );
+
+ /* Reset counter, dmaptr
+ */
+ rmesa->vb.dmaptr = (int *)(rmesa->dma.current.ptr + rmesa->dma.current.address);
+ rmesa->vb.counter = (rmesa->dma.current.end - rmesa->dma.current.ptr) /
+ (rmesa->vb.vertex_size * 4);
+ rmesa->vb.counter--;
+ rmesa->vb.initial_counter = rmesa->vb.counter;
+ rmesa->vb.notify = wrap_buffer;
+
+ rmesa->dma.flush = flush_prims;
+
+ /* Restart wrapped primitive:
+ */
+ if (rmesa->vb.prim[0] != GL_POLYGON+1)
+ start_prim( rmesa, rmesa->vb.prim[0] );
+
+ /* Reemit saved vertices
+ */
+ for (i = 0 ; i < nrverts; i++) {
+ if (RADEON_DEBUG & DEBUG_VERTS) {
+ int j;
+ fprintf(stderr, "re-emit vertex %d to %p\n", i, rmesa->vb.dmaptr);
+ if (RADEON_DEBUG & DEBUG_VERBOSE)
+ for (j = 0 ; j < rmesa->vb.vertex_size; j++)
+ fprintf(stderr, "\t%08x/%f\n", *(int*)&tmp[i][j], tmp[i][j]);
+ }
+
+ memcpy( rmesa->vb.dmaptr, tmp[i], rmesa->vb.vertex_size * 4 );
+ rmesa->vb.dmaptr += rmesa->vb.vertex_size;
+ rmesa->vb.counter--;
+ }
+}
+
+
+
+static GLboolean check_vtx_fmt( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLuint ind = RADEON_CP_VC_FRMT_Z;
+
+ if (rmesa->TclFallback || rmesa->vb.fell_back || ctx->CompileFlag)
+ return GL_FALSE;
+
+ if (ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT)
+ ctx->Driver.FlushVertices( ctx, FLUSH_UPDATE_CURRENT );
+
+ /* Make all this event-driven:
+ */
+ if (ctx->Light.Enabled) {
+ ind |= RADEON_CP_VC_FRMT_N0;
+
+ /* TODO: make this data driven: If we receive only ubytes, send
+ * color as ubytes. Also check if converting (with free
+ * checking for overflow) is cheaper than sending floats
+ * directly.
+ */
+ if (ctx->Light.ColorMaterialEnabled) {
+ ind |= (RADEON_CP_VC_FRMT_FPCOLOR |
+ RADEON_CP_VC_FRMT_FPALPHA);
+ }
+ else
+ ind |= RADEON_CP_VC_FRMT_PKCOLOR; /* for alpha? */
+ }
+ else {
+ /* TODO: make this data driven?
+ */
+ ind |= RADEON_CP_VC_FRMT_PKCOLOR;
+
+ if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) {
+ ind |= RADEON_CP_VC_FRMT_PKSPEC;
+ }
+ }
+
+ if (ctx->Texture.Unit[0]._ReallyEnabled) {
+ if (ctx->Texture.Unit[0].TexGenEnabled) {
+ if (rmesa->TexGenNeedNormals[0]) {
+ ind |= RADEON_CP_VC_FRMT_N0;
+ }
+ } else {
+ if (ctx->Current.Attrib[VERT_ATTRIB_TEX0][2] != 0.0F ||
+ ctx->Current.Attrib[VERT_ATTRIB_TEX0][3] != 1.0) {
+ if (RADEON_DEBUG & (DEBUG_VFMT|DEBUG_FALLBACKS))
+ fprintf(stderr, "%s: rq0\n", __FUNCTION__);
+ return GL_FALSE;
+ }
+ ind |= RADEON_CP_VC_FRMT_ST0;
+ }
+ }
+
+ if (ctx->Texture.Unit[1]._ReallyEnabled) {
+ if (ctx->Texture.Unit[1].TexGenEnabled) {
+ if (rmesa->TexGenNeedNormals[1]) {
+ ind |= RADEON_CP_VC_FRMT_N0;
+ }
+ } else {
+ if (ctx->Current.Attrib[VERT_ATTRIB_TEX1][2] != 0.0F ||
+ ctx->Current.Attrib[VERT_ATTRIB_TEX1][3] != 1.0) {
+ if (RADEON_DEBUG & (DEBUG_VFMT|DEBUG_FALLBACKS))
+ fprintf(stderr, "%s: rq1\n", __FUNCTION__);
+ return GL_FALSE;
+ }
+ ind |= RADEON_CP_VC_FRMT_ST1;
+ }
+ }
+
+ if (RADEON_DEBUG & (DEBUG_VFMT|DEBUG_STATE))
+ fprintf(stderr, "%s: format: 0x%x\n", __FUNCTION__, ind );
+
+ RADEON_NEWPRIM(rmesa);
+ rmesa->vb.vertex_format = ind;
+ rmesa->vb.vertex_size = 3;
+ rmesa->vb.prim = &ctx->Driver.CurrentExecPrimitive;
+
+ rmesa->vb.normalptr = ctx->Current.Attrib[VERT_ATTRIB_NORMAL];
+ rmesa->vb.colorptr = NULL;
+ rmesa->vb.floatcolorptr = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
+ rmesa->vb.specptr = NULL;
+ rmesa->vb.floatspecptr = ctx->Current.Attrib[VERT_ATTRIB_COLOR1];
+ rmesa->vb.texcoordptr[0] = ctx->Current.Attrib[VERT_ATTRIB_TEX0];
+ rmesa->vb.texcoordptr[1] = ctx->Current.Attrib[VERT_ATTRIB_TEX1];
+
+ /* Run through and initialize the vertex components in the order
+ * the hardware understands:
+ */
+ if (ind & RADEON_CP_VC_FRMT_N0) {
+ rmesa->vb.normalptr = &rmesa->vb.vertex[rmesa->vb.vertex_size].f;
+ rmesa->vb.vertex_size += 3;
+ rmesa->vb.normalptr[0] = ctx->Current.Attrib[VERT_ATTRIB_NORMAL][0];
+ rmesa->vb.normalptr[1] = ctx->Current.Attrib[VERT_ATTRIB_NORMAL][1];
+ rmesa->vb.normalptr[2] = ctx->Current.Attrib[VERT_ATTRIB_NORMAL][2];
+ }
+
+ if (ind & RADEON_CP_VC_FRMT_PKCOLOR) {
+ rmesa->vb.colorptr = &rmesa->vb.vertex[rmesa->vb.vertex_size].color;
+ rmesa->vb.vertex_size += 1;
+ UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.colorptr->red, ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0] );
+ UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.colorptr->green, ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1] );
+ UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.colorptr->blue, ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2] );
+ UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.colorptr->alpha, ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3] );
+ }
+
+ if (ind & RADEON_CP_VC_FRMT_FPCOLOR) {
+ assert(!(ind & RADEON_CP_VC_FRMT_PKCOLOR));
+ rmesa->vb.floatcolorptr = &rmesa->vb.vertex[rmesa->vb.vertex_size].f;
+ rmesa->vb.vertex_size += 3;
+ rmesa->vb.floatcolorptr[0] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0];
+ rmesa->vb.floatcolorptr[1] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1];
+ rmesa->vb.floatcolorptr[2] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2];
+
+ if (ind & RADEON_CP_VC_FRMT_FPALPHA) {
+ rmesa->vb.vertex_size += 1;
+ rmesa->vb.floatcolorptr[3] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3];
+ }
+ }
+
+ if (ind & RADEON_CP_VC_FRMT_PKSPEC) {
+ rmesa->vb.specptr = &rmesa->vb.vertex[rmesa->vb.vertex_size].color;
+ rmesa->vb.vertex_size += 1;
+ UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.specptr->red, ctx->Current.Attrib[VERT_ATTRIB_COLOR1][0] );
+ UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.specptr->green, ctx->Current.Attrib[VERT_ATTRIB_COLOR1][1] );
+ UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.specptr->blue, ctx->Current.Attrib[VERT_ATTRIB_COLOR1][2] );
+ }
+
+ if (ind & RADEON_CP_VC_FRMT_ST0) {
+ rmesa->vb.texcoordptr[0] = &rmesa->vb.vertex[rmesa->vb.vertex_size].f;
+ rmesa->vb.vertex_size += 2;
+ rmesa->vb.texcoordptr[0][0] = ctx->Current.Attrib[VERT_ATTRIB_TEX0][0];
+ rmesa->vb.texcoordptr[0][1] = ctx->Current.Attrib[VERT_ATTRIB_TEX0][1];
+ }
+
+ if (ind & RADEON_CP_VC_FRMT_ST1) {
+ rmesa->vb.texcoordptr[1] = &rmesa->vb.vertex[rmesa->vb.vertex_size].f;
+ rmesa->vb.vertex_size += 2;
+ rmesa->vb.texcoordptr[1][0] = ctx->Current.Attrib[VERT_ATTRIB_TEX1][0];
+ rmesa->vb.texcoordptr[1][1] = ctx->Current.Attrib[VERT_ATTRIB_TEX1][1];
+ }
+
+ if (rmesa->vb.installed_vertex_format != rmesa->vb.vertex_format) {
+ if (RADEON_DEBUG & DEBUG_VFMT)
+ fprintf(stderr, "reinstall on vertex_format change\n");
+ _mesa_install_exec_vtxfmt( ctx, &rmesa->vb.vtxfmt );
+ rmesa->vb.installed_vertex_format = rmesa->vb.vertex_format;
+ }
+
+ if (RADEON_DEBUG & DEBUG_VFMT)
+ fprintf(stderr, "%s -- success\n", __FUNCTION__);
+
+ return GL_TRUE;
+}
+
+void radeonVtxfmtInvalidate( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+
+ rmesa->vb.recheck = GL_TRUE;
+ rmesa->vb.fell_back = GL_FALSE;
+}
+
+
+static void radeonNewList( GLcontext *ctx, GLuint list, GLenum mode )
+{
+ VFMT_FALLBACK_OUTSIDE_BEGIN_END( __FUNCTION__ );
+}
+
+
+static void radeonVtxfmtValidate( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+
+ if (RADEON_DEBUG & DEBUG_VFMT)
+ fprintf(stderr, "%s\n", __FUNCTION__);
+
+ if (ctx->Driver.NeedFlush)
+ ctx->Driver.FlushVertices( ctx, ctx->Driver.NeedFlush );
+
+ rmesa->vb.recheck = GL_FALSE;
+
+ if (check_vtx_fmt( ctx )) {
+ if (!rmesa->vb.installed) {
+ if (RADEON_DEBUG & DEBUG_VFMT)
+ fprintf(stderr, "reinstall (new install)\n");
+
+ _mesa_install_exec_vtxfmt( ctx, &rmesa->vb.vtxfmt );
+ ctx->Driver.FlushVertices = radeonVtxfmtFlushVertices;
+ ctx->Driver.NewList = radeonNewList;
+ rmesa->vb.installed = GL_TRUE;
+ }
+ else if (RADEON_DEBUG & DEBUG_VFMT)
+ fprintf(stderr, "%s: already installed", __FUNCTION__);
+ }
+ else {
+ if (RADEON_DEBUG & DEBUG_VFMT)
+ fprintf(stderr, "%s: failed\n", __FUNCTION__);
+
+ if (rmesa->vb.installed) {
+ if (rmesa->dma.flush)
+ rmesa->dma.flush( rmesa );
+ _tnl_wakeup_exec( ctx );
+ ctx->Driver.FlushVertices = radeonFlushVertices;
+ rmesa->vb.installed = GL_FALSE;
+ }
+ }
+}
+
+
+
+/* Materials:
+ */
+static void radeon_Materialfv( GLenum face, GLenum pname,
+ const GLfloat *params )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+
+ if (RADEON_DEBUG & DEBUG_VFMT)
+ fprintf(stderr, "%s\n", __FUNCTION__);
+
+ if (rmesa->vb.prim[0] != GL_POLYGON+1) {
+ VFMT_FALLBACK( __FUNCTION__ );
+ glMaterialfv( face, pname, params );
+ return;
+ }
+ _mesa_noop_Materialfv( face, pname, params );
+ radeonUpdateMaterial( ctx );
+}
+
+
+/* Begin/End
+ */
+static void radeon_Begin( GLenum mode )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ if (RADEON_DEBUG & DEBUG_VFMT)
+ fprintf(stderr, "%s( %s )\n", __FUNCTION__,
+ _mesa_lookup_enum_by_nr( mode ));
+
+ if (mode > GL_POLYGON) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glBegin" );
+ return;
+ }
+
+ if (rmesa->vb.prim[0] != GL_POLYGON+1) {
+ _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" );
+ return;
+ }
+
+ if (ctx->NewState)
+ _mesa_update_state( ctx );
+
+ if (rmesa->NewGLState)
+ radeonValidateState( ctx );
+
+ if (rmesa->vb.recheck)
+ radeonVtxfmtValidate( ctx );
+
+ if (!rmesa->vb.installed) {
+ glBegin( mode );
+ return;
+ }
+
+
+ if (rmesa->dma.flush && rmesa->vb.counter < 12) {
+ if (RADEON_DEBUG & DEBUG_VFMT)
+ fprintf(stderr, "%s: flush almost-empty buffers\n", __FUNCTION__);
+ flush_prims( rmesa );
+ }
+
+ /* Need to arrange to save vertices here? Or always copy from dma (yuk)?
+ */
+ if (!rmesa->dma.flush) {
+ if (rmesa->dma.current.ptr + 12*rmesa->vb.vertex_size*4 >
+ rmesa->dma.current.end) {
+ RADEON_NEWPRIM( rmesa );
+ radeonRefillCurrentDmaRegion( rmesa );
+ }
+
+ rmesa->vb.dmaptr = (int *)(rmesa->dma.current.address + rmesa->dma.current.ptr);
+ rmesa->vb.counter = (rmesa->dma.current.end - rmesa->dma.current.ptr) /
+ (rmesa->vb.vertex_size * 4);
+ rmesa->vb.counter--;
+ rmesa->vb.initial_counter = rmesa->vb.counter;
+ rmesa->vb.notify = wrap_buffer;
+ rmesa->dma.flush = flush_prims;
+ ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
+ }
+
+
+ rmesa->vb.prim[0] = mode;
+ start_prim( rmesa, mode | PRIM_BEGIN );
+}
+
+
+
+static void radeon_End( void )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ if (RADEON_DEBUG & DEBUG_VFMT)
+ fprintf(stderr, "%s\n", __FUNCTION__);
+
+ if (rmesa->vb.prim[0] == GL_POLYGON+1) {
+ _mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" );
+ return;
+ }
+
+ note_last_prim( rmesa, PRIM_END );
+ rmesa->vb.prim[0] = GL_POLYGON+1;
+}
+
+
+/* Fallback on difficult entrypoints:
+ */
+#define PRE_LOOPBACK( FUNC ) \
+do { \
+ if (RADEON_DEBUG & DEBUG_VFMT) \
+ fprintf(stderr, "%s\n", __FUNCTION__); \
+ VFMT_FALLBACK( __FUNCTION__ ); \
+} while (0)
+#define TAG(x) radeon_fallback_##x
+#include "vtxfmt_tmp.h"
+
+
+
+static GLboolean radeonNotifyBegin( GLcontext *ctx, GLenum p )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+
+ if (RADEON_DEBUG & DEBUG_VFMT)
+ fprintf(stderr, "%s\n", __FUNCTION__);
+
+ assert(!rmesa->vb.installed);
+
+ if (ctx->NewState)
+ _mesa_update_state( ctx );
+
+ if (rmesa->NewGLState)
+ radeonValidateState( ctx );
+
+ if (ctx->Driver.NeedFlush)
+ ctx->Driver.FlushVertices( ctx, ctx->Driver.NeedFlush );
+
+ if (rmesa->vb.recheck)
+ radeonVtxfmtValidate( ctx );
+
+ if (!rmesa->vb.installed) {
+ if (RADEON_DEBUG & DEBUG_VFMT)
+ fprintf(stderr, "%s -- failed\n", __FUNCTION__);
+ return GL_FALSE;
+ }
+
+ radeon_Begin( p );
+ return GL_TRUE;
+}
+
+static void radeonVtxfmtFlushVertices( GLcontext *ctx, GLuint flags )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+
+ if (RADEON_DEBUG & DEBUG_VFMT)
+ fprintf(stderr, "%s\n", __FUNCTION__);
+
+ assert(rmesa->vb.installed);
+
+ if (flags & FLUSH_UPDATE_CURRENT) {
+ radeon_copy_to_current( ctx );
+ if (RADEON_DEBUG & DEBUG_VFMT)
+ fprintf(stderr, "reinstall on update_current\n");
+ _mesa_install_exec_vtxfmt( ctx, &rmesa->vb.vtxfmt );
+ ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT;
+ }
+
+ if (flags & FLUSH_STORED_VERTICES) {
+ radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+ assert (rmesa->dma.flush == 0 ||
+ rmesa->dma.flush == flush_prims);
+ if (rmesa->dma.flush == flush_prims)
+ flush_prims( RADEON_CONTEXT( ctx ) );
+ ctx->Driver.NeedFlush &= ~FLUSH_STORED_VERTICES;
+ }
+}
+
+
+
+/* At this point, don't expect very many versions of each function to
+ * be generated, so not concerned about freeing them?
+ */
+
+
+void radeonVtxfmtInit( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+ GLvertexformat *vfmt = &(rmesa->vb.vtxfmt);
+
+ MEMSET( vfmt, 0, sizeof(GLvertexformat) );
+
+ /* Hook in chooser functions for codegen, etc:
+ */
+ radeonVtxfmtInitChoosers( vfmt );
+
+ /* Handled fully in supported states, but no codegen:
+ */
+ vfmt->Materialfv = radeon_Materialfv;
+ vfmt->ArrayElement = _ae_loopback_array_elt; /* generic helper */
+ vfmt->Rectf = _mesa_noop_Rectf; /* generic helper */
+ vfmt->Begin = radeon_Begin;
+ vfmt->End = radeon_End;
+
+ /* Fallback for performance reasons: (Fix with cva/elt path here and
+ * dmatmp2.h style primitive-merging)
+ *
+ * These should call NotifyBegin(), as should _tnl_EvalMesh, to allow
+ * a driver-hook.
+ */
+ vfmt->DrawArrays = radeon_fallback_DrawArrays;
+ vfmt->DrawElements = radeon_fallback_DrawElements;
+ vfmt->DrawRangeElements = radeon_fallback_DrawRangeElements;
+
+
+ /* Not active in supported states; just keep ctx->Current uptodate:
+ */
+ vfmt->FogCoordfvEXT = _mesa_noop_FogCoordfvEXT;
+ vfmt->FogCoordfEXT = _mesa_noop_FogCoordfEXT;
+ vfmt->EdgeFlag = _mesa_noop_EdgeFlag;
+ vfmt->EdgeFlagv = _mesa_noop_EdgeFlagv;
+ vfmt->Indexi = _mesa_noop_Indexi;
+ vfmt->Indexiv = _mesa_noop_Indexiv;
+
+
+ /* Active but unsupported -- fallback if we receive these:
+ */
+ vfmt->CallList = radeon_fallback_CallList;
+ vfmt->EvalCoord1f = radeon_fallback_EvalCoord1f;
+ vfmt->EvalCoord1fv = radeon_fallback_EvalCoord1fv;
+ vfmt->EvalCoord2f = radeon_fallback_EvalCoord2f;
+ vfmt->EvalCoord2fv = radeon_fallback_EvalCoord2fv;
+ vfmt->EvalMesh1 = radeon_fallback_EvalMesh1;
+ vfmt->EvalMesh2 = radeon_fallback_EvalMesh2;
+ vfmt->EvalPoint1 = radeon_fallback_EvalPoint1;
+ vfmt->EvalPoint2 = radeon_fallback_EvalPoint2;
+ vfmt->TexCoord3f = radeon_fallback_TexCoord3f;
+ vfmt->TexCoord3fv = radeon_fallback_TexCoord3fv;
+ vfmt->TexCoord4f = radeon_fallback_TexCoord4f;
+ vfmt->TexCoord4fv = radeon_fallback_TexCoord4fv;
+ vfmt->MultiTexCoord3fARB = radeon_fallback_MultiTexCoord3fARB;
+ vfmt->MultiTexCoord3fvARB = radeon_fallback_MultiTexCoord3fvARB;
+ vfmt->MultiTexCoord4fARB = radeon_fallback_MultiTexCoord4fARB;
+ vfmt->MultiTexCoord4fvARB = radeon_fallback_MultiTexCoord4fvARB;
+ vfmt->Vertex4f = radeon_fallback_Vertex4f;
+ vfmt->Vertex4fv = radeon_fallback_Vertex4fv;
+
+ (void)radeon_fallback_vtxfmt;
+
+ TNL_CONTEXT(ctx)->Driver.NotifyBegin = radeonNotifyBegin;
+
+ rmesa->vb.enabled = 1;
+ rmesa->vb.prim = &ctx->Driver.CurrentExecPrimitive;
+ rmesa->vb.primflags = 0;
+
+ make_empty_list( &rmesa->vb.dfn_cache.Vertex2f );
+ make_empty_list( &rmesa->vb.dfn_cache.Vertex2fv );
+ make_empty_list( &rmesa->vb.dfn_cache.Vertex3f );
+ make_empty_list( &rmesa->vb.dfn_cache.Vertex3fv );
+ make_empty_list( &rmesa->vb.dfn_cache.Color4ub );
+ make_empty_list( &rmesa->vb.dfn_cache.Color4ubv );
+ make_empty_list( &rmesa->vb.dfn_cache.Color3ub );
+ make_empty_list( &rmesa->vb.dfn_cache.Color3ubv );
+ make_empty_list( &rmesa->vb.dfn_cache.Color4f );
+ make_empty_list( &rmesa->vb.dfn_cache.Color4fv );
+ make_empty_list( &rmesa->vb.dfn_cache.Color3f );
+ make_empty_list( &rmesa->vb.dfn_cache.Color3fv );
+ make_empty_list( &rmesa->vb.dfn_cache.SecondaryColor3fEXT );
+ make_empty_list( &rmesa->vb.dfn_cache.SecondaryColor3fvEXT );
+ make_empty_list( &rmesa->vb.dfn_cache.SecondaryColor3ubEXT );
+ make_empty_list( &rmesa->vb.dfn_cache.SecondaryColor3ubvEXT );
+ make_empty_list( &rmesa->vb.dfn_cache.Normal3f );
+ make_empty_list( &rmesa->vb.dfn_cache.Normal3fv );
+ make_empty_list( &rmesa->vb.dfn_cache.TexCoord2f );
+ make_empty_list( &rmesa->vb.dfn_cache.TexCoord2fv );
+ make_empty_list( &rmesa->vb.dfn_cache.TexCoord1f );
+ make_empty_list( &rmesa->vb.dfn_cache.TexCoord1fv );
+ make_empty_list( &rmesa->vb.dfn_cache.MultiTexCoord2fARB );
+ make_empty_list( &rmesa->vb.dfn_cache.MultiTexCoord2fvARB );
+ make_empty_list( &rmesa->vb.dfn_cache.MultiTexCoord1fARB );
+ make_empty_list( &rmesa->vb.dfn_cache.MultiTexCoord1fvARB );
+
+ radeonInitCodegen( &rmesa->vb.codegen );
+}
+
+static void free_funcs( struct dynfn *l )
+{
+ struct dynfn *f, *tmp;
+ foreach_s (f, tmp, l) {
+ remove_from_list( f );
+ ALIGN_FREE( f->code );
+ FREE( f );
+ }
+}
+
+
+
+void radeonVtxfmtMakeCurrent( GLcontext *ctx )
+{
+}
+
+
+void radeonVtxfmtDestroy( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+
+ count_funcs( rmesa );
+ free_funcs( &rmesa->vb.dfn_cache.Vertex2f );
+ free_funcs( &rmesa->vb.dfn_cache.Vertex2fv );
+ free_funcs( &rmesa->vb.dfn_cache.Vertex3f );
+ free_funcs( &rmesa->vb.dfn_cache.Vertex3fv );
+ free_funcs( &rmesa->vb.dfn_cache.Color4ub );
+ free_funcs( &rmesa->vb.dfn_cache.Color4ubv );
+ free_funcs( &rmesa->vb.dfn_cache.Color3ub );
+ free_funcs( &rmesa->vb.dfn_cache.Color3ubv );
+ free_funcs( &rmesa->vb.dfn_cache.Color4f );
+ free_funcs( &rmesa->vb.dfn_cache.Color4fv );
+ free_funcs( &rmesa->vb.dfn_cache.Color3f );
+ free_funcs( &rmesa->vb.dfn_cache.Color3fv );
+ free_funcs( &rmesa->vb.dfn_cache.SecondaryColor3ubEXT );
+ free_funcs( &rmesa->vb.dfn_cache.SecondaryColor3ubvEXT );
+ free_funcs( &rmesa->vb.dfn_cache.SecondaryColor3fEXT );
+ free_funcs( &rmesa->vb.dfn_cache.SecondaryColor3fvEXT );
+ free_funcs( &rmesa->vb.dfn_cache.Normal3f );
+ free_funcs( &rmesa->vb.dfn_cache.Normal3fv );
+ free_funcs( &rmesa->vb.dfn_cache.TexCoord2f );
+ free_funcs( &rmesa->vb.dfn_cache.TexCoord2fv );
+ free_funcs( &rmesa->vb.dfn_cache.TexCoord1f );
+ free_funcs( &rmesa->vb.dfn_cache.TexCoord1fv );
+ free_funcs( &rmesa->vb.dfn_cache.MultiTexCoord2fARB );
+ free_funcs( &rmesa->vb.dfn_cache.MultiTexCoord2fvARB );
+ free_funcs( &rmesa->vb.dfn_cache.MultiTexCoord1fARB );
+ free_funcs( &rmesa->vb.dfn_cache.MultiTexCoord1fvARB );
+}
+
diff --git a/src/mesa/drivers/dri/radeon/radeon_vtxfmt.h b/src/mesa/drivers/dri/radeon/radeon_vtxfmt.h
new file mode 100644
index 0000000000..9792fcbb78
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_vtxfmt.h
@@ -0,0 +1,124 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_vtxfmt.h,v 1.3 2002/12/21 17:02:16 dawes Exp $ */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+ Tungsten Graphics Inc., Cedar Park, Texas.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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 __RADEON_VTXFMT_H__
+#define __RADEON_VTXFMT_H__
+
+#ifdef GLX_DIRECT_RENDERING
+
+#include "radeon_context.h"
+
+
+extern void radeonVtxfmtUpdate( GLcontext *ctx );
+extern void radeonVtxfmtInit( GLcontext *ctx );
+extern void radeonVtxfmtInvalidate( GLcontext *ctx );
+extern void radeonVtxfmtDestroy( GLcontext *ctx );
+extern void radeonVtxfmtInitChoosers( GLvertexformat *vfmt );
+
+extern void radeonVtxfmtMakeCurrent( GLcontext *ctx );
+extern void radeonVtxfmtUnbindContext( GLcontext *ctx );
+
+extern void radeon_copy_to_current( GLcontext *ctx );
+
+#define DFN( FUNC, CACHE) \
+do { \
+ char *start = (char *)&FUNC; \
+ char *end = (char *)&FUNC##_end; \
+ insert_at_head( &CACHE, dfn ); \
+ dfn->key = key; \
+ dfn->code = ALIGN_MALLOC( end - start, 16 ); \
+ memcpy (dfn->code, start, end - start); \
+} \
+while ( 0 )
+
+#define FIXUP( CODE, OFFSET, CHECKVAL, NEWVAL ) \
+do { \
+ int *icode = (int *)(CODE+OFFSET); \
+ assert (*icode == CHECKVAL); \
+ *icode = (int)NEWVAL; \
+} while (0)
+
+
+/* Useful for figuring out the offsets:
+ */
+#define FIXUP2( CODE, OFFSET, CHECKVAL, NEWVAL ) \
+do { \
+ while (*(int *)(CODE+OFFSET) != CHECKVAL) OFFSET++; \
+ fprintf(stderr, "%s/%d CVAL %x OFFSET %d VAL %x\n", __FUNCTION__, \
+ __LINE__, CHECKVAL, OFFSET, (int)(NEWVAL)); \
+ *(int *)(CODE+OFFSET) = (int)(NEWVAL); \
+ OFFSET += 4; \
+} while (0)
+
+/*
+ */
+void radeonInitCodegen( struct dfn_generators *gen );
+void radeonInitX86Codegen( struct dfn_generators *gen );
+void radeonInitSSECodegen( struct dfn_generators *gen );
+
+
+
+/* Defined in radeon_vtxfmt_x86.c
+ */
+struct dynfn *radeon_makeX86Vertex2f( GLcontext *, int );
+struct dynfn *radeon_makeX86Vertex2fv( GLcontext *, int );
+struct dynfn *radeon_makeX86Vertex3f( GLcontext *, int );
+struct dynfn *radeon_makeX86Vertex3fv( GLcontext *, int );
+struct dynfn *radeon_makeX86Color4ub( GLcontext *, int );
+struct dynfn *radeon_makeX86Color4ubv( GLcontext *, int );
+struct dynfn *radeon_makeX86Color3ub( GLcontext *, int );
+struct dynfn *radeon_makeX86Color3ubv( GLcontext *, int );
+struct dynfn *radeon_makeX86Color4f( GLcontext *, int );
+struct dynfn *radeon_makeX86Color4fv( GLcontext *, int );
+struct dynfn *radeon_makeX86Color3f( GLcontext *, int );
+struct dynfn *radeon_makeX86Color3fv( GLcontext *, int );
+struct dynfn *radeon_makeX86SecondaryColor3ubEXT( GLcontext *, int );
+struct dynfn *radeon_makeX86SecondaryColor3ubvEXT( GLcontext *, int );
+struct dynfn *radeon_makeX86SecondaryColor3fEXT( GLcontext *, int );
+struct dynfn *radeon_makeX86SecondaryColor3fvEXT( GLcontext *, int );
+struct dynfn *radeon_makeX86Normal3f( GLcontext *, int );
+struct dynfn *radeon_makeX86Normal3fv( GLcontext *, int );
+struct dynfn *radeon_makeX86TexCoord2f( GLcontext *, int );
+struct dynfn *radeon_makeX86TexCoord2fv( GLcontext *, int );
+struct dynfn *radeon_makeX86TexCoord1f( GLcontext *, int );
+struct dynfn *radeon_makeX86TexCoord1fv( GLcontext *, int );
+struct dynfn *radeon_makeX86MultiTexCoord2fARB( GLcontext *, int );
+struct dynfn *radeon_makeX86MultiTexCoord2fvARB( GLcontext *, int );
+struct dynfn *radeon_makeX86MultiTexCoord1fARB( GLcontext *, int );
+struct dynfn *radeon_makeX86MultiTexCoord1fvARB( GLcontext *, int );
+
+
+#endif
+#endif
diff --git a/src/mesa/drivers/dri/radeon/radeon_vtxfmt_c.c b/src/mesa/drivers/dri/radeon/radeon_vtxfmt_c.c
new file mode 100644
index 0000000000..188e34a420
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_vtxfmt_c.c
@@ -0,0 +1,905 @@
+/* $XFree86$ */
+/**************************************************************************
+
+Copyright 2002 ATI Technologies Inc., Ontario, Canada, and
+ Tungsten Graphics Inc., Cedar Park, Texas.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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 "glheader.h"
+#include "mtypes.h"
+#include "colormac.h"
+#include "simple_list.h"
+#include "api_noop.h"
+#include "vtxfmt.h"
+
+#include "radeon_vtxfmt.h"
+
+/* Fallback versions of all the entrypoints for situations where
+ * codegen isn't available. This is still a lot faster than the
+ * vb/pipeline implementation in Mesa.
+ */
+static void radeon_Vertex3f( GLfloat x, GLfloat y, GLfloat z )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ int i;
+
+ *rmesa->vb.dmaptr++ = *(int *)&x;
+ *rmesa->vb.dmaptr++ = *(int *)&y;
+ *rmesa->vb.dmaptr++ = *(int *)&z;
+
+ for (i = 3; i < rmesa->vb.vertex_size; i++)
+ *rmesa->vb.dmaptr++ = rmesa->vb.vertex[i].i;
+
+ if (--rmesa->vb.counter == 0)
+ rmesa->vb.notify();
+}
+
+
+static void radeon_Vertex3fv( const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ int i;
+
+ *rmesa->vb.dmaptr++ = *(int *)&v[0];
+ *rmesa->vb.dmaptr++ = *(int *)&v[1];
+ *rmesa->vb.dmaptr++ = *(int *)&v[2];
+
+ for (i = 3; i < rmesa->vb.vertex_size; i++)
+ *rmesa->vb.dmaptr++ = rmesa->vb.vertex[i].i;
+
+ if (--rmesa->vb.counter == 0)
+ rmesa->vb.notify();
+}
+
+
+static void radeon_Vertex2f( GLfloat x, GLfloat y )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ int i;
+
+ *rmesa->vb.dmaptr++ = *(int *)&x;
+ *rmesa->vb.dmaptr++ = *(int *)&y;
+ *rmesa->vb.dmaptr++ = 0;
+
+ for (i = 3; i < rmesa->vb.vertex_size; i++)
+ *rmesa->vb.dmaptr++ = *(int *)&rmesa->vb.vertex[i];
+
+ if (--rmesa->vb.counter == 0)
+ rmesa->vb.notify();
+}
+
+
+static void radeon_Vertex2fv( const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ int i;
+
+ *rmesa->vb.dmaptr++ = *(int *)&v[0];
+ *rmesa->vb.dmaptr++ = *(int *)&v[1];
+ *rmesa->vb.dmaptr++ = 0;
+
+ for (i = 3; i < rmesa->vb.vertex_size; i++)
+ *rmesa->vb.dmaptr++ = rmesa->vb.vertex[i].i;
+
+ if (--rmesa->vb.counter == 0)
+ rmesa->vb.notify();
+}
+
+
+
+/* Color for ubyte (packed) color formats:
+ */
+static void radeon_Color3ub_ub( GLubyte r, GLubyte g, GLubyte b )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ radeon_color_t *dest = rmesa->vb.colorptr;
+ dest->red = r;
+ dest->green = g;
+ dest->blue = b;
+ dest->alpha = 0xff;
+}
+
+static void radeon_Color3ubv_ub( const GLubyte *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ radeon_color_t *dest = rmesa->vb.colorptr;
+ dest->red = v[0];
+ dest->green = v[1];
+ dest->blue = v[2];
+ dest->alpha = 0xff;
+}
+
+static void radeon_Color4ub_ub( GLubyte r, GLubyte g, GLubyte b, GLubyte a )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ radeon_color_t *dest = rmesa->vb.colorptr;
+ dest->red = r;
+ dest->green = g;
+ dest->blue = b;
+ dest->alpha = a;
+}
+
+static void radeon_Color4ubv_ub( const GLubyte *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ *(GLuint *)rmesa->vb.colorptr = LE32_TO_CPU(*(GLuint *)v);
+}
+
+
+static void radeon_Color3f_ub( GLfloat r, GLfloat g, GLfloat b )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ radeon_color_t *dest = rmesa->vb.colorptr;
+ UNCLAMPED_FLOAT_TO_UBYTE( dest->red, r );
+ UNCLAMPED_FLOAT_TO_UBYTE( dest->green, g );
+ UNCLAMPED_FLOAT_TO_UBYTE( dest->blue, b );
+ dest->alpha = 255;
+}
+
+static void radeon_Color3fv_ub( const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ radeon_color_t *dest = rmesa->vb.colorptr;
+ UNCLAMPED_FLOAT_TO_UBYTE( dest->red, v[0] );
+ UNCLAMPED_FLOAT_TO_UBYTE( dest->green, v[1] );
+ UNCLAMPED_FLOAT_TO_UBYTE( dest->blue, v[2] );
+ dest->alpha = 255;
+}
+
+static void radeon_Color4f_ub( GLfloat r, GLfloat g, GLfloat b, GLfloat a )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ radeon_color_t *dest = rmesa->vb.colorptr;
+ UNCLAMPED_FLOAT_TO_UBYTE( dest->red, r );
+ UNCLAMPED_FLOAT_TO_UBYTE( dest->green, g );
+ UNCLAMPED_FLOAT_TO_UBYTE( dest->blue, b );
+ UNCLAMPED_FLOAT_TO_UBYTE( dest->alpha, a );
+}
+
+static void radeon_Color4fv_ub( const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ radeon_color_t *dest = rmesa->vb.colorptr;
+ UNCLAMPED_FLOAT_TO_UBYTE( dest->red, v[0] );
+ UNCLAMPED_FLOAT_TO_UBYTE( dest->green, v[1] );
+ UNCLAMPED_FLOAT_TO_UBYTE( dest->blue, v[2] );
+ UNCLAMPED_FLOAT_TO_UBYTE( dest->alpha, v[3] );
+}
+
+
+/* Color for float color+alpha formats:
+ */
+static void radeon_Color3ub_4f( GLubyte r, GLubyte g, GLubyte b )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLfloat *dest = rmesa->vb.floatcolorptr;
+ dest[0] = UBYTE_TO_FLOAT(r);
+ dest[1] = UBYTE_TO_FLOAT(g);
+ dest[2] = UBYTE_TO_FLOAT(b);
+ dest[3] = 1.0;
+}
+
+static void radeon_Color3ubv_4f( const GLubyte *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLfloat *dest = rmesa->vb.floatcolorptr;
+ dest[0] = UBYTE_TO_FLOAT(v[0]);
+ dest[1] = UBYTE_TO_FLOAT(v[1]);
+ dest[2] = UBYTE_TO_FLOAT(v[2]);
+ dest[3] = 1.0;
+}
+
+static void radeon_Color4ub_4f( GLubyte r, GLubyte g, GLubyte b, GLubyte a )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLfloat *dest = rmesa->vb.floatcolorptr;
+ dest[0] = UBYTE_TO_FLOAT(r);
+ dest[1] = UBYTE_TO_FLOAT(g);
+ dest[2] = UBYTE_TO_FLOAT(b);
+ dest[3] = UBYTE_TO_FLOAT(a);
+}
+
+static void radeon_Color4ubv_4f( const GLubyte *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLfloat *dest = rmesa->vb.floatcolorptr;
+ dest[0] = UBYTE_TO_FLOAT(v[0]);
+ dest[1] = UBYTE_TO_FLOAT(v[1]);
+ dest[2] = UBYTE_TO_FLOAT(v[2]);
+ dest[3] = UBYTE_TO_FLOAT(v[3]);
+}
+
+
+static void radeon_Color3f_4f( GLfloat r, GLfloat g, GLfloat b )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLfloat *dest = rmesa->vb.floatcolorptr;
+ dest[0] = r;
+ dest[1] = g;
+ dest[2] = b;
+ dest[3] = 1.0;
+}
+
+static void radeon_Color3fv_4f( const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLfloat *dest = rmesa->vb.floatcolorptr;
+ dest[0] = v[0];
+ dest[1] = v[1];
+ dest[2] = v[2];
+ dest[3] = 1.0;
+}
+
+static void radeon_Color4f_4f( GLfloat r, GLfloat g, GLfloat b, GLfloat a )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLfloat *dest = rmesa->vb.floatcolorptr;
+ dest[0] = r;
+ dest[1] = g;
+ dest[2] = b;
+ dest[3] = a;
+}
+
+static void radeon_Color4fv_4f( const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLfloat *dest = rmesa->vb.floatcolorptr;
+ dest[0] = v[0];
+ dest[1] = v[1];
+ dest[2] = v[2];
+ dest[3] = v[3];
+}
+
+
+/* Color for float color formats:
+ */
+static void radeon_Color3ub_3f( GLubyte r, GLubyte g, GLubyte b )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLfloat *dest = rmesa->vb.floatcolorptr;
+ dest[0] = UBYTE_TO_FLOAT(r);
+ dest[1] = UBYTE_TO_FLOAT(g);
+ dest[2] = UBYTE_TO_FLOAT(b);
+}
+
+static void radeon_Color3ubv_3f( const GLubyte *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLfloat *dest = rmesa->vb.floatcolorptr;
+ dest[0] = UBYTE_TO_FLOAT(v[0]);
+ dest[1] = UBYTE_TO_FLOAT(v[1]);
+ dest[2] = UBYTE_TO_FLOAT(v[2]);
+}
+
+static void radeon_Color4ub_3f( GLubyte r, GLubyte g, GLubyte b, GLubyte a )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLfloat *dest = rmesa->vb.floatcolorptr;
+ dest[0] = UBYTE_TO_FLOAT(r);
+ dest[1] = UBYTE_TO_FLOAT(g);
+ dest[2] = UBYTE_TO_FLOAT(b);
+ ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3] = UBYTE_TO_FLOAT(a);
+}
+
+static void radeon_Color4ubv_3f( const GLubyte *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLfloat *dest = rmesa->vb.floatcolorptr;
+ dest[0] = UBYTE_TO_FLOAT(v[0]);
+ dest[1] = UBYTE_TO_FLOAT(v[1]);
+ dest[2] = UBYTE_TO_FLOAT(v[2]);
+ ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3] = UBYTE_TO_FLOAT(v[3]);
+}
+
+
+static void radeon_Color3f_3f( GLfloat r, GLfloat g, GLfloat b )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLfloat *dest = rmesa->vb.floatcolorptr;
+ dest[0] = r;
+ dest[1] = g;
+ dest[2] = b;
+}
+
+static void radeon_Color3fv_3f( const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLfloat *dest = rmesa->vb.floatcolorptr;
+ dest[0] = v[0];
+ dest[1] = v[1];
+ dest[2] = v[2];
+}
+
+static void radeon_Color4f_3f( GLfloat r, GLfloat g, GLfloat b, GLfloat a )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLfloat *dest = rmesa->vb.floatcolorptr;
+ dest[0] = r;
+ dest[1] = g;
+ dest[2] = b;
+ ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3] = a;
+}
+
+static void radeon_Color4fv_3f( const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLfloat *dest = rmesa->vb.floatcolorptr;
+ dest[0] = v[0];
+ dest[1] = v[1];
+ dest[2] = v[2];
+ ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3] = v[3];
+}
+
+
+/* Secondary Color:
+ */
+static void radeon_SecondaryColor3ubEXT_ub( GLubyte r, GLubyte g, GLubyte b )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ radeon_color_t *dest = rmesa->vb.specptr;
+ dest->red = r;
+ dest->green = g;
+ dest->blue = b;
+ dest->alpha = 0xff;
+}
+
+static void radeon_SecondaryColor3ubvEXT_ub( const GLubyte *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ radeon_color_t *dest = rmesa->vb.specptr;
+ dest->red = v[0];
+ dest->green = v[1];
+ dest->blue = v[2];
+ dest->alpha = 0xff;
+}
+
+static void radeon_SecondaryColor3fEXT_ub( GLfloat r, GLfloat g, GLfloat b )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ radeon_color_t *dest = rmesa->vb.specptr;
+ UNCLAMPED_FLOAT_TO_UBYTE( dest->red, r );
+ UNCLAMPED_FLOAT_TO_UBYTE( dest->green, g );
+ UNCLAMPED_FLOAT_TO_UBYTE( dest->blue, b );
+ dest->alpha = 255;
+}
+
+static void radeon_SecondaryColor3fvEXT_ub( const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ radeon_color_t *dest = rmesa->vb.specptr;
+ UNCLAMPED_FLOAT_TO_UBYTE( dest->red, v[0] );
+ UNCLAMPED_FLOAT_TO_UBYTE( dest->green, v[1] );
+ UNCLAMPED_FLOAT_TO_UBYTE( dest->blue, v[2] );
+ dest->alpha = 255;
+}
+
+static void radeon_SecondaryColor3ubEXT_3f( GLubyte r, GLubyte g, GLubyte b )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLfloat *dest = rmesa->vb.floatspecptr;
+ dest[0] = UBYTE_TO_FLOAT(r);
+ dest[1] = UBYTE_TO_FLOAT(g);
+ dest[2] = UBYTE_TO_FLOAT(b);
+ dest[3] = 1.0;
+}
+
+static void radeon_SecondaryColor3ubvEXT_3f( const GLubyte *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLfloat *dest = rmesa->vb.floatspecptr;
+ dest[0] = UBYTE_TO_FLOAT(v[0]);
+ dest[1] = UBYTE_TO_FLOAT(v[1]);
+ dest[2] = UBYTE_TO_FLOAT(v[2]);
+ dest[3] = 1.0;
+}
+
+static void radeon_SecondaryColor3fEXT_3f( GLfloat r, GLfloat g, GLfloat b )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLfloat *dest = rmesa->vb.floatspecptr;
+ dest[0] = r;
+ dest[1] = g;
+ dest[2] = b;
+ dest[3] = 1.0;
+}
+
+static void radeon_SecondaryColor3fvEXT_3f( const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLfloat *dest = rmesa->vb.floatspecptr;
+ dest[0] = v[0];
+ dest[1] = v[1];
+ dest[2] = v[2];
+ dest[3] = 1.0;
+}
+
+
+/* Normal
+ */
+static void radeon_Normal3f( GLfloat n0, GLfloat n1, GLfloat n2 )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLfloat *dest = rmesa->vb.normalptr;
+ dest[0] = n0;
+ dest[1] = n1;
+ dest[2] = n2;
+}
+
+static void radeon_Normal3fv( const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLfloat *dest = rmesa->vb.normalptr;
+ dest[0] = v[0];
+ dest[1] = v[1];
+ dest[2] = v[2];
+}
+
+
+/* TexCoord
+ */
+static void radeon_TexCoord1f( GLfloat s )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLfloat *dest = rmesa->vb.texcoordptr[0];
+ dest[0] = s;
+ dest[1] = 0;
+}
+
+static void radeon_TexCoord1fv( const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLfloat *dest = rmesa->vb.texcoordptr[0];
+ dest[0] = v[0];
+ dest[1] = 0;
+}
+
+static void radeon_TexCoord2f( GLfloat s, GLfloat t )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLfloat *dest = rmesa->vb.texcoordptr[0];
+ dest[0] = s;
+ dest[1] = t;
+}
+
+static void radeon_TexCoord2fv( const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLfloat *dest = rmesa->vb.texcoordptr[0];
+ dest[0] = v[0];
+ dest[1] = v[1];
+}
+
+
+/* MultiTexcoord
+ *
+ * Technically speaking, these functions should subtract GL_TEXTURE0 from
+ * \c target before masking and using it. The value of GL_TEXTURE0 is 0x84C0,
+ * which has the low-order 5 bits 0. For all possible valid values of
+ * \c target. Subtracting GL_TEXTURE0 has the net effect of masking \c target
+ * with 0x1F. Masking with 0x1F and then masking with 0x01 is redundant, so
+ * the subtraction has been omitted.
+ */
+
+static void radeon_MultiTexCoord1fARB( GLenum target, GLfloat s )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLfloat *dest = rmesa->vb.texcoordptr[target & 1];
+ dest[0] = s;
+ dest[1] = 0;
+}
+
+static void radeon_MultiTexCoord1fvARB( GLenum target, const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLfloat *dest = rmesa->vb.texcoordptr[target & 1];
+ dest[0] = v[0];
+ dest[1] = 0;
+}
+
+static void radeon_MultiTexCoord2fARB( GLenum target, GLfloat s, GLfloat t )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLfloat *dest = rmesa->vb.texcoordptr[target & 1];
+ dest[0] = s;
+ dest[1] = t;
+}
+
+static void radeon_MultiTexCoord2fvARB( GLenum target, const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLfloat *dest = rmesa->vb.texcoordptr[target & 1];
+ dest[0] = v[0];
+ dest[1] = v[1];
+}
+
+static struct dynfn *lookup( struct dynfn *l, int key )
+{
+ struct dynfn *f;
+
+ foreach( f, l ) {
+ if (f->key == key)
+ return f;
+ }
+
+ return 0;
+}
+
+/* Can't use the loopback template for this:
+ */
+
+#define CHOOSE(FN, FNTYPE, MASK, ACTIVE, ARGS1, ARGS2 ) \
+static void choose_##FN ARGS1 \
+{ \
+ GET_CURRENT_CONTEXT(ctx); \
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \
+ int key = rmesa->vb.vertex_format & (MASK|ACTIVE); \
+ struct dynfn *dfn; \
+ \
+ dfn = lookup( &rmesa->vb.dfn_cache.FN, key ); \
+ if (dfn == 0) \
+ dfn = rmesa->vb.codegen.FN( ctx, key ); \
+ else if (RADEON_DEBUG & DEBUG_CODEGEN) \
+ fprintf(stderr, "%s -- cached codegen\n", __FUNCTION__ ); \
+ \
+ if (dfn) \
+ ctx->Exec->FN = (FNTYPE)(dfn->code); \
+ else { \
+ if (RADEON_DEBUG & DEBUG_CODEGEN) \
+ fprintf(stderr, "%s -- generic version\n", __FUNCTION__ ); \
+ ctx->Exec->FN = radeon_##FN; \
+ } \
+ \
+ ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; \
+ ctx->Exec->FN ARGS2; \
+}
+
+
+
+/* For the _3f case, only allow one color function to be hooked in at
+ * a time. Eventually, use a similar mechanism to allow selecting the
+ * color component of the vertex format based on client behaviour.
+ *
+ * Note: Perform these actions even if there is a codegen or cached
+ * codegen version of the chosen function.
+ */
+#define CHOOSE_COLOR(FN, FNTYPE, NR, MASK, ACTIVE, ARGS1, ARGS2 ) \
+static void choose_##FN ARGS1 \
+{ \
+ GET_CURRENT_CONTEXT(ctx); \
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \
+ int key = rmesa->vb.vertex_format & (MASK|ACTIVE); \
+ struct dynfn *dfn; \
+ \
+ if (rmesa->vb.vertex_format & ACTIVE_PKCOLOR) { \
+ ctx->Exec->FN = radeon_##FN##_ub; \
+ } \
+ else if ((rmesa->vb.vertex_format & \
+ (ACTIVE_FPCOLOR|ACTIVE_FPALPHA)) == ACTIVE_FPCOLOR) { \
+ \
+ if (rmesa->vb.installed_color_3f_sz != NR) { \
+ rmesa->vb.installed_color_3f_sz = NR; \
+ if (NR == 3) ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3] = 1.0; \
+ if (ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) { \
+ radeon_copy_to_current( ctx ); \
+ _mesa_install_exec_vtxfmt( ctx, &rmesa->vb.vtxfmt ); \
+ ctx->Exec->FN ARGS2; \
+ return; \
+ } \
+ } \
+ \
+ ctx->Exec->FN = radeon_##FN##_3f; \
+ } \
+ else { \
+ ctx->Exec->FN = radeon_##FN##_4f; \
+ } \
+ \
+ \
+ dfn = lookup( &rmesa->vb.dfn_cache.FN, key ); \
+ if (!dfn) dfn = rmesa->vb.codegen.FN( ctx, key ); \
+ \
+ if (dfn) { \
+ if (RADEON_DEBUG & DEBUG_CODEGEN) \
+ fprintf(stderr, "%s -- codegen version\n", __FUNCTION__ ); \
+ ctx->Exec->FN = (FNTYPE)dfn->code; \
+ } \
+ else if (RADEON_DEBUG & DEBUG_CODEGEN) \
+ fprintf(stderr, "%s -- 'c' version\n", __FUNCTION__ ); \
+ \
+ ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; \
+ ctx->Exec->FN ARGS2; \
+}
+
+
+
+/* Right now there are both _ub and _3f versions of the secondary color
+ * functions. Currently, we only set-up the hardware to use the _ub versions.
+ * The _3f versions are needed for the cases where secondary color isn't used
+ * in the vertex format, but it still needs to be stored in the context
+ * state vector.
+ */
+#define CHOOSE_SECONDARY_COLOR(FN, FNTYPE, MASK, ACTIVE, ARGS1, ARGS2 ) \
+static void choose_##FN ARGS1 \
+{ \
+ GET_CURRENT_CONTEXT(ctx); \
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \
+ int key = rmesa->vb.vertex_format & (MASK|ACTIVE); \
+ struct dynfn *dfn = lookup( &rmesa->vb.dfn_cache.FN, key ); \
+ \
+ if (dfn == 0) \
+ dfn = rmesa->vb.codegen.FN( ctx, key ); \
+ else if (RADEON_DEBUG & DEBUG_CODEGEN) \
+ fprintf(stderr, "%s -- cached version\n", __FUNCTION__ ); \
+ \
+ if (dfn) \
+ ctx->Exec->FN = (FNTYPE)(dfn->code); \
+ else { \
+ if (RADEON_DEBUG & DEBUG_CODEGEN) \
+ fprintf(stderr, "%s -- generic version\n", __FUNCTION__ ); \
+ ctx->Exec->FN = ((rmesa->vb.vertex_format & ACTIVE_PKSPEC) != 0) \
+ ? radeon_##FN##_ub : radeon_##FN##_3f; \
+ } \
+ \
+ ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; \
+ ctx->Exec->FN ARGS2; \
+}
+
+
+
+
+
+/* Shorthands
+ */
+#define ACTIVE_XYZW (RADEON_CP_VC_FRMT_W0|RADEON_CP_VC_FRMT_Z)
+#define ACTIVE_NORM RADEON_CP_VC_FRMT_N0
+
+#define ACTIVE_PKCOLOR RADEON_CP_VC_FRMT_PKCOLOR
+#define ACTIVE_FPCOLOR RADEON_CP_VC_FRMT_FPCOLOR
+#define ACTIVE_FPALPHA RADEON_CP_VC_FRMT_FPALPHA
+#define ACTIVE_COLOR (ACTIVE_FPCOLOR|ACTIVE_PKCOLOR)
+
+#define ACTIVE_PKSPEC RADEON_CP_VC_FRMT_PKSPEC
+#define ACTIVE_FPSPEC RADEON_CP_VC_FRMT_FPSPEC
+#define ACTIVE_SPEC (ACTIVE_FPSPEC|ACTIVE_PKSPEC)
+
+#define ACTIVE_ST0 RADEON_CP_VC_FRMT_ST0
+#define ACTIVE_ST1 RADEON_CP_VC_FRMT_ST1
+#define ACTIVE_ST_ALL (RADEON_CP_VC_FRMT_ST1|RADEON_CP_VC_FRMT_ST0)
+
+/* Each codegen function should be able to be fully specified by a
+ * subsetted version of rmesa->vb.vertex_format.
+ */
+#define MASK_NORM (ACTIVE_XYZW)
+#define MASK_COLOR (MASK_NORM|ACTIVE_NORM)
+#define MASK_SPEC (MASK_COLOR|ACTIVE_COLOR)
+#define MASK_ST0 (MASK_SPEC|ACTIVE_SPEC)
+#define MASK_ST1 (MASK_ST0|ACTIVE_ST0)
+#define MASK_ST_ALL (MASK_ST1|ACTIVE_ST1)
+#define MASK_VERTEX (MASK_ST_ALL|ACTIVE_FPALPHA)
+
+
+typedef void (*p4f)( GLfloat, GLfloat, GLfloat, GLfloat );
+typedef void (*p3f)( GLfloat, GLfloat, GLfloat );
+typedef void (*p2f)( GLfloat, GLfloat );
+typedef void (*p1f)( GLfloat );
+typedef void (*pe2f)( GLenum, GLfloat, GLfloat );
+typedef void (*pe1f)( GLenum, GLfloat );
+typedef void (*p4ub)( GLubyte, GLubyte, GLubyte, GLubyte );
+typedef void (*p3ub)( GLubyte, GLubyte, GLubyte );
+typedef void (*pfv)( const GLfloat * );
+typedef void (*pefv)( GLenum, const GLfloat * );
+typedef void (*pubv)( const GLubyte * );
+
+
+CHOOSE(Normal3f, p3f, MASK_NORM, ACTIVE_NORM,
+ (GLfloat a,GLfloat b,GLfloat c), (a,b,c))
+CHOOSE(Normal3fv, pfv, MASK_NORM, ACTIVE_NORM,
+ (const GLfloat *v), (v))
+
+CHOOSE_COLOR(Color4ub, p4ub, 4, MASK_COLOR, ACTIVE_COLOR,
+ (GLubyte a,GLubyte b, GLubyte c, GLubyte d), (a,b,c,d))
+CHOOSE_COLOR(Color4ubv, pubv, 4, MASK_COLOR, ACTIVE_COLOR,
+ (const GLubyte *v), (v))
+CHOOSE_COLOR(Color3ub, p3ub, 3, MASK_COLOR, ACTIVE_COLOR,
+ (GLubyte a,GLubyte b, GLubyte c), (a,b,c))
+CHOOSE_COLOR(Color3ubv, pubv, 3, MASK_COLOR, ACTIVE_COLOR,
+ (const GLubyte *v), (v))
+
+CHOOSE_COLOR(Color4f, p4f, 4, MASK_COLOR, ACTIVE_COLOR,
+ (GLfloat a,GLfloat b, GLfloat c, GLfloat d), (a,b,c,d))
+CHOOSE_COLOR(Color4fv, pfv, 4, MASK_COLOR, ACTIVE_COLOR,
+ (const GLfloat *v), (v))
+CHOOSE_COLOR(Color3f, p3f, 3, MASK_COLOR, ACTIVE_COLOR,
+ (GLfloat a,GLfloat b, GLfloat c), (a,b,c))
+CHOOSE_COLOR(Color3fv, pfv, 3, MASK_COLOR, ACTIVE_COLOR,
+ (const GLfloat *v), (v))
+
+
+CHOOSE_SECONDARY_COLOR(SecondaryColor3ubEXT, p3ub, MASK_SPEC, ACTIVE_SPEC,
+ (GLubyte a,GLubyte b, GLubyte c), (a,b,c))
+CHOOSE_SECONDARY_COLOR(SecondaryColor3ubvEXT, pubv, MASK_SPEC, ACTIVE_SPEC,
+ (const GLubyte *v), (v))
+CHOOSE_SECONDARY_COLOR(SecondaryColor3fEXT, p3f, MASK_SPEC, ACTIVE_SPEC,
+ (GLfloat a,GLfloat b, GLfloat c), (a,b,c))
+CHOOSE_SECONDARY_COLOR(SecondaryColor3fvEXT, pfv, MASK_SPEC, ACTIVE_SPEC,
+ (const GLfloat *v), (v))
+
+CHOOSE(TexCoord2f, p2f, MASK_ST0, ACTIVE_ST0,
+ (GLfloat a,GLfloat b), (a,b))
+CHOOSE(TexCoord2fv, pfv, MASK_ST0, ACTIVE_ST0,
+ (const GLfloat *v), (v))
+CHOOSE(TexCoord1f, p1f, MASK_ST0, ACTIVE_ST0,
+ (GLfloat a), (a))
+CHOOSE(TexCoord1fv, pfv, MASK_ST0, ACTIVE_ST0,
+ (const GLfloat *v), (v))
+
+CHOOSE(MultiTexCoord2fARB, pe2f, MASK_ST_ALL, ACTIVE_ST_ALL,
+ (GLenum u,GLfloat a,GLfloat b), (u,a,b))
+CHOOSE(MultiTexCoord2fvARB, pefv, MASK_ST_ALL, ACTIVE_ST_ALL,
+ (GLenum u,const GLfloat *v), (u,v))
+CHOOSE(MultiTexCoord1fARB, pe1f, MASK_ST_ALL, ACTIVE_ST_ALL,
+ (GLenum u,GLfloat a), (u,a))
+CHOOSE(MultiTexCoord1fvARB, pefv, MASK_ST_ALL, ACTIVE_ST_ALL,
+ (GLenum u,const GLfloat *v), (u,v))
+
+CHOOSE(Vertex3f, p3f, MASK_VERTEX, MASK_VERTEX,
+ (GLfloat a,GLfloat b,GLfloat c), (a,b,c))
+CHOOSE(Vertex3fv, pfv, MASK_VERTEX, MASK_VERTEX,
+ (const GLfloat *v), (v))
+CHOOSE(Vertex2f, p2f, MASK_VERTEX, MASK_VERTEX,
+ (GLfloat a,GLfloat b), (a,b))
+CHOOSE(Vertex2fv, pfv, MASK_VERTEX, MASK_VERTEX,
+ (const GLfloat *v), (v))
+
+
+
+
+
+void radeonVtxfmtInitChoosers( GLvertexformat *vfmt )
+{
+ vfmt->Color3f = choose_Color3f;
+ vfmt->Color3fv = choose_Color3fv;
+ vfmt->Color3ub = choose_Color3ub;
+ vfmt->Color3ubv = choose_Color3ubv;
+ vfmt->Color4f = choose_Color4f;
+ vfmt->Color4fv = choose_Color4fv;
+ vfmt->Color4ub = choose_Color4ub;
+ vfmt->Color4ubv = choose_Color4ubv;
+ vfmt->SecondaryColor3fEXT = choose_SecondaryColor3fEXT;
+ vfmt->SecondaryColor3fvEXT = choose_SecondaryColor3fvEXT;
+ vfmt->SecondaryColor3ubEXT = choose_SecondaryColor3ubEXT;
+ vfmt->SecondaryColor3ubvEXT = choose_SecondaryColor3ubvEXT;
+ vfmt->MultiTexCoord1fARB = choose_MultiTexCoord1fARB;
+ vfmt->MultiTexCoord1fvARB = choose_MultiTexCoord1fvARB;
+ vfmt->MultiTexCoord2fARB = choose_MultiTexCoord2fARB;
+ vfmt->MultiTexCoord2fvARB = choose_MultiTexCoord2fvARB;
+ vfmt->Normal3f = choose_Normal3f;
+ vfmt->Normal3fv = choose_Normal3fv;
+ vfmt->TexCoord1f = choose_TexCoord1f;
+ vfmt->TexCoord1fv = choose_TexCoord1fv;
+ vfmt->TexCoord2f = choose_TexCoord2f;
+ vfmt->TexCoord2fv = choose_TexCoord2fv;
+ vfmt->Vertex2f = choose_Vertex2f;
+ vfmt->Vertex2fv = choose_Vertex2fv;
+ vfmt->Vertex3f = choose_Vertex3f;
+ vfmt->Vertex3fv = choose_Vertex3fv;
+}
+
+
+static struct dynfn *codegen_noop( GLcontext *ctx, int key )
+{
+ (void) ctx; (void) key;
+ return 0;
+}
+
+void radeonInitCodegen( struct dfn_generators *gen )
+{
+ gen->Vertex3f = codegen_noop;
+ gen->Vertex3fv = codegen_noop;
+ gen->Color4ub = codegen_noop;
+ gen->Color4ubv = codegen_noop;
+ gen->Normal3f = codegen_noop;
+ gen->Normal3fv = codegen_noop;
+ gen->TexCoord2f = codegen_noop;
+ gen->TexCoord2fv = codegen_noop;
+ gen->MultiTexCoord2fARB = codegen_noop;
+ gen->MultiTexCoord2fvARB = codegen_noop;
+ gen->Vertex2f = codegen_noop;
+ gen->Vertex2fv = codegen_noop;
+ gen->Color3ub = codegen_noop;
+ gen->Color3ubv = codegen_noop;
+ gen->Color4f = codegen_noop;
+ gen->Color4fv = codegen_noop;
+ gen->Color3f = codegen_noop;
+ gen->Color3fv = codegen_noop;
+ gen->SecondaryColor3fEXT = codegen_noop;
+ gen->SecondaryColor3fvEXT = codegen_noop;
+ gen->SecondaryColor3ubEXT = codegen_noop;
+ gen->SecondaryColor3ubvEXT = codegen_noop;
+ gen->TexCoord1f = codegen_noop;
+ gen->TexCoord1fv = codegen_noop;
+ gen->MultiTexCoord1fARB = codegen_noop;
+ gen->MultiTexCoord1fvARB = codegen_noop;
+
+ if (!getenv("RADEON_NO_CODEGEN")) {
+#if defined(USE_X86_ASM)
+ radeonInitX86Codegen( gen );
+#endif
+
+#if defined(USE_SSE_ASM)
+ radeonInitSSECodegen( gen );
+#endif
+ }
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_vtxfmt_sse.c b/src/mesa/drivers/dri/radeon/radeon_vtxfmt_sse.c
new file mode 100644
index 0000000000..0f2c82bd87
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_vtxfmt_sse.c
@@ -0,0 +1,232 @@
+/* $XFree86$ */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+ Tungsten Graphics Inc., Cedar Park, Texas.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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 "glheader.h"
+#include "imports.h"
+#include "simple_list.h"
+#include "radeon_vtxfmt.h"
+
+#if defined(USE_SSE_ASM)
+#include "X86/common_x86_asm.h"
+
+#define EXTERN( FUNC ) \
+extern const char *FUNC; \
+extern const char *FUNC##_end
+
+EXTERN( _sse_Attribute2fv );
+EXTERN( _sse_Attribute2f );
+EXTERN( _sse_Attribute3fv );
+EXTERN( _sse_Attribute3f );
+EXTERN( _sse_MultiTexCoord2fv );
+EXTERN( _sse_MultiTexCoord2f );
+EXTERN( _sse_MultiTexCoord2fv_2 );
+EXTERN( _sse_MultiTexCoord2f_2 );
+
+/* Build specialized versions of the immediate calls on the fly for
+ * the current state.
+ */
+
+static struct dynfn *radeon_makeSSEAttribute2fv( struct dynfn * cache, int key,
+ const char * name, void * dest)
+{
+ struct dynfn *dfn = MALLOC_STRUCT( dynfn );
+
+ if (RADEON_DEBUG & DEBUG_CODEGEN)
+ fprintf(stderr, "%s 0x%08x\n", name, key );
+
+ DFN ( _sse_Attribute2fv, (*cache) );
+ FIXUP(dfn->code, 10, 0x0, (int)dest);
+ return dfn;
+}
+
+static struct dynfn *radeon_makeSSEAttribute2f( struct dynfn * cache, int key,
+ const char * name, void * dest )
+{
+ struct dynfn *dfn = MALLOC_STRUCT( dynfn );
+
+ if (RADEON_DEBUG & DEBUG_CODEGEN)
+ fprintf(stderr, "%s 0x%08x\n", name, key );
+
+ DFN ( _sse_Attribute2f, (*cache) );
+ FIXUP(dfn->code, 8, 0x0, (int)dest);
+ return dfn;
+}
+
+static struct dynfn *radeon_makeSSEAttribute3fv( struct dynfn * cache, int key,
+ const char * name, void * dest)
+{
+ struct dynfn *dfn = MALLOC_STRUCT( dynfn );
+
+ if (RADEON_DEBUG & DEBUG_CODEGEN)
+ fprintf(stderr, "%s 0x%08x\n", name, key );
+
+ DFN ( _sse_Attribute3fv, (*cache) );
+ FIXUP(dfn->code, 13, 0x0, (int)dest);
+ FIXUP(dfn->code, 18, 0x8, 8+(int)dest);
+ return dfn;
+}
+
+static struct dynfn *radeon_makeSSEAttribute3f( struct dynfn * cache, int key,
+ const char * name, void * dest )
+{
+ struct dynfn *dfn = MALLOC_STRUCT( dynfn );
+
+ if (RADEON_DEBUG & DEBUG_CODEGEN)
+ fprintf(stderr, "%s 0x%08x\n", name, key );
+
+ DFN ( _sse_Attribute3f, (*cache) );
+ FIXUP(dfn->code, 12, 0x0, (int)dest);
+ FIXUP(dfn->code, 17, 0x8, 8+(int)dest);
+ return dfn;
+}
+
+static struct dynfn * radeon_makeSSENormal3fv( GLcontext *ctx, int key )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ return radeon_makeSSEAttribute3fv( & rmesa->vb.dfn_cache.Normal3fv, key,
+ __FUNCTION__, rmesa->vb.normalptr );
+}
+
+static struct dynfn *radeon_makeSSENormal3f( GLcontext *ctx, int key )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ return radeon_makeSSEAttribute3f( & rmesa->vb.dfn_cache.Normal3f, key,
+ __FUNCTION__, rmesa->vb.normalptr );
+}
+
+static struct dynfn *radeon_makeSSEColor3fv( GLcontext *ctx, int key )
+{
+ if (key & (RADEON_CP_VC_FRMT_PKCOLOR|RADEON_CP_VC_FRMT_FPALPHA))
+ return 0;
+ else
+ {
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ return radeon_makeSSEAttribute3fv( & rmesa->vb.dfn_cache.Color3fv, key,
+ __FUNCTION__, rmesa->vb.floatcolorptr );
+ }
+}
+
+static struct dynfn *radeon_makeSSEColor3f( GLcontext *ctx, int key )
+{
+ if (key & (RADEON_CP_VC_FRMT_PKCOLOR|RADEON_CP_VC_FRMT_FPALPHA))
+ return 0;
+ else
+ {
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ return radeon_makeSSEAttribute3f( & rmesa->vb.dfn_cache.Color3f, key,
+ __FUNCTION__, rmesa->vb.floatcolorptr );
+ }
+}
+
+static struct dynfn *radeon_makeSSETexCoord2fv( GLcontext *ctx, int key )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ return radeon_makeSSEAttribute2fv( & rmesa->vb.dfn_cache.TexCoord2fv, key,
+ __FUNCTION__, rmesa->vb.texcoordptr[0] );
+}
+
+static struct dynfn *radeon_makeSSETexCoord2f( GLcontext *ctx, int key )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ return radeon_makeSSEAttribute2f( & rmesa->vb.dfn_cache.TexCoord2f, key,
+ __FUNCTION__, rmesa->vb.texcoordptr[0] );
+}
+
+static struct dynfn *radeon_makeSSEMultiTexCoord2fv( GLcontext *ctx, int key )
+{
+ struct dynfn *dfn = MALLOC_STRUCT( dynfn );
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ if (RADEON_DEBUG & DEBUG_CODEGEN)
+ fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
+
+ if ((key & (RADEON_CP_VC_FRMT_ST0|RADEON_CP_VC_FRMT_ST1)) ==
+ (RADEON_CP_VC_FRMT_ST0|RADEON_CP_VC_FRMT_ST1)) {
+ DFN ( _sse_MultiTexCoord2fv, rmesa->vb.dfn_cache.MultiTexCoord2fvARB );
+ FIXUP(dfn->code, 18, 0xdeadbeef, (int)rmesa->vb.texcoordptr[0]);
+ } else {
+ DFN ( _sse_MultiTexCoord2fv_2, rmesa->vb.dfn_cache.MultiTexCoord2fvARB );
+ FIXUP(dfn->code, 14, 0x0, (int)rmesa->vb.texcoordptr);
+ }
+ return dfn;
+}
+
+static struct dynfn *radeon_makeSSEMultiTexCoord2f( GLcontext *ctx, int key )
+{
+ struct dynfn *dfn = MALLOC_STRUCT( dynfn );
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ if (RADEON_DEBUG & DEBUG_CODEGEN)
+ fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
+
+ if ((key & (RADEON_CP_VC_FRMT_ST0|RADEON_CP_VC_FRMT_ST1)) ==
+ (RADEON_CP_VC_FRMT_ST0|RADEON_CP_VC_FRMT_ST1)) {
+ DFN ( _sse_MultiTexCoord2f, rmesa->vb.dfn_cache.MultiTexCoord2fARB );
+ FIXUP(dfn->code, 16, 0xdeadbeef, (int)rmesa->vb.texcoordptr[0]);
+ } else {
+ DFN ( _sse_MultiTexCoord2f_2, rmesa->vb.dfn_cache.MultiTexCoord2fARB );
+ FIXUP(dfn->code, 15, 0x0, (int)rmesa->vb.texcoordptr);
+ }
+ return dfn;
+}
+
+void radeonInitSSECodegen( struct dfn_generators *gen )
+{
+ if ( cpu_has_xmm ) {
+ gen->Normal3fv = (void *) radeon_makeSSENormal3fv;
+ gen->Normal3f = (void *) radeon_makeSSENormal3f;
+ gen->Color3fv = (void *) radeon_makeSSEColor3fv;
+ gen->Color3f = (void *) radeon_makeSSEColor3f;
+ gen->TexCoord2fv = (void *) radeon_makeSSETexCoord2fv;
+ gen->TexCoord2f = (void *) radeon_makeSSETexCoord2f;
+ gen->MultiTexCoord2fvARB = (void *) radeon_makeSSEMultiTexCoord2fv;
+ gen->MultiTexCoord2fARB = (void *) radeon_makeSSEMultiTexCoord2f;
+ }
+}
+
+#else
+
+void radeonInitSSECodegen( struct dfn_generators *gen )
+{
+ (void) gen;
+}
+
+#endif
diff --git a/src/mesa/drivers/dri/radeon/radeon_vtxfmt_x86.c b/src/mesa/drivers/dri/radeon/radeon_vtxfmt_x86.c
new file mode 100644
index 0000000000..92941ca5f8
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_vtxfmt_x86.c
@@ -0,0 +1,437 @@
+/* $XFree86$ */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+ Tungsten Graphics Inc., Cedar Park, Texas.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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 "glheader.h"
+#include "imports.h"
+#include "simple_list.h"
+#include "radeon_vtxfmt.h"
+
+#if defined(USE_X86_ASM)
+
+#define EXTERN( FUNC ) \
+extern const char *FUNC; \
+extern const char *FUNC##_end
+
+EXTERN ( _x86_Attribute2fv );
+EXTERN ( _x86_Attribute2f );
+EXTERN ( _x86_Attribute3fv );
+EXTERN ( _x86_Attribute3f );
+EXTERN ( _x86_Vertex3fv_6 );
+EXTERN ( _x86_Vertex3fv_8 );
+EXTERN ( _x86_Vertex3fv );
+EXTERN ( _x86_Vertex3f_4 );
+EXTERN ( _x86_Vertex3f_6 );
+EXTERN ( _x86_Vertex3f );
+EXTERN ( _x86_Color4ubv_ub );
+EXTERN ( _x86_Color4ubv_4f );
+EXTERN ( _x86_Color4ub_ub );
+EXTERN ( _x86_MultiTexCoord2fv );
+EXTERN ( _x86_MultiTexCoord2fv_2 );
+EXTERN ( _x86_MultiTexCoord2f );
+EXTERN ( _x86_MultiTexCoord2f_2 );
+
+
+/* Build specialized versions of the immediate calls on the fly for
+ * the current state. Generic x86 versions.
+ */
+
+struct dynfn *radeon_makeX86Vertex3f( GLcontext *ctx, int key )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ struct dynfn *dfn = MALLOC_STRUCT( dynfn );
+
+ if (RADEON_DEBUG & DEBUG_CODEGEN)
+ fprintf(stderr, "%s 0x%08x %d\n", __FUNCTION__, key, rmesa->vb.vertex_size );
+
+ switch (rmesa->vb.vertex_size) {
+ case 4: {
+
+ DFN ( _x86_Vertex3f_4, rmesa->vb.dfn_cache.Vertex3f );
+ FIXUP(dfn->code, 2, 0x0, (int)&rmesa->vb.dmaptr);
+ FIXUP(dfn->code, 25, 0x0, (int)&rmesa->vb.vertex[3]);
+ FIXUP(dfn->code, 36, 0x0, (int)&rmesa->vb.counter);
+ FIXUP(dfn->code, 46, 0x0, (int)&rmesa->vb.dmaptr);
+ FIXUP(dfn->code, 51, 0x0, (int)&rmesa->vb.counter);
+ FIXUP(dfn->code, 60, 0x0, (int)&rmesa->vb.notify);
+ break;
+ }
+ case 6: {
+
+ DFN ( _x86_Vertex3f_6, rmesa->vb.dfn_cache.Vertex3f );
+ FIXUP(dfn->code, 3, 0x0, (int)&rmesa->vb.dmaptr);
+ FIXUP(dfn->code, 28, 0x0, (int)&rmesa->vb.vertex[3]);
+ FIXUP(dfn->code, 34, 0x0, (int)&rmesa->vb.vertex[4]);
+ FIXUP(dfn->code, 40, 0x0, (int)&rmesa->vb.vertex[5]);
+ FIXUP(dfn->code, 57, 0x0, (int)&rmesa->vb.counter);
+ FIXUP(dfn->code, 63, 0x0, (int)&rmesa->vb.dmaptr);
+ FIXUP(dfn->code, 70, 0x0, (int)&rmesa->vb.counter);
+ FIXUP(dfn->code, 79, 0x0, (int)&rmesa->vb.notify);
+ break;
+ }
+ default: {
+
+ DFN ( _x86_Vertex3f, rmesa->vb.dfn_cache.Vertex3f );
+ FIXUP(dfn->code, 3, 0x0, (int)&rmesa->vb.vertex[3]);
+ FIXUP(dfn->code, 9, 0x0, (int)&rmesa->vb.dmaptr);
+ FIXUP(dfn->code, 37, 0x0, rmesa->vb.vertex_size-3);
+ FIXUP(dfn->code, 44, 0x0, (int)&rmesa->vb.counter);
+ FIXUP(dfn->code, 50, 0x0, (int)&rmesa->vb.dmaptr);
+ FIXUP(dfn->code, 56, 0x0, (int)&rmesa->vb.counter);
+ FIXUP(dfn->code, 67, 0x0, (int)&rmesa->vb.notify);
+ break;
+ }
+ }
+
+ return dfn;
+}
+
+
+
+struct dynfn *radeon_makeX86Vertex3fv( GLcontext *ctx, int key )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ struct dynfn *dfn = MALLOC_STRUCT( dynfn );
+
+ if (RADEON_DEBUG & DEBUG_CODEGEN)
+ fprintf(stderr, "%s 0x%08x %d\n", __FUNCTION__, key, rmesa->vb.vertex_size );
+
+ switch (rmesa->vb.vertex_size) {
+ case 6: {
+
+ DFN ( _x86_Vertex3fv_6, rmesa->vb.dfn_cache.Vertex3fv );
+ FIXUP(dfn->code, 1, 0x00000000, (int)&rmesa->vb.dmaptr);
+ FIXUP(dfn->code, 27, 0x0000001c, (int)&rmesa->vb.vertex[3]);
+ FIXUP(dfn->code, 33, 0x00000020, (int)&rmesa->vb.vertex[4]);
+ FIXUP(dfn->code, 45, 0x00000024, (int)&rmesa->vb.vertex[5]);
+ FIXUP(dfn->code, 56, 0x00000000, (int)&rmesa->vb.dmaptr);
+ FIXUP(dfn->code, 61, 0x00000004, (int)&rmesa->vb.counter);
+ FIXUP(dfn->code, 67, 0x00000004, (int)&rmesa->vb.counter);
+ FIXUP(dfn->code, 76, 0x00000008, (int)&rmesa->vb.notify);
+ break;
+ }
+
+
+ case 8: {
+
+ DFN ( _x86_Vertex3fv_8, rmesa->vb.dfn_cache.Vertex3fv );
+ FIXUP(dfn->code, 1, 0x00000000, (int)&rmesa->vb.dmaptr);
+ FIXUP(dfn->code, 27, 0x0000001c, (int)&rmesa->vb.vertex[3]);
+ FIXUP(dfn->code, 33, 0x00000020, (int)&rmesa->vb.vertex[4]);
+ FIXUP(dfn->code, 45, 0x0000001c, (int)&rmesa->vb.vertex[5]);
+ FIXUP(dfn->code, 51, 0x00000020, (int)&rmesa->vb.vertex[6]);
+ FIXUP(dfn->code, 63, 0x00000024, (int)&rmesa->vb.vertex[7]);
+ FIXUP(dfn->code, 74, 0x00000000, (int)&rmesa->vb.dmaptr);
+ FIXUP(dfn->code, 79, 0x00000004, (int)&rmesa->vb.counter);
+ FIXUP(dfn->code, 85, 0x00000004, (int)&rmesa->vb.counter);
+ FIXUP(dfn->code, 94, 0x00000008, (int)&rmesa->vb.notify);
+ break;
+ }
+
+
+
+ default: {
+
+ DFN ( _x86_Vertex3fv, rmesa->vb.dfn_cache.Vertex3fv );
+ FIXUP(dfn->code, 8, 0x01010101, (int)&rmesa->vb.dmaptr);
+ FIXUP(dfn->code, 32, 0x00000006, rmesa->vb.vertex_size-3);
+ FIXUP(dfn->code, 37, 0x00000058, (int)&rmesa->vb.vertex[3]);
+ FIXUP(dfn->code, 45, 0x01010101, (int)&rmesa->vb.dmaptr);
+ FIXUP(dfn->code, 50, 0x02020202, (int)&rmesa->vb.counter);
+ FIXUP(dfn->code, 58, 0x02020202, (int)&rmesa->vb.counter);
+ FIXUP(dfn->code, 67, 0x0, (int)&rmesa->vb.notify);
+ break;
+ }
+ }
+
+ return dfn;
+}
+
+static struct dynfn *
+radeon_makeX86Attribute2fv( struct dynfn * cache, int key,
+ const char * name, void * dest )
+{
+ struct dynfn *dfn = MALLOC_STRUCT( dynfn );
+
+ if (RADEON_DEBUG & DEBUG_CODEGEN)
+ fprintf(stderr, "%s 0x%08x\n", name, key );
+
+ DFN ( _x86_Attribute2fv, (*cache) );
+ FIXUP(dfn->code, 11, 0x0, (int)dest);
+ FIXUP(dfn->code, 16, 0x4, 4+(int)dest);
+
+ return dfn;
+}
+
+static struct dynfn *
+radeon_makeX86Attribute2f( struct dynfn * cache, int key,
+ const char * name, void * dest )
+{
+ struct dynfn *dfn = MALLOC_STRUCT( dynfn );
+
+ if (RADEON_DEBUG & DEBUG_CODEGEN)
+ fprintf(stderr, "%s 0x%08x\n", name, key );
+
+ DFN ( _x86_Attribute2f, (*cache) );
+ FIXUP(dfn->code, 1, 0x0, (int)dest);
+
+ return dfn;
+}
+
+
+static struct dynfn *
+radeon_makeX86Attribute3fv( struct dynfn * cache, int key,
+ const char * name, void * dest )
+{
+ struct dynfn *dfn = MALLOC_STRUCT( dynfn );
+
+ if (RADEON_DEBUG & DEBUG_CODEGEN)
+ fprintf(stderr, "%s 0x%08x\n", name, key );
+
+ DFN ( _x86_Attribute3fv, (*cache) );
+ FIXUP(dfn->code, 14, 0x0, (int)dest);
+ FIXUP(dfn->code, 20, 0x4, 4+(int)dest);
+ FIXUP(dfn->code, 25, 0x8, 8+(int)dest);
+
+ return dfn;
+}
+
+static struct dynfn *
+radeon_makeX86Attribute3f( struct dynfn * cache, int key,
+ const char * name, void * dest )
+{
+ struct dynfn *dfn = MALLOC_STRUCT( dynfn );
+
+ if (RADEON_DEBUG & DEBUG_CODEGEN)
+ fprintf(stderr, "%s 0x%08x\n", name, key );
+
+ DFN ( _x86_Attribute3f, (*cache) );
+ FIXUP(dfn->code, 14, 0x0, (int)dest);
+ FIXUP(dfn->code, 20, 0x4, 4+(int)dest);
+ FIXUP(dfn->code, 25, 0x8, 8+(int)dest);
+
+ return dfn;
+}
+
+struct dynfn *radeon_makeX86Normal3fv( GLcontext *ctx, int key )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ return radeon_makeX86Attribute3fv( & rmesa->vb.dfn_cache.Normal3fv, key,
+ __FUNCTION__, rmesa->vb.normalptr );
+}
+
+struct dynfn *radeon_makeX86Normal3f( GLcontext *ctx, int key )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ return radeon_makeX86Attribute3f( & rmesa->vb.dfn_cache.Normal3f, key,
+ __FUNCTION__, rmesa->vb.normalptr );
+}
+
+struct dynfn *radeon_makeX86Color4ubv( GLcontext *ctx, int key )
+{
+ struct dynfn *dfn = MALLOC_STRUCT( dynfn );
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+
+ if (RADEON_DEBUG & DEBUG_CODEGEN)
+ fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
+
+ if (key & RADEON_CP_VC_FRMT_PKCOLOR) {
+ DFN ( _x86_Color4ubv_ub, rmesa->vb.dfn_cache.Color4ubv);
+ FIXUP(dfn->code, 5, 0x12345678, (int)rmesa->vb.colorptr);
+ return dfn;
+ }
+ else {
+
+ DFN ( _x86_Color4ubv_4f, rmesa->vb.dfn_cache.Color4ubv);
+ FIXUP(dfn->code, 2, 0x00000000, (int)_mesa_ubyte_to_float_color_tab);
+ FIXUP(dfn->code, 27, 0xdeadbeaf, (int)rmesa->vb.floatcolorptr);
+ FIXUP(dfn->code, 33, 0xdeadbeaf, (int)rmesa->vb.floatcolorptr+4);
+ FIXUP(dfn->code, 55, 0xdeadbeaf, (int)rmesa->vb.floatcolorptr+8);
+ FIXUP(dfn->code, 61, 0xdeadbeaf, (int)rmesa->vb.floatcolorptr+12);
+ return dfn;
+ }
+}
+
+struct dynfn *radeon_makeX86Color4ub( GLcontext *ctx, int key )
+{
+ if (RADEON_DEBUG & DEBUG_CODEGEN)
+ fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
+
+ if (key & RADEON_CP_VC_FRMT_PKCOLOR) {
+ struct dynfn *dfn = MALLOC_STRUCT( dynfn );
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ DFN ( _x86_Color4ub_ub, rmesa->vb.dfn_cache.Color4ub );
+ FIXUP(dfn->code, 18, 0x0, (int)rmesa->vb.colorptr);
+ FIXUP(dfn->code, 24, 0x0, (int)rmesa->vb.colorptr+1);
+ FIXUP(dfn->code, 30, 0x0, (int)rmesa->vb.colorptr+2);
+ FIXUP(dfn->code, 36, 0x0, (int)rmesa->vb.colorptr+3);
+ return dfn;
+ }
+ else
+ return 0;
+}
+
+
+struct dynfn *radeon_makeX86Color3fv( GLcontext *ctx, int key )
+{
+ if (key & (RADEON_CP_VC_FRMT_PKCOLOR|RADEON_CP_VC_FRMT_FPALPHA))
+ return 0;
+ else
+ {
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ return radeon_makeX86Attribute3fv( & rmesa->vb.dfn_cache.Color3fv, key,
+ __FUNCTION__, rmesa->vb.floatcolorptr );
+ }
+}
+
+struct dynfn *radeon_makeX86Color3f( GLcontext *ctx, int key )
+{
+ if (key & (RADEON_CP_VC_FRMT_PKCOLOR|RADEON_CP_VC_FRMT_FPALPHA))
+ return 0;
+ else
+ {
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ return radeon_makeX86Attribute3f( & rmesa->vb.dfn_cache.Color3f, key,
+ __FUNCTION__, rmesa->vb.floatcolorptr );
+ }
+}
+
+
+
+struct dynfn *radeon_makeX86TexCoord2fv( GLcontext *ctx, int key )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ return radeon_makeX86Attribute2fv( & rmesa->vb.dfn_cache.TexCoord2fv, key,
+ __FUNCTION__, rmesa->vb.texcoordptr[0] );
+}
+
+struct dynfn *radeon_makeX86TexCoord2f( GLcontext *ctx, int key )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ return radeon_makeX86Attribute2f( & rmesa->vb.dfn_cache.TexCoord2f, key,
+ __FUNCTION__, rmesa->vb.texcoordptr[0] );
+}
+
+struct dynfn *radeon_makeX86MultiTexCoord2fvARB( GLcontext *ctx, int key )
+{
+ struct dynfn *dfn = MALLOC_STRUCT( dynfn );
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ if (RADEON_DEBUG & DEBUG_CODEGEN)
+ fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
+
+ if ((key & (RADEON_CP_VC_FRMT_ST0|RADEON_CP_VC_FRMT_ST1)) ==
+ (RADEON_CP_VC_FRMT_ST0|RADEON_CP_VC_FRMT_ST1)) {
+ DFN ( _x86_MultiTexCoord2fv, rmesa->vb.dfn_cache.MultiTexCoord2fvARB );
+ FIXUP(dfn->code, 21, 0xdeadbeef, (int)rmesa->vb.texcoordptr[0]);
+ FIXUP(dfn->code, 27, 0xdeadbeef, (int)rmesa->vb.texcoordptr[0]+4);
+ } else {
+ DFN ( _x86_MultiTexCoord2fv_2, rmesa->vb.dfn_cache.MultiTexCoord2fvARB );
+ FIXUP(dfn->code, 14, 0x0, (int)rmesa->vb.texcoordptr);
+ }
+ return dfn;
+}
+
+struct dynfn *radeon_makeX86MultiTexCoord2fARB( GLcontext *ctx,
+ int key )
+{
+ struct dynfn *dfn = MALLOC_STRUCT( dynfn );
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+ if (RADEON_DEBUG & DEBUG_CODEGEN)
+ fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
+
+ if ((key & (RADEON_CP_VC_FRMT_ST0|RADEON_CP_VC_FRMT_ST1)) ==
+ (RADEON_CP_VC_FRMT_ST0|RADEON_CP_VC_FRMT_ST1)) {
+ DFN ( _x86_MultiTexCoord2f, rmesa->vb.dfn_cache.MultiTexCoord2fARB );
+ FIXUP(dfn->code, 20, 0xdeadbeef, (int)rmesa->vb.texcoordptr[0]);
+ FIXUP(dfn->code, 26, 0xdeadbeef, (int)rmesa->vb.texcoordptr[0]+4);
+ }
+ else {
+ /* Note: this might get generated multiple times, even though the
+ * actual emitted code is the same.
+ */
+ DFN ( _x86_MultiTexCoord2f_2, rmesa->vb.dfn_cache.MultiTexCoord2fARB );
+ FIXUP(dfn->code, 18, 0x0, (int)rmesa->vb.texcoordptr);
+ }
+ return dfn;
+}
+
+
+void radeonInitX86Codegen( struct dfn_generators *gen )
+{
+ gen->Vertex3f = radeon_makeX86Vertex3f;
+ gen->Vertex3fv = radeon_makeX86Vertex3fv;
+ gen->Color4ub = radeon_makeX86Color4ub; /* PKCOLOR only */
+ gen->Color4ubv = radeon_makeX86Color4ubv; /* PKCOLOR only */
+ gen->Normal3f = radeon_makeX86Normal3f;
+ gen->Normal3fv = radeon_makeX86Normal3fv;
+ gen->TexCoord2f = radeon_makeX86TexCoord2f;
+ gen->TexCoord2fv = radeon_makeX86TexCoord2fv;
+ gen->MultiTexCoord2fARB = radeon_makeX86MultiTexCoord2fARB;
+ gen->MultiTexCoord2fvARB = radeon_makeX86MultiTexCoord2fvARB;
+ gen->Color3f = radeon_makeX86Color3f;
+ gen->Color3fv = radeon_makeX86Color3fv;
+
+ /* Not done:
+ */
+/* gen->Vertex2f = radeon_makeX86Vertex2f; */
+/* gen->Vertex2fv = radeon_makeX86Vertex2fv; */
+/* gen->Color3ub = radeon_makeX86Color3ub; */
+/* gen->Color3ubv = radeon_makeX86Color3ubv; */
+/* gen->Color4f = radeon_makeX86Color4f; */
+/* gen->Color4fv = radeon_makeX86Color4fv; */
+/* gen->TexCoord1f = radeon_makeX86TexCoord1f; */
+/* gen->TexCoord1fv = radeon_makeX86TexCoord1fv; */
+/* gen->MultiTexCoord1fARB = radeon_makeX86MultiTexCoord1fARB; */
+/* gen->MultiTexCoord1fvARB = radeon_makeX86MultiTexCoord1fvARB; */
+}
+
+
+#else
+
+void radeonInitX86Codegen( struct dfn_generators *gen )
+{
+ (void) gen;
+}
+
+#endif
diff --git a/src/mesa/drivers/dri/radeon/server/radeon_common.h b/src/mesa/drivers/dri/radeon/server/radeon_common.h
index c26ccd3cc2..0792b5c2e0 100644
--- a/src/mesa/drivers/dri/radeon/server/radeon_common.h
+++ b/src/mesa/drivers/dri/radeon/server/radeon_common.h
@@ -1,19 +1,5 @@
-/**
- * \file server/radeon_common.h
- * \brief Common header definitions for Radeon 2D/3D/DRM driver suite.
+/* radeon_common.h -- common header definitions for Radeon 2D/3D/DRM suite
*
- * \note Some of these structures are meant for backward compatibility and
- * aren't used by the subset driver.
- *
- * \author Gareth Hughes <gareth@valinux.com>
- * \author Kevin E. Martin <martin@valinux.com>
- * \author Keith Whitwell <keith@tungstengraphics.com>
- *
- * \author Converted to common header format by
- * Jens Owen <jens@tungstengraphics.com>
- */
-
-/*
* Copyright 2000 VA Linux Systems, Inc., Fremont, California.
* Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
@@ -36,10 +22,19 @@
* 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.
+ *
+ * Author:
+ * Gareth Hughes <gareth@valinux.com>
+ * Kevin E. Martin <martin@valinux.com>
+ * Keith Whitwell <keith@tungstengraphics.com>
+ *
+ * Converted to common header format:
+ * Jens Owen <jens@tungstengraphics.com>
+ *
+ * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/xf86drmRadeon.h,v 1.6 2001/04/16 15:02:13 tsi Exp $
+ *
*/
-/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/xf86drmRadeon.h,v 1.6 2001/04/16 15:02:13 tsi Exp $ */
-
#ifndef _RADEON_COMMON_H_
#define _RADEON_COMMON_H_
@@ -90,42 +85,33 @@
#define RADEON_CLEAR_DEPTH 4
-/**
- * \brief DRM_RADEON_CP_INIT ioctl argument type.
- */
typedef struct {
enum {
- DRM_RADEON_INIT_CP = 0x01, /**< \brief initialize CP */
- DRM_RADEON_CLEANUP_CP = 0x02, /**< \brief clean up CP */
- DRM_RADEON_INIT_R200_CP = 0x03 /**< \brief initialize R200 CP */
- } func; /**< \brief request */
- unsigned long sarea_priv_offset; /**< \brief SAREA private offset */
- int is_pci; /**< \brief is current card a PCI card? */
- int cp_mode; /**< \brief CP mode */
- int agp_size; /**< \brief AGP space size */
- int ring_size; /**< \brief CP ring buffer size */
- int usec_timeout; /**< \brief timeout for DRM operations in usecs */
-
- unsigned int fb_bpp;
- unsigned int front_offset; /**< \brief front color buffer offset */
- unsigned int front_pitch; /**< \brief front color buffer pitch */
- unsigned int back_offset; /**< \brief back color buffer offset */
- unsigned int back_pitch; /**< \brief back color buffer pitch*/
- unsigned int depth_bpp; /**< \brief depth buffer bits-per-pixel */
- unsigned int depth_offset; /**< \brief depth buffer offset */
- unsigned int depth_pitch; /**< \brief depth buffer pitch */
-
- unsigned long fb_offset; /**< \brief framebuffer offset */
- unsigned long mmio_offset; /**< \brief MMIO register offset */
- unsigned long ring_offset; /**< \brief CP ring buffer offset */
- unsigned long ring_rptr_offset; /**< \brief CP ring buffer read pointer offset */
- unsigned long buffers_offset; /**< \brief vertex buffers offset */
- unsigned long agp_textures_offset; /**< \brief AGP textures offset */
+ DRM_RADEON_INIT_CP = 0x01,
+ DRM_RADEON_CLEANUP_CP = 0x02,
+ DRM_RADEON_INIT_R200_CP = 0x03
+ } func;
+ unsigned long sarea_priv_offset;
+ int is_pci;
+ int cp_mode;
+ int agp_size;
+ int ring_size;
+ int usec_timeout;
+
+ unsigned int fb_bpp;
+ unsigned int front_offset, front_pitch;
+ unsigned int back_offset, back_pitch;
+ unsigned int depth_bpp;
+ unsigned int depth_offset, depth_pitch;
+
+ unsigned long fb_offset;
+ unsigned long mmio_offset;
+ unsigned long ring_offset;
+ unsigned long ring_rptr_offset;
+ unsigned long buffers_offset;
+ unsigned long agp_textures_offset;
} drmRadeonInit;
-/**
- * \brief DRM_RADEON_CP_STOP ioctl argument type.
- */
typedef struct {
int flush;
int idle;
@@ -143,17 +129,13 @@ typedef union drmRadeonClearR {
unsigned int ui[5];
} drmRadeonClearRect;
-/**
- * \brief DRM_RADEON_CLEAR ioctl argument type.
- */
typedef struct drmRadeonClearT {
- unsigned int flags; /**< \brief bitmask of the planes to clear */
- unsigned int clear_color; /**< \brief color buffer clear value */
- unsigned int clear_depth; /**< \brief depth buffer clear value */
- unsigned int color_mask; /**< \brief color buffer clear mask */
- unsigned int depth_mask; /**< \brief stencil buffer clear value
- * \todo Misnamed field. */
- drmRadeonClearRect *depth_boxes; /**< \brief depth buffer cliprects */
+ unsigned int flags;
+ unsigned int clear_color;
+ unsigned int clear_depth;
+ unsigned int color_mask;
+ unsigned int depth_mask; /* misnamed field: should be stencil */
+ drmRadeonClearRect *depth_boxes;
} drmRadeonClearType;
typedef struct drmRadeonFullscreenT {
@@ -163,16 +145,10 @@ typedef struct drmRadeonFullscreenT {
} func;
} drmRadeonFullscreenType;
-/**
- * \brief DRM_RADEON_STIPPLE ioctl argument type.
- */
typedef struct {
unsigned int *mask;
} drmRadeonStipple;
-/**
- * \brief Texture image for drmRadeonTexture.
- */
typedef struct {
unsigned int x;
unsigned int y;
@@ -181,22 +157,18 @@ typedef struct {
const void *data;
} drmRadeonTexImage;
-/**
- * \brief DRM_RADEON_TEXTURE ioctl argument type.
- */
typedef struct {
- int offset; /**< \brief texture offset */
- int pitch; /**< \brief texture pitch */
- int format; /**< \brief pixel format */
- int width; /**< \brief texture width */
- int height; /**< \brief texture height */
- drmRadeonTexImage *image; /**< \brief image */
+ int offset;
+ int pitch;
+ int format;
+ int width; /* Texture image coordinates */
+ int height;
+ drmRadeonTexImage *image;
} drmRadeonTexture;
#define RADEON_MAX_TEXTURE_UNITS 3
-
/* Layout matches drm_radeon_state_t in linux drm_radeon.h.
*/
typedef struct {
@@ -266,16 +238,13 @@ typedef struct {
unsigned int dirty;
} drmRadeonState;
-/**
- * \brief DRM 1.1 vertex ioctl.
- *
- * Used in compatibility modes.
+/* 1.1 vertex ioctl. Used in compatibility modes.
*/
typedef struct {
- int prim; /**< \brief Primitive number */
- int idx; /**< \brief Index of vertex buffer */
- int count; /**< \brief Number of vertices in buffer */
- int discard; /**< \brief Client finished with buffer? */
+ int prim;
+ int idx; /* Index of vertex buffer */
+ int count; /* Number of vertices in buffer */
+ int discard; /* Client finished with buffer? */
} drmRadeonVertex;
typedef struct {
@@ -283,13 +252,13 @@ typedef struct {
unsigned int finish;
unsigned int prim:8;
unsigned int stateidx:8;
- unsigned int numverts:16; /**< overloaded as offset/64 for elt prims */
+ unsigned int numverts:16; /* overloaded as offset/64 for elt prims */
unsigned int vc_format;
} drmRadeonPrim;
typedef struct {
- int idx; /**< \brief Index of vertex buffer */
- int discard; /**< \brief Client finished with buffer? */
+ int idx; /* Index of vertex buffer */
+ int discard; /* Client finished with buffer? */
int nr_states;
drmRadeonState *state;
int nr_prims;
@@ -299,156 +268,127 @@ typedef struct {
#define RADEON_MAX_STATES 16
#define RADEON_MAX_PRIMS 64
-
-/**
- * \brief Command buffer.
- *
- * \todo Replace with true DMA stream?
+/* Command buffer. Replace with true dma stream?
*/
typedef struct {
- int bufsz; /**< \brief buffer size */
- char *buf; /**< \brief buffer */
- int nbox; /**< \brief number of cliprects */
- drmClipRect *boxes; /**< \brief cliprects */
+ int bufsz;
+ char *buf;
+ int nbox;
+ drmClipRect *boxes;
} drmRadeonCmdBuffer;
-
-/**
- * \brief Per-packet identifiers for use with the ::RADEON_CMD_PACKET command
- * in the DRM_RADEON_CMDBUF ioctl.
- *
- * \note Comments relate new packets to old state bits and the packet size.
+/* New style per-packet identifiers for use in cmd_buffer ioctl with
+ * the RADEON_EMIT_PACKET command. Comments relate new packets to old
+ * state bits and the packet size:
*/
-enum drmRadeonCmdPkt {
- RADEON_EMIT_PP_MISC = 0, /* context/7 */
- RADEON_EMIT_PP_CNTL = 1, /* context/3 */
- RADEON_EMIT_RB3D_COLORPITCH = 2, /* context/1 */
- RADEON_EMIT_RE_LINE_PATTERN = 3, /* line/2 */
- RADEON_EMIT_SE_LINE_WIDTH = 4, /* line/1 */
- RADEON_EMIT_PP_LUM_MATRIX = 5, /* bumpmap/1 */
- RADEON_EMIT_PP_ROT_MATRIX_0 = 6, /* bumpmap/2 */
- RADEON_EMIT_RB3D_STENCILREFMASK = 7, /* masks/3 */
- RADEON_EMIT_SE_VPORT_XSCALE = 8, /* viewport/6 */
- RADEON_EMIT_SE_CNTL = 9, /* setup/2 */
- RADEON_EMIT_SE_CNTL_STATUS = 10, /* setup/1 */
- RADEON_EMIT_RE_MISC = 11, /* misc/1 */
- RADEON_EMIT_PP_TXFILTER_0 = 12, /* tex0/6 */
- RADEON_EMIT_PP_BORDER_COLOR_0 = 13, /* tex0/1 */
- RADEON_EMIT_PP_TXFILTER_1 = 14, /* tex1/6 */
- RADEON_EMIT_PP_BORDER_COLOR_1 = 15, /* tex1/1 */
- RADEON_EMIT_PP_TXFILTER_2 = 16, /* tex2/6 */
- RADEON_EMIT_PP_BORDER_COLOR_2 = 17, /* tex2/1 */
- RADEON_EMIT_SE_ZBIAS_FACTOR = 18, /* zbias/2 */
- RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT = 19, /* tcl/11 */
- RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED = 20, /* material/17 */
- R200_EMIT_PP_TXCBLEND_0 = 21, /* tex0/4 */
- R200_EMIT_PP_TXCBLEND_1 = 22, /* tex1/4 */
- R200_EMIT_PP_TXCBLEND_2 = 23, /* tex2/4 */
- R200_EMIT_PP_TXCBLEND_3 = 24, /* tex3/4 */
- R200_EMIT_PP_TXCBLEND_4 = 25, /* tex4/4 */
- R200_EMIT_PP_TXCBLEND_5 = 26, /* tex5/4 */
- R200_EMIT_PP_TXCBLEND_6 = 27, /* /4 */
- R200_EMIT_PP_TXCBLEND_7 = 28, /* /4 */
- R200_EMIT_TCL_LIGHT_MODEL_CTL_0 = 29, /* tcl/6 */
- R200_EMIT_TFACTOR_0 = 30, /* tf/6 */
- R200_EMIT_VTX_FMT_0 = 31, /* vtx/4 */
- R200_EMIT_VAP_CTL = 32, /* vap/1 */
- R200_EMIT_MATRIX_SELECT_0 = 33, /* msl/5 */
- R200_EMIT_TEX_PROC_CTL_2 = 34, /* tcg/5 */
- R200_EMIT_TCL_UCP_VERT_BLEND_CTL = 35, /* tcl/1 */
- R200_EMIT_PP_TXFILTER_0 = 36, /* tex0/6 */
- R200_EMIT_PP_TXFILTER_1 = 37, /* tex1/6 */
- R200_EMIT_PP_TXFILTER_2 = 38, /* tex2/6 */
- R200_EMIT_PP_TXFILTER_3 = 39, /* tex3/6 */
- R200_EMIT_PP_TXFILTER_4 = 40, /* tex4/6 */
- R200_EMIT_PP_TXFILTER_5 = 41, /* tex5/6 */
- R200_EMIT_PP_TXOFFSET_0 = 42, /* tex0/1 */
- R200_EMIT_PP_TXOFFSET_1 = 43, /* tex1/1 */
- R200_EMIT_PP_TXOFFSET_2 = 44, /* tex2/1 */
- R200_EMIT_PP_TXOFFSET_3 = 45, /* tex3/1 */
- R200_EMIT_PP_TXOFFSET_4 = 46, /* tex4/1 */
- R200_EMIT_PP_TXOFFSET_5 = 47, /* tex5/1 */
- R200_EMIT_VTE_CNTL = 48, /* vte/1 */
- R200_EMIT_OUTPUT_VTX_COMP_SEL = 49, /* vtx/1 */
- R200_EMIT_PP_TAM_DEBUG3 = 50, /* tam/1 */
- R200_EMIT_PP_CNTL_X = 51, /* cst/1 */
- R200_EMIT_RB3D_DEPTHXY_OFFSET = 52, /* cst/1 */
- R200_EMIT_RE_AUX_SCISSOR_CNTL = 53, /* cst/1 */
- R200_EMIT_RE_SCISSOR_TL_0 = 54, /* cst/2 */
- R200_EMIT_RE_SCISSOR_TL_1 = 55, /* cst/2 */
- R200_EMIT_RE_SCISSOR_TL_2 = 56, /* cst/2 */
- R200_EMIT_SE_VAP_CNTL_STATUS = 57, /* cst/1 */
- R200_EMIT_SE_VTX_STATE_CNTL = 58, /* cst/1 */
- R200_EMIT_RE_POINTSIZE = 59, /* cst/1 */
- R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0 = 60, /* cst/4 */
- R200_EMIT_PP_CUBIC_FACES_0 = 61,
- R200_EMIT_PP_CUBIC_OFFSETS_0 = 62,
- R200_EMIT_PP_CUBIC_FACES_1 = 63,
- R200_EMIT_PP_CUBIC_OFFSETS_1 = 64,
- R200_EMIT_PP_CUBIC_FACES_2 = 65,
- R200_EMIT_PP_CUBIC_OFFSETS_2 = 66,
- R200_EMIT_PP_CUBIC_FACES_3 = 67,
- R200_EMIT_PP_CUBIC_OFFSETS_3 = 68,
- R200_EMIT_PP_CUBIC_FACES_4 = 69,
- R200_EMIT_PP_CUBIC_OFFSETS_4 = 70,
- R200_EMIT_PP_CUBIC_FACES_5 = 71,
- R200_EMIT_PP_CUBIC_OFFSETS_5 = 72,
- RADEON_MAX_STATE_PACKETS = 73
-} ;
-
-
-/**
- * \brief Command types understood by the DRM_RADEON_CMDBUF ioctl.
- *
- * More can be added but obviously these can't be removed or changed.
- *
- * \sa drmRadeonCmdHeader.
- */
-enum drmRadeonCmdType {
- RADEON_CMD_PACKET = 1, /**< \brief emit one of the ::drmRadeonCmdPkt register packets */
- RADEON_CMD_SCALARS = 2, /**< \brief emit scalar data */
- RADEON_CMD_VECTORS = 3, /**< \brief emit vector data */
- RADEON_CMD_DMA_DISCARD = 4, /**< \brief discard current DMA buffer */
- RADEON_CMD_PACKET3 = 5, /**< \brief emit hardware packet */
- RADEON_CMD_PACKET3_CLIP = 6, /**< \brief emit hardware packet wrapped in cliprects */
- RADEON_CMD_SCALARS2 = 7, /**< \brief R200 stopgap */
- RADEON_CMD_WAIT = 8 /**< \brief synchronization */
-} ;
-
-/**
- * \brief Command packet headers understood by the DRM_RADEON_CMDBUF ioctl.
- *
- * \sa drmRadeonCmdType.
+#define RADEON_EMIT_PP_MISC 0 /* context/7 */
+#define RADEON_EMIT_PP_CNTL 1 /* context/3 */
+#define RADEON_EMIT_RB3D_COLORPITCH 2 /* context/1 */
+#define RADEON_EMIT_RE_LINE_PATTERN 3 /* line/2 */
+#define RADEON_EMIT_SE_LINE_WIDTH 4 /* line/1 */
+#define RADEON_EMIT_PP_LUM_MATRIX 5 /* bumpmap/1 */
+#define RADEON_EMIT_PP_ROT_MATRIX_0 6 /* bumpmap/2 */
+#define RADEON_EMIT_RB3D_STENCILREFMASK 7 /* masks/3 */
+#define RADEON_EMIT_SE_VPORT_XSCALE 8 /* viewport/6 */
+#define RADEON_EMIT_SE_CNTL 9 /* setup/2 */
+#define RADEON_EMIT_SE_CNTL_STATUS 10 /* setup/1 */
+#define RADEON_EMIT_RE_MISC 11 /* misc/1 */
+#define RADEON_EMIT_PP_TXFILTER_0 12 /* tex0/6 */
+#define RADEON_EMIT_PP_BORDER_COLOR_0 13 /* tex0/1 */
+#define RADEON_EMIT_PP_TXFILTER_1 14 /* tex1/6 */
+#define RADEON_EMIT_PP_BORDER_COLOR_1 15 /* tex1/1 */
+#define RADEON_EMIT_PP_TXFILTER_2 16 /* tex2/6 */
+#define RADEON_EMIT_PP_BORDER_COLOR_2 17 /* tex2/1 */
+#define RADEON_EMIT_SE_ZBIAS_FACTOR 18 /* zbias/2 */
+#define RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT 19 /* tcl/11 */
+#define RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED 20 /* material/17 */
+#define R200_EMIT_PP_TXCBLEND_0 21 /* tex0/4 */
+#define R200_EMIT_PP_TXCBLEND_1 22 /* tex1/4 */
+#define R200_EMIT_PP_TXCBLEND_2 23 /* tex2/4 */
+#define R200_EMIT_PP_TXCBLEND_3 24 /* tex3/4 */
+#define R200_EMIT_PP_TXCBLEND_4 25 /* tex4/4 */
+#define R200_EMIT_PP_TXCBLEND_5 26 /* tex5/4 */
+#define R200_EMIT_PP_TXCBLEND_6 27 /* /4 */
+#define R200_EMIT_PP_TXCBLEND_7 28 /* /4 */
+#define R200_EMIT_TCL_LIGHT_MODEL_CTL_0 29 /* tcl/6 */
+#define R200_EMIT_TFACTOR_0 30 /* tf/6 */
+#define R200_EMIT_VTX_FMT_0 31 /* vtx/4 */
+#define R200_EMIT_VAP_CTL 32 /* vap/1 */
+#define R200_EMIT_MATRIX_SELECT_0 33 /* msl/5 */
+#define R200_EMIT_TEX_PROC_CTL_2 34 /* tcg/5 */
+#define R200_EMIT_TCL_UCP_VERT_BLEND_CTL 35 /* tcl/1 */
+#define R200_EMIT_PP_TXFILTER_0 36 /* tex0/6 */
+#define R200_EMIT_PP_TXFILTER_1 37 /* tex1/6 */
+#define R200_EMIT_PP_TXFILTER_2 38 /* tex2/6 */
+#define R200_EMIT_PP_TXFILTER_3 39 /* tex3/6 */
+#define R200_EMIT_PP_TXFILTER_4 40 /* tex4/6 */
+#define R200_EMIT_PP_TXFILTER_5 41 /* tex5/6 */
+#define R200_EMIT_PP_TXOFFSET_0 42 /* tex0/1 */
+#define R200_EMIT_PP_TXOFFSET_1 43 /* tex1/1 */
+#define R200_EMIT_PP_TXOFFSET_2 44 /* tex2/1 */
+#define R200_EMIT_PP_TXOFFSET_3 45 /* tex3/1 */
+#define R200_EMIT_PP_TXOFFSET_4 46 /* tex4/1 */
+#define R200_EMIT_PP_TXOFFSET_5 47 /* tex5/1 */
+#define R200_EMIT_VTE_CNTL 48 /* vte/1 */
+#define R200_EMIT_OUTPUT_VTX_COMP_SEL 49 /* vtx/1 */
+#define R200_EMIT_PP_TAM_DEBUG3 50 /* tam/1 */
+#define R200_EMIT_PP_CNTL_X 51 /* cst/1 */
+#define R200_EMIT_RB3D_DEPTHXY_OFFSET 52 /* cst/1 */
+#define R200_EMIT_RE_AUX_SCISSOR_CNTL 53 /* cst/1 */
+#define R200_EMIT_RE_SCISSOR_TL_0 54 /* cst/2 */
+#define R200_EMIT_RE_SCISSOR_TL_1 55 /* cst/2 */
+#define R200_EMIT_RE_SCISSOR_TL_2 56 /* cst/2 */
+#define R200_EMIT_SE_VAP_CNTL_STATUS 57 /* cst/1 */
+#define R200_EMIT_SE_VTX_STATE_CNTL 58 /* cst/1 */
+#define R200_EMIT_RE_POINTSIZE 59 /* cst/1 */
+#define R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0 60 /* cst/4 */
+#define R200_EMIT_PP_CUBIC_FACES_0 61
+#define R200_EMIT_PP_CUBIC_OFFSETS_0 62
+#define R200_EMIT_PP_CUBIC_FACES_1 63
+#define R200_EMIT_PP_CUBIC_OFFSETS_1 64
+#define R200_EMIT_PP_CUBIC_FACES_2 65
+#define R200_EMIT_PP_CUBIC_OFFSETS_2 66
+#define R200_EMIT_PP_CUBIC_FACES_3 67
+#define R200_EMIT_PP_CUBIC_OFFSETS_3 68
+#define R200_EMIT_PP_CUBIC_FACES_4 69
+#define R200_EMIT_PP_CUBIC_OFFSETS_4 70
+#define R200_EMIT_PP_CUBIC_FACES_5 71
+#define R200_EMIT_PP_CUBIC_OFFSETS_5 72
+#define RADEON_EMIT_PP_TEX_SIZE_0 73
+#define RADEON_EMIT_PP_TEX_SIZE_1 74
+#define RADEON_EMIT_PP_TEX_SIZE_2 75
+#define RADEON_MAX_STATE_PACKETS 76
+
+
+/* Commands understood by cmd_buffer ioctl. More can be added but
+ * obviously these can't be removed or changed:
*/
+#define RADEON_CMD_PACKET 1 /* emit one of the register packets above */
+#define RADEON_CMD_SCALARS 2 /* emit scalar data */
+#define RADEON_CMD_VECTORS 3 /* emit vector data */
+#define RADEON_CMD_DMA_DISCARD 4 /* discard current dma buf */
+#define RADEON_CMD_PACKET3 5 /* emit hw packet */
+#define RADEON_CMD_PACKET3_CLIP 6 /* emit hw packet wrapped in cliprects */
+#define RADEON_CMD_SCALARS2 7 /* R200 stopgap */
+#define RADEON_CMD_WAIT 8 /* synchronization */
+
typedef union {
- /** \brief integer equivalent */
int i;
-
struct {
unsigned char cmd_type, pad0, pad1, pad2;
} header;
-
- /** \brief emit a register packet */
struct {
unsigned char cmd_type, packet_id, pad0, pad1;
} packet;
-
- /** \brief scalar data */
struct {
unsigned char cmd_type, offset, stride, count;
} scalars;
-
- /** \brief vector data */
struct {
unsigned char cmd_type, offset, stride, count;
} vectors;
-
- /** \brief discard current DMA buffer */
struct {
unsigned char cmd_type, buf_idx, pad0, pad1;
} dma;
-
- /** \brief synchronization */
struct {
unsigned char cmd_type, flags, pad0, pad1;
} wait;
@@ -458,12 +398,10 @@ typedef union {
#define RADEON_WAIT_2D 0x1
#define RADEON_WAIT_3D 0x2
-/**
- * \brief DRM_RADEON_GETPARAM ioctl argument type.
- */
+
typedef struct drm_radeon_getparam {
- int param; /**< \brief parameter number */
- int *value; /**< \brief parameter value */
+ int param;
+ void *value;
} drmRadeonGetParam;
#define RADEON_PARAM_AGP_BUFFER_OFFSET 1
@@ -472,10 +410,6 @@ typedef struct drm_radeon_getparam {
#define RADEON_PARAM_LAST_CLEAR 4
#define RADEON_PARAM_IRQ_NR 5
#define RADEON_PARAM_AGP_BASE 6
-#define RADEON_PARAM_REGISTER_HANDLE 7
-#define RADEON_PARAM_STATUS_HANDLE 8
-#define RADEON_PARAM_SAREA_HANDLE 9
-#define RADEON_PARAM_AGP_TEX_HANDLE 10
#define RADEON_MEM_REGION_AGP 1
@@ -493,29 +427,18 @@ typedef struct drm_radeon_mem_free {
int region_offset;
} drmRadeonMemFree;
-/**
- * \brief DRM_RADEON_INIT_HEAP argument type.
- */
typedef struct drm_radeon_mem_init_heap {
- int region; /**< \brief region type */
- int size; /**< \brief region size */
- int start; /**< \brief region start offset */
+ int region;
+ int size;
+ int start;
} drmRadeonMemInitHeap;
-/**
- * \brief DRM_RADEON_IRQ_EMIT ioctl argument type.
- *
- * New in DRM 1.6: userspace can request and wait on IRQ's.
+/* 1.6: Userspace can request & wait on irq's:
*/
typedef struct drm_radeon_irq_emit {
int *irq_seq;
} drmRadeonIrqEmit;
-/**
- * \brief DRM_RADEON_IRQ_WAIT ioctl argument type.
- *
- * New in DRM 1.6: userspace can request and wait on IRQ's.
- */
typedef struct drm_radeon_irq_wait {
int irq_seq;
} drmRadeonIrqWait;
diff --git a/src/mesa/drivers/dri/radeon/server/radeon_dri.c b/src/mesa/drivers/dri/radeon/server/radeon_dri.c
index f14bd13a95..4271aa7da2 100644
--- a/src/mesa/drivers/dri/radeon/server/radeon_dri.c
+++ b/src/mesa/drivers/dri/radeon/server/radeon_dri.c
@@ -12,6 +12,7 @@
#include <stdlib.h>
#include <string.h>
#include <errno.h>
+#include <unistd.h>
#include "driver.h"
#include "drm.h"
@@ -23,9 +24,6 @@
#include "radeon_sarea.h"
#include "sarea.h"
-#include <unistd.h>
-
-
/* HACK - for now, put this here... */
/* Alpha - this may need to be a variable to handle UP1x00 vs TITAN */
@@ -735,7 +733,7 @@ static int RADEONMemoryInit( const DRIDriverContext *ctx, RADEONInfoPtr info )
* Setups a RADEONDRIRec structure to be passed to radeon_dri.so for its
* initialization.
*/
-static int RADEONScreenInit( DRIDriverContext *ctx, RADEONInfoPtr info )
+static int RADEONScreenInit( const DRIDriverContext *ctx, RADEONInfoPtr info )
{
RADEONDRIPtr pRADEONDRI;
int err;
diff --git a/src/mesa/drivers/dri/radeon/server/radeon_reg.h b/src/mesa/drivers/dri/radeon/server/radeon_reg.h
index 2cd9dbe094..5570a43945 100644
--- a/src/mesa/drivers/dri/radeon/server/radeon_reg.h
+++ b/src/mesa/drivers/dri/radeon/server/radeon_reg.h
@@ -1,24 +1,4 @@
-/**
- * \file server/radeon_reg.h
- * \brief Registers and register definitions for the Radeon.
- *
- * \authors Kevin E. Martin <martin@xfree86.org>
- * \authors Rickard E. Faith <faith@valinux.com>
- * \authors Alan Hourihane <alanh@fairlite.demon.co.uk>
- *
- * \par References
- *
- * - RAGE 128 VR/ RAGE 128 GL Register Reference Manual (Technical
- * Reference Manual P/N RRG-G04100-C Rev. 0.04), ATI Technologies: April
- * 1999.
- * - RAGE 128 Software Development Manual (Technical Reference Manual P/N
- * SDK-G04000 Rev. 0.01), ATI Technologies: June 1999.
- *
- * \note !!!! FIXME !!!! THIS FILE HAS BEEN CONVERTED FROM r128_reg.h
- * AND CONTAINS REGISTERS AND REGISTER DEFINITIONS THAT ARE NOT CORRECT
- * ON THE RADEON. A FULL AUDIT OF THIS CODE IS NEEDED!
- */
-
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h,v 1.25 2003/02/07 18:08:59 martin Exp $ */
/*
* Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
* VA Linux Systems Inc., Fremont, California.
@@ -47,7 +27,28 @@
* DEALINGS IN THE SOFTWARE.
*/
-/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h,v 1.20 2002/10/12 01:38:07 martin Exp $ */
+/*
+ * Authors:
+ * Kevin E. Martin <martin@xfree86.org>
+ * Rickard E. Faith <faith@valinux.com>
+ * Alan Hourihane <alanh@fairlite.demon.co.uk>
+ *
+ * References:
+ *
+ * !!!! FIXME !!!!
+ * RAGE 128 VR/ RAGE 128 GL Register Reference Manual (Technical
+ * Reference Manual P/N RRG-G04100-C Rev. 0.04), ATI Technologies: April
+ * 1999.
+ *
+ * !!!! FIXME !!!!
+ * RAGE 128 Software Development Manual (Technical Reference Manual P/N
+ * SDK-G04000 Rev. 0.01), ATI Technologies: June 1999.
+ *
+ */
+
+/* !!!! FIXME !!!! NOTE: THIS FILE HAS BEEN CONVERTED FROM r128_reg.h
+ * AND CONTAINS REGISTERS AND REGISTER DEFINITIONS THAT ARE NOT CORRECT
+ * ON THE RADEON. A FULL AUDIT OF THIS CODE IS NEEDED! */
#ifndef _RADEON_REG_H_
#define _RADEON_REG_H_
@@ -216,6 +217,10 @@
#define RADEON_CONFIG_APER_SIZE 0x0108
#define RADEON_CONFIG_BONDS 0x00e8
#define RADEON_CONFIG_CNTL 0x00e0
+# define RADEON_CFG_ATI_REV_A11 (0 << 16)
+# define RADEON_CFG_ATI_REV_A12 (1 << 16)
+# define RADEON_CFG_ATI_REV_A13 (2 << 16)
+# define RADEON_CFG_ATI_REV_ID_MASK (0xf << 16)
#define RADEON_CONFIG_MEMSIZE 0x00f8
#define RADEON_CONFIG_MEMSIZE_EMBEDDED 0x0114
#define RADEON_CONFIG_REG_1_BASE 0x010c
@@ -302,6 +307,10 @@
#define RADEON_CRTC2_PITCH 0x032c
#define RADEON_CRTC_STATUS 0x005c
# define RADEON_CRTC_VBLANK_SAVE (1 << 1)
+# define RADEON_CRTC_VBLANK_SAVE_CLEAR (1 << 1)
+#define RADEON_CRTC2_STATUS 0x03fc
+# define RADEON_CRTC2_VBLANK_SAVE (1 << 1)
+# define RADEON_CRTC2_VBLANK_SAVE_CLEAR (1 << 1)
#define RADEON_CRTC_V_SYNC_STRT_WID 0x020c
# define RADEON_CRTC_V_SYNC_STRT (0x7ff << 0)
# define RADEON_CRTC_V_SYNC_STRT_SHIFT 0
@@ -492,6 +501,7 @@
#define RADEON_DST_LINE_START 0x1600
#define RADEON_DST_LINE_END 0x1604
#define RADEON_DST_LINE_PATCOUNT 0x1608
+# define RADEON_BRES_CNTL_SHIFT 8
#define RADEON_DST_OFFSET 0x1404
#define RADEON_DST_PITCH 0x1408
#define RADEON_DST_PITCH_OFFSET 0x142c
@@ -554,6 +564,7 @@
#define RADEON_FP_GEN_CNTL 0x0284
# define RADEON_FP_FPON (1 << 0)
# define RADEON_FP_TMDS_EN (1 << 2)
+# define RADEON_FP_PANEL_FORMAT (1 << 3)
# define RADEON_FP_EN_TMDS (1 << 7)
# define RADEON_FP_DETECT_SENSE (1 << 8)
# define RADEON_FP_SEL_CRTC2 (1 << 13)
@@ -612,6 +623,8 @@
#define RADEON_GEN_INT_STATUS 0x0044
# define RADEON_VSYNC_INT_AK (1 << 2)
# define RADEON_VSYNC_INT (1 << 2)
+# define RADEON_VSYNC2_INT_AK (1 << 6)
+# define RADEON_VSYNC2_INT (1 << 6)
#define RADEON_GENENB 0x03c3 /* VGA */
#define RADEON_GENFC_RD 0x03ca /* VGA */
#define RADEON_GENFC_WT 0x03da /* VGA, 0x03ba */
@@ -708,6 +721,9 @@
#define RADEON_MM_DATA 0x0004
#define RADEON_MM_INDEX 0x0000
#define RADEON_MPLL_CNTL 0x000e /* PLL */
+#define RADEON_MPP_TB_CONFIG 0x01c0 /* ? */
+#define RADEON_MPP_GP_CONFIG 0x01c8 /* ? */
+
#define RADEON_N_VIF_COUNT 0x0248
@@ -863,6 +879,8 @@
# define RADEON_P2PLL_REF_DIV_MASK 0x03ff
# define RADEON_P2PLL_ATOMIC_UPDATE_R (1 << 15) /* same as _W */
# define RADEON_P2PLL_ATOMIC_UPDATE_W (1 << 15) /* same as _R */
+# define R300_PPLL_REF_DIV_ACC_MASK (0x3ff < 18)
+# define R300_PPLL_REF_DIV_ACC_SHIFT 18
#define RADEON_PALETTE_DATA 0x00b4
#define RADEON_PALETTE_30_DATA 0x00b8
#define RADEON_PALETTE_INDEX 0x00b0
@@ -1122,6 +1140,10 @@
# define RADEON_LOD_BIAS_SHIFT 8
# define RADEON_MAX_MIP_LEVEL_MASK (0x0f << 16)
# define RADEON_MAX_MIP_LEVEL_SHIFT 16
+# define RADEON_YUV_TO_RGB (1 << 20)
+# define RADEON_YUV_TEMPERATURE_COOL (0 << 21)
+# define RADEON_YUV_TEMPERATURE_HOT (1 << 21)
+# define RADEON_YUV_TEMPERATURE_MASK (1 << 21)
# define RADEON_WRAPEN_S (1 << 22)
# define RADEON_CLAMP_S_WRAP (0 << 23)
# define RADEON_CLAMP_S_MIRROR (1 << 23)
@@ -1129,6 +1151,8 @@
# define RADEON_CLAMP_S_MIRROR_CLAMP_LAST (3 << 23)
# define RADEON_CLAMP_S_CLAMP_BORDER (4 << 23)
# define RADEON_CLAMP_S_MIRROR_CLAMP_BORDER (5 << 23)
+# define RADEON_CLAMP_S_CLAMP_GL (6 << 23)
+# define RADEON_CLAMP_S_MIRROR_CLAMP_GL (7 << 23)
# define RADEON_CLAMP_S_MASK (7 << 23)
# define RADEON_WRAPEN_T (1 << 26)
# define RADEON_CLAMP_T_WRAP (0 << 27)
@@ -1137,6 +1161,8 @@
# define RADEON_CLAMP_T_MIRROR_CLAMP_LAST (3 << 27)
# define RADEON_CLAMP_T_CLAMP_BORDER (4 << 27)
# define RADEON_CLAMP_T_MIRROR_CLAMP_BORDER (5 << 27)
+# define RADEON_CLAMP_T_CLAMP_GL (6 << 27)
+# define RADEON_CLAMP_T_MIRROR_CLAMP_GL (7 << 27)
# define RADEON_CLAMP_T_MASK (7 << 27)
# define RADEON_BORDER_MODE_OGL (0 << 31)
# define RADEON_BORDER_MODE_D3D (1 << 31)
@@ -1152,6 +1178,11 @@
# define RADEON_TXFORMAT_ARGB8888 (6 << 0)
# define RADEON_TXFORMAT_RGBA8888 (7 << 0)
# define RADEON_TXFORMAT_Y8 (8 << 0)
+# define RADEON_TXFORMAT_VYUY422 (10 << 0)
+# define RADEON_TXFORMAT_YVYU422 (11 << 0)
+# define RADEON_TXFORMAT_DXT1 (12 << 0)
+# define RADEON_TXFORMAT_DXT23 (14 << 0)
+# define RADEON_TXFORMAT_DXT45 (15 << 0)
# define RADEON_TXFORMAT_FORMAT_MASK (31 << 0)
# define RADEON_TXFORMAT_FORMAT_SHIFT 0
# define RADEON_TXFORMAT_APPLE_YUV_MODE (1 << 5)
@@ -1161,6 +1192,10 @@
# define RADEON_TXFORMAT_WIDTH_SHIFT 8
# define RADEON_TXFORMAT_HEIGHT_MASK (15 << 12)
# define RADEON_TXFORMAT_HEIGHT_SHIFT 12
+# define RADEON_TXFORMAT_F5_WIDTH_MASK (15 << 16)
+# define RADEON_TXFORMAT_F5_WIDTH_SHIFT 16
+# define RADEON_TXFORMAT_F5_HEIGHT_MASK (15 << 20)
+# define RADEON_TXFORMAT_F5_HEIGHT_SHIFT 20
# define RADEON_TXFORMAT_ST_ROUTE_STQ0 (0 << 24)
# define RADEON_TXFORMAT_ST_ROUTE_MASK (3 << 24)
# define RADEON_TXFORMAT_ST_ROUTE_STQ1 (1 << 24)
@@ -1173,6 +1208,26 @@
# define RADEON_TXFORMAT_CHROMA_KEY_ENABLE (1 << 29)
# define RADEON_TXFORMAT_CUBIC_MAP_ENABLE (1 << 30)
# define RADEON_TXFORMAT_PERSPECTIVE_ENABLE (1 << 31)
+#define RADEON_PP_CUBIC_FACES_0 0x1d24
+#define RADEON_PP_CUBIC_FACES_1 0x1d28
+#define RADEON_PP_CUBIC_FACES_2 0x1d2c
+# define RADEON_FACE_WIDTH_1_SHIFT 0
+# define RADEON_FACE_HEIGHT_1_SHIFT 4
+# define RADEON_FACE_WIDTH_1_MASK (0xf << 0)
+# define RADEON_FACE_HEIGHT_1_MASK (0xf << 4)
+# define RADEON_FACE_WIDTH_2_SHIFT 8
+# define RADEON_FACE_HEIGHT_2_SHIFT 12
+# define RADEON_FACE_WIDTH_2_MASK (0xf << 8)
+# define RADEON_FACE_HEIGHT_2_MASK (0xf << 12)
+# define RADEON_FACE_WIDTH_3_SHIFT 16
+# define RADEON_FACE_HEIGHT_3_SHIFT 20
+# define RADEON_FACE_WIDTH_3_MASK (0xf << 16)
+# define RADEON_FACE_HEIGHT_3_MASK (0xf << 20)
+# define RADEON_FACE_WIDTH_4_SHIFT 24
+# define RADEON_FACE_HEIGHT_4_SHIFT 28
+# define RADEON_FACE_WIDTH_4_MASK (0xf << 24)
+# define RADEON_FACE_HEIGHT_4_MASK (0xf << 28)
+
#define RADEON_PP_TXOFFSET_0 0x1c5c
#define RADEON_PP_TXOFFSET_1 0x1c74
#define RADEON_PP_TXOFFSET_2 0x1c8c
@@ -1187,6 +1242,39 @@
# define RADEON_TXO_MICRO_TILE_OPT (2 << 3)
# define RADEON_TXO_OFFSET_MASK 0xffffffe0
# define RADEON_TXO_OFFSET_SHIFT 5
+
+#define RADEON_PP_CUBIC_OFFSET_T0_0 0x1dd0 /* bits [31:5] */
+#define RADEON_PP_CUBIC_OFFSET_T0_1 0x1dd4
+#define RADEON_PP_CUBIC_OFFSET_T0_2 0x1dd8
+#define RADEON_PP_CUBIC_OFFSET_T0_3 0x1ddc
+#define RADEON_PP_CUBIC_OFFSET_T0_4 0x1de0
+#define RADEON_PP_CUBIC_OFFSET_T1_0 0x1e00
+#define RADEON_PP_CUBIC_OFFSET_T1_1 0x1e04
+#define RADEON_PP_CUBIC_OFFSET_T1_2 0x1e08
+#define RADEON_PP_CUBIC_OFFSET_T1_3 0x1e0c
+#define RADEON_PP_CUBIC_OFFSET_T1_4 0x1e10
+#define RADEON_PP_CUBIC_OFFSET_T2_0 0x1e14
+#define RADEON_PP_CUBIC_OFFSET_T2_1 0x1e18
+#define RADEON_PP_CUBIC_OFFSET_T2_2 0x1e1c
+#define RADEON_PP_CUBIC_OFFSET_T2_3 0x1e20
+#define RADEON_PP_CUBIC_OFFSET_T2_4 0x1e24
+
+#define RADEON_PP_TEX_SIZE_0 0x1d04 /* NPOT */
+#define RADEON_PP_TEX_SIZE_1 0x1d0c
+#define RADEON_PP_TEX_SIZE_2 0x1d14
+# define RADEON_TEX_USIZE_MASK (0x7ff << 0)
+# define RADEON_TEX_USIZE_SHIFT 0
+# define RADEON_TEX_VSIZE_MASK (0x7ff << 16)
+# define RADEON_TEX_VSIZE_SHIFT 16
+# define RADEON_SIGNED_RGB_MASK (1 << 30)
+# define RADEON_SIGNED_RGB_SHIFT 30
+# define RADEON_SIGNED_ALPHA_MASK (1 << 31)
+# define RADEON_SIGNED_ALPHA_SHIFT 31
+#define RADEON_PP_TEX_PITCH_0 0x1d08 /* NPOT */
+#define RADEON_PP_TEX_PITCH_1 0x1d10 /* NPOT */
+#define RADEON_PP_TEX_PITCH_2 0x1d18 /* NPOT */
+/* note: bits 13-5: 32 byte aligned stride of texture map */
+
#define RADEON_PP_TXCBLEND_0 0x1c60
#define RADEON_PP_TXCBLEND_1 0x1c78
#define RADEON_PP_TXCBLEND_2 0x1c90
diff --git a/src/mesa/drivers/dri/radeon/server/radeon_sarea.h b/src/mesa/drivers/dri/radeon/server/radeon_sarea.h
index f682bb6b6a..81e4325d7a 100644
--- a/src/mesa/drivers/dri/radeon/server/radeon_sarea.h
+++ b/src/mesa/drivers/dri/radeon/server/radeon_sarea.h
@@ -296,9 +296,9 @@ typedef struct {
/** \brief Texture regions.
* Last element is sentinal
*/
- radeon_tex_region_t texList[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS+1];
+ drmTextureRegion texList[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS+1];
/** \brief last time texture was uploaded */
- int texAge[RADEON_NR_TEX_HEAPS];
+ unsigned int texAge[RADEON_NR_TEX_HEAPS];
/*@}*/
int ctxOwner; /**< \brief last context to upload state */