diff options
author | Luc Verhaegen <libv@skynet.be> | 2010-03-11 01:55:49 +0100 |
---|---|---|
committer | Luc Verhaegen <libv@skynet.be> | 2010-03-11 01:55:49 +0100 |
commit | 5347249ae0486e833f851e841c007bc4137395c2 (patch) | |
tree | 52474f816415a52b29e3659ed2eb01c819d1fe35 | |
parent | 5dee9b7b19c1aa3a13618b08bc24f00677b5364b (diff) |
-rw-r--r-- | configure.ac | 5 | ||||
-rw-r--r-- | src/Doxyfile | 234 | ||||
-rw-r--r-- | src/Makefile.am | 24 | ||||
-rw-r--r-- | src/README | 26 | ||||
-rw-r--r-- | src/mga_texcombine.c | 672 | ||||
-rw-r--r-- | src/mga_texstate.c | 902 | ||||
-rw-r--r-- | src/mga_xmesa.c | 1046 | ||||
-rw-r--r-- | src/mga_xmesa.h | 155 | ||||
-rw-r--r-- | src/mgacontext.h | 365 | ||||
-rw-r--r-- | src/mgadd.c | 80 | ||||
-rw-r--r-- | src/mgadd.h | 36 | ||||
-rw-r--r-- | src/mgaioctl.c | 751 | ||||
-rw-r--r-- | src/mgaioctl.h | 111 | ||||
-rw-r--r-- | src/mgapixel.c | 656 | ||||
-rw-r--r-- | src/mgapixel.h | 36 | ||||
-rw-r--r-- | src/mgaregs.h | 1395 | ||||
-rw-r--r-- | src/mgarender.c | 172 | ||||
-rw-r--r-- | src/mgaspan.c | 223 | ||||
-rw-r--r-- | src/mgaspan.h | 40 | ||||
-rw-r--r-- | src/mgastate.c | 1205 | ||||
-rw-r--r-- | src/mgastate.h | 39 | ||||
-rw-r--r-- | src/mgatex.c | 541 | ||||
-rw-r--r-- | src/mgatex.h | 51 | ||||
-rw-r--r-- | src/mgatexmem.c | 278 | ||||
-rw-r--r-- | src/mgatris.c | 912 | ||||
-rw-r--r-- | src/mgatris.h | 52 | ||||
-rw-r--r-- | src/mgavb.c | 480 | ||||
-rw-r--r-- | src/mgavb.h | 66 | ||||
-rw-r--r-- | src/server/mga.h | 115 | ||||
-rw-r--r-- | src/server/mga_bios.h | 143 | ||||
-rw-r--r-- | src/server/mga_dri.c | 1089 | ||||
-rw-r--r-- | src/server/mga_dri.h | 113 | ||||
-rw-r--r-- | src/server/mga_macros.h | 118 | ||||
-rw-r--r-- | src/server/mga_reg.h | 484 |
34 files changed, 12608 insertions, 7 deletions
diff --git a/configure.ac b/configure.ac index 2a78cfd..a4bb79b 100644 --- a/configure.ac +++ b/configure.ac @@ -1,7 +1,7 @@ # Process this file with autoconf to produce a configure script AC_PREREQ(2.57) -AC_INIT([mesa-dri-xxx], 7.0.3, [], mesa-dri-xxx) +AC_INIT([mesa-dri-mga], 7.0.3, [], mesa-dri-mga) AM_INIT_AUTOMAKE([dist-bzip2]) @@ -16,7 +16,8 @@ AC_PROG_CC AC_HEADER_STDC PKG_CHECK_MODULES([DRM], [libdrm >= 2.3.0]) -PKG_CHECK_MODULES([DRI], [libmesadri = 7.0.3 libmesadricommon = 7.0.3]) +PKG_CHECK_MODULES([DRI], [libmesadri >= 7.0.3 libmesadri < 7.1.0 + libmesadricommon >= 7.0.3 libmesadricommon < 7.1.0]) AC_OUTPUT([ Makefile diff --git a/src/Doxyfile b/src/Doxyfile new file mode 100644 index 0000000..0d0c134 --- /dev/null +++ b/src/Doxyfile @@ -0,0 +1,234 @@ +# Doxyfile 1.3.3-Gideon + +#--------------------------------------------------------------------------- +# General configuration options +#--------------------------------------------------------------------------- +PROJECT_NAME = mga +PROJECT_NUMBER = $VERSION$ +OUTPUT_DIRECTORY = +OUTPUT_LANGUAGE = English +USE_WINDOWS_ENCODING = NO +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = YES +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = NO +STRIP_FROM_PATH = +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = YES +SHORT_NAMES = NO +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +JAVADOC_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +DETAILS_AT_TOP = NO +INHERIT_DOCS = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +DISTRIBUTE_GROUP_DOC = NO +TAB_SIZE = 8 +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ALIASES = +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_JAVA = NO +SHOW_USED_FILES = YES +SUBGROUPING = YES +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = /home/newtree/temp/src/mesa/drivers/dri/mga +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.idl \ + *.odl \ + *.cs \ + *.C \ + *.H \ + *.tlh \ + *.diff \ + *.patch \ + *.moc \ + *.xpm \ + *.dox +RECURSIVE = yes +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = * +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = YES +VERBATIM_HEADERS = YES +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = NO +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_ALIGN_MEMBERS = YES +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +BINARY_TOC = NO +TOC_EXPAND = NO +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = NO +TREEVIEW_WIDTH = 250 +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = YES +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = NO +USE_PDFLATEX = NO +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = yes +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::addtions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = YES +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = NO +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +UML_LOOK = NO +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +MAX_DOT_GRAPH_WIDTH = 1024 +MAX_DOT_GRAPH_HEIGHT = 1024 +MAX_DOT_GRAPH_DEPTH = 1000 +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +#--------------------------------------------------------------------------- +# Configuration::addtions related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = NO +CGI_NAME = search.cgi +CGI_URL = +DOC_URL = +DOC_ABSPATH = +BIN_ABSPATH = /usr/local/bin/ +EXT_DOC_PATHS = diff --git a/src/Makefile.am b/src/Makefile.am index aa854c5..db3e79d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,7 +1,21 @@ AM_CFLAGS = -DIN_DRI_DRIVER -DGLX_DIRECT_RENDERING -DGLX_INDIRECT_RENDERING -xxx_dri_la_LTLIBRARIES = xxx_dri.la -xxx_dri_la_CFLAGS = $(AM_CFLAGS) $(DRM_CFLAGS) $(DRI_CFLAGS) -Iserver -xxx_dri_la_LDFLAGS = -module -noprefix -lm -ldl $(DRM_LIBS) $(DRI_LIBS) -xxx_dri_ladir = @libdir@/dri -xxx_dri_la_SOURCES = \ +mga_dri_la_LTLIBRARIES = mga_dri.la +mga_dri_la_CFLAGS = $(AM_CFLAGS) $(DRM_CFLAGS) $(DRI_CFLAGS) -Iserver +mga_dri_la_LDFLAGS = -module -noprefix -avoid-version -lm -ldl \ + $(DRM_LIBS) $(DRI_LIBS) +mga_dri_ladir = @libdir@/dri +mga_dri_la_SOURCES = \ + mgadd.c \ + mgaioctl.c \ + mgarender.c \ + mgastate.c \ + mgatris.c \ + mgapixel.c \ + mgaspan.c \ + mgatex.c \ + mgatexmem.c \ + mga_texstate.c \ + mga_texcombine.c \ + mgavb.c \ + mga_xmesa.c diff --git a/src/README b/src/README new file mode 100644 index 0000000..a7133fa --- /dev/null +++ b/src/README @@ -0,0 +1,26 @@ +MGA DRI driver ported from XF86DRI to FBDRI +by Denis Oliver Kropp <dok@directfb.org> + + +INFO + +This driver has been ported from the head branch of XFree86 to +the embedded-1-branch of Mesa. + + +STATUS + +Already working very well as far as I've tested it (16/32 bit). +glxgears runs at 935 fps (G550 32MB AGP 4x, Athlon 1.33) vs 744 fps with XFree. +Other demos (terrain, fire, etc.) have been successfully tested as well. + + +TODO + +- mgaEngineShutdown +- mgaEngineRestore +- SGRAM detection +- remove some unused bits from server/* +- subset driver support +- mgaWaitForVBlank +- deinitialization (from MGADRICloseScreen) a la radeonDestroyScreen diff --git a/src/mga_texcombine.c b/src/mga_texcombine.c new file mode 100644 index 0000000..bbfa29b --- /dev/null +++ b/src/mga_texcombine.c @@ -0,0 +1,672 @@ +/* + * Copyright (c) 2003 Ville Syrjala + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Ville Syrjala <syrjala@sci.fi> + */ + +#include "glheader.h" + +#include "mgacontext.h" +#include "mgatex.h" +#include "mgaregs.h" + +/* + * GL_ARB_texture_env_combine + * GL_EXT_texture_env_combine + * GL_ARB_texture_env_crossbar + * GL_ATI_texture_env_combine3 + */ + +#define ARG_DISABLE 0xffffffff +#define MGA_ARG1 0 +#define MGA_ARG2 1 +#define MGA_ALPHA 2 + +GLboolean mgaUpdateTextureEnvCombine( GLcontext *ctx, int unit ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + const int source = mmesa->tmu_source[unit]; + const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source]; + GLuint *reg = ((GLuint *)&mmesa->setup.tdualstage0 + unit); + GLuint numColorArgs = 0, numAlphaArgs = 0; + GLuint arg1[3], arg2[3], alpha[3]; + int args[3]; + int i; + + switch (texUnit->Combine.ModeRGB) { + case GL_REPLACE: + numColorArgs = 1; + break; + case GL_MODULATE: + case GL_ADD: + case GL_ADD_SIGNED: + case GL_SUBTRACT: + numColorArgs = 2; + break; + case GL_INTERPOLATE: + case GL_MODULATE_ADD_ATI: + case GL_MODULATE_SIGNED_ADD_ATI: + case GL_MODULATE_SUBTRACT_ATI: + numColorArgs = 3; + break; + default: + return GL_FALSE; + } + + switch (texUnit->Combine.ModeA) { + case GL_REPLACE: + numAlphaArgs = 1; + break; + case GL_MODULATE: + case GL_ADD: + case GL_ADD_SIGNED: + case GL_SUBTRACT: + numAlphaArgs = 2; + break; + default: + return GL_FALSE; + } + + /* Start fresh :) */ + *reg = 0; + + /* COLOR */ + for (i = 0; i < 3; i++) { + arg1[i] = 0; + arg2[i] = 0; + alpha[i] = 0; + } + + for (i = 0;i < numColorArgs; i++) { + switch (texUnit->Combine.SourceRGB[i]) { + case GL_TEXTURE: + arg1[i] |= 0; + arg2[i] |= ARG_DISABLE; + alpha[i] |= TD0_color_alpha_currtex; + break; + case GL_TEXTURE0: + if (source == 0) { + arg1[i] |= 0; + arg2[i] |= ARG_DISABLE; + alpha[i] |= TD0_color_alpha_currtex; + } else { + if (ctx->Texture._EnabledUnits != 0x03) { + /* disable texturing */ + mmesa->setup.dwgctl &= DC_opcod_MASK; + mmesa->setup.dwgctl |= DC_opcod_trap; + mmesa->hw.alpha_sel = AC_alphasel_diffused; + /* return GL_TRUE since we don't need a fallback */ + return GL_TRUE; + } + arg1[i] |= ARG_DISABLE; + arg2[i] |= ARG_DISABLE; + alpha[i] |= TD0_color_alpha_prevtex; + } + break; + case GL_TEXTURE1: + if (source == 0) { + if (ctx->Texture._EnabledUnits != 0x03) { + /* disable texturing */ + mmesa->setup.dwgctl &= DC_opcod_MASK; + mmesa->setup.dwgctl |= DC_opcod_trap; + mmesa->hw.alpha_sel = AC_alphasel_diffused; + /* return GL_TRUE since we don't need a fallback */ + return GL_TRUE; + } + arg1[i] |= ARG_DISABLE; + /* G400 specs (TDUALSTAGE0) */ + arg2[i] |= TD0_color_arg2_prevstage; + alpha[i] |= TD0_color_alpha_prevstage; + } else { + arg1[i] |= 0; + arg2[i] |= ARG_DISABLE; + alpha[i] |= TD0_color_alpha_currtex; + } + break; + case GL_CONSTANT: + if (mmesa->fcol_used && + mmesa->envcolor[source] != mmesa->envcolor[!source]) + return GL_FALSE; + + arg1[i] |= ARG_DISABLE; + arg2[i] |= TD0_color_arg2_fcol; + alpha[i] |= TD0_color_alpha_fcol; + + mmesa->setup.fcol = mmesa->envcolor[source]; + mmesa->fcol_used = GL_TRUE; + break; + case GL_PRIMARY_COLOR: + arg1[i] |= ARG_DISABLE; + /* G400 specs (TDUALSTAGE1) */ + if (unit == 0 || (mmesa->setup.tdualstage0 & + ((TD0_color_sel_mul & TD0_color_sel_add) | + (TD0_alpha_sel_mul & TD0_alpha_sel_add)))) { + arg2[i] |= TD0_color_arg2_diffuse; + alpha[i] |= TD0_color_alpha_diffuse; + } else { + arg2[i] |= ARG_DISABLE; + alpha[i] |= ARG_DISABLE; + } + break; + case GL_PREVIOUS: + arg1[i] |= ARG_DISABLE; + if (unit == 0) { + arg2[i] |= TD0_color_arg2_diffuse; + alpha[i] |= TD0_color_alpha_diffuse; + } else { + arg2[i] |= TD0_color_arg2_prevstage; + alpha[i] |= TD0_color_alpha_prevstage; + } + break; + default: + return GL_FALSE; + } + + switch (texUnit->Combine.OperandRGB[i]) { + case GL_SRC_COLOR: + arg1[i] |= 0; + arg2[i] |= 0; + if (texUnit->Combine.SourceRGB[i] == GL_CONSTANT && + RGBA_EQUAL( mmesa->envcolor[source] )) { + alpha[i] |= 0; + } else { + alpha[i] |= ARG_DISABLE; + } + break; + case GL_ONE_MINUS_SRC_COLOR: + arg1[i] |= TD0_color_arg1_inv_enable; + arg2[i] |= TD0_color_arg2_inv_enable; + if (texUnit->Combine.SourceRGB[i] == GL_CONSTANT && + RGBA_EQUAL( mmesa->envcolor[source] )) { + alpha[i] |= (TD0_color_alpha1inv_enable | + TD0_color_alpha2inv_enable); + } else { + alpha[i] |= ARG_DISABLE; + } + break; + case GL_SRC_ALPHA: + arg1[i] |= TD0_color_arg1_replicatealpha_enable; + arg2[i] |= TD0_color_arg2_replicatealpha_enable; + alpha[i] |= 0; + break; + case GL_ONE_MINUS_SRC_ALPHA: + arg1[i] |= (TD0_color_arg1_replicatealpha_enable | + TD0_color_arg1_inv_enable); + arg2[i] |= (TD0_color_arg2_replicatealpha_enable | + TD0_color_arg2_inv_enable); + alpha[i] |= (TD0_color_alpha1inv_enable | + TD0_color_alpha2inv_enable); + break; + } + } + + switch (texUnit->Combine.ModeRGB) { + case GL_MODULATE_ADD_ATI: + case GL_MODULATE_SIGNED_ADD_ATI: + /* Special handling for ATI_texture_env_combine3. + * If Arg1 == Arg0 or Arg1 == Arg2 we can use arg1 or arg2 as input for + * both multiplier and adder. + */ + /* Arg1 == arg1 */ + if (arg1[1] == arg1[0]) { + if ((arg1[1] | arg2[2]) != ARG_DISABLE) { + *reg |= arg1[1] | arg2[2]; + args[0] = MGA_ARG1; args[1] = MGA_ARG1; args[2] = MGA_ARG2; + break; + } else + if ((arg1[1] | alpha[2]) != ARG_DISABLE) { + *reg |= arg1[1] | alpha[2]; + args[0] = MGA_ARG1; args[1] = MGA_ARG1; args[2] = MGA_ALPHA; + break; + } + } + if (arg1[1] == arg1[2]) { + if ((arg1[1] | arg2[0]) != ARG_DISABLE) { + *reg |= arg1[1] | arg2[0]; + args[0] = MGA_ARG2; args[1] = MGA_ARG1; args[2] = MGA_ARG1; + break; + } else + if ((arg1[1] | alpha[0]) != ARG_DISABLE) { + *reg |= arg1[1] | alpha[0]; + args[0] = MGA_ALPHA; args[1] = MGA_ARG1; args[2] = MGA_ARG1; + break; + } + } + /* fallthrough */ + case GL_MODULATE_SUBTRACT_ATI: + /* Arg1 == arg2 */ + if (arg2[1] == arg2[0]) { + if ((arg2[1] | arg1[2]) != ARG_DISABLE) { + *reg |= arg2[1] | arg1[2]; + args[0] = MGA_ARG2; args[1] = MGA_ARG2; args[2] = MGA_ARG1; + break; + } else + if ((arg2[1] | alpha[2]) != ARG_DISABLE) { + *reg |= arg2[1] | alpha[2]; + args[0] = MGA_ARG2; args[1] = MGA_ARG2; args[2] = MGA_ALPHA; + break; + } + } + if (arg2[1] == arg2[2]) { + if ((arg2[1] | arg1[0]) != ARG_DISABLE) { + *reg |= arg2[1] | arg1[0]; + args[0] = MGA_ARG1; args[1] = MGA_ARG2; args[2] = MGA_ARG2; + break; + } else + if ((arg2[1] | alpha[0]) != ARG_DISABLE) { + *reg |= arg2[1] | alpha[0]; + args[0] = MGA_ALPHA; args[1] = MGA_ARG2; args[2] = MGA_ARG2; + break; + } + } + /* fallthrough */ + default: + /* Find working combo of arg1, arg2 and alpha. + * + * Keep the Arg0 != alpha cases first since there's + * no way to get alpha out by itself (GL_REPLACE). + * + * Keep the Arg2 == alpha cases first because only alpha has the + * capabilities to function as Arg2 (GL_INTERPOLATE). Also good for + * GL_ADD, GL_ADD_SIGNED, GL_SUBTRACT since we can't get alpha to the + * adder. + * + * Keep the Arg1 == alpha cases last for GL_MODULATE_ADD_ATI, + * GL_MODULATE_SIGNED_ADD_ATI. Again because we can't get alpha to the + * adder. + * + * GL_MODULATE_SUBTRACT_ATI needs special treatment since it requires + * that Arg1 == arg2. This requirement clashes with those of other modes. + */ + if ((arg1[0] | arg2[1] | alpha[2]) != ARG_DISABLE) { + *reg |= arg1[0] | arg2[1] | alpha[2]; + args[0] = MGA_ARG1; args[1] = MGA_ARG2; args[2] = MGA_ALPHA; + } else + if ((arg1[1] | arg2[0] | alpha[2]) != ARG_DISABLE && + texUnit->Combine.ModeRGB != GL_MODULATE_SUBTRACT_ATI) { + *reg |= arg1[1] | arg2[0] | alpha[2]; + args[0] = MGA_ARG2; args[1] = MGA_ARG1; args[2] = MGA_ALPHA; + } else + if ((arg1[1] | arg2[2] | alpha[0]) != ARG_DISABLE && + texUnit->Combine.ModeRGB != GL_MODULATE_SUBTRACT_ATI) { + *reg |= arg1[1] | arg2[2] | alpha[0]; + args[0] = MGA_ALPHA; args[1] = MGA_ARG1; args[2] = MGA_ARG2; + } else + if ((arg1[2] | arg2[1] | alpha[0]) != ARG_DISABLE) { + *reg |= arg1[2] | arg2[1] | alpha[0]; + args[0] = MGA_ALPHA; args[1] = MGA_ARG2; args[2] = MGA_ARG1; + } else + if ((arg1[0] | arg2[2] | alpha[1]) != ARG_DISABLE) { + *reg |= arg1[0] | arg2[2] | alpha[1]; + args[0] = MGA_ARG1; args[1] = MGA_ALPHA; args[2] = MGA_ARG2; + } else + if ((arg1[2] | arg2[0] | alpha[1]) != ARG_DISABLE) { + *reg |= arg1[2] | arg2[0] | alpha[1]; + args[0] = MGA_ARG2; args[1] = MGA_ALPHA; args[2] = MGA_ARG1; + } else { + /* nothing suitable */ + return GL_FALSE; + } + } + + switch (texUnit->Combine.ModeRGB) { + case GL_REPLACE: + if (texUnit->Combine.ScaleShiftRGB) { + return GL_FALSE; + } + + if (args[0] == MGA_ARG1) { + *reg |= TD0_color_sel_arg1; + } else if (args[0] == MGA_ARG2) { + *reg |= TD0_color_sel_arg2; + } else if (args[0] == MGA_ALPHA) { + /* Can't get alpha out by itself */ + return GL_FALSE; + } + break; + case GL_MODULATE: + if (texUnit->Combine.ScaleShiftRGB == 1) { + *reg |= TD0_color_modbright_2x; + } else if (texUnit->Combine.ScaleShiftRGB == 2) { + *reg |= TD0_color_modbright_4x; + } + + *reg |= TD0_color_sel_mul; + + if (args[0] == MGA_ALPHA || args[1] == MGA_ALPHA) { + if (args[0] == MGA_ARG1 || args[1] == MGA_ARG1) { + *reg |= TD0_color_arg2mul_alpha2; + } else if (args[0] == MGA_ARG2 || args[1] == MGA_ARG2) { + *reg |= TD0_color_arg1mul_alpha1; + } + } + break; + case GL_ADD_SIGNED: + *reg |= TD0_color_addbias_enable; + /* fallthrough */ + case GL_ADD: + if (args[0] == MGA_ALPHA || args[1] == MGA_ALPHA) { + /* Can't get alpha to the adder */ + return GL_FALSE; + } + if (texUnit->Combine.ScaleShiftRGB == 1) { + *reg |= TD0_color_add2x_enable; + } else if (texUnit->Combine.ScaleShiftRGB == 2) { + return GL_FALSE; + } + + *reg |= (TD0_color_add_add | + TD0_color_sel_add); + break; + case GL_INTERPOLATE: + if (args[2] != MGA_ALPHA) { + /* Only alpha can function as Arg2 */ + return GL_FALSE; + } + if (texUnit->Combine.ScaleShiftRGB == 1) { + *reg |= TD0_color_add2x_enable; + } else if (texUnit->Combine.ScaleShiftRGB == 2) { + return GL_FALSE; + } + + *reg |= (TD0_color_arg1mul_alpha1 | + TD0_color_blend_enable | + TD0_color_arg1add_mulout | + TD0_color_arg2add_mulout | + TD0_color_add_add | + TD0_color_sel_add); + + /* Have to do this with xor since GL_ONE_MINUS_SRC_ALPHA may have + * already touched this bit. + */ + *reg ^= TD0_color_alpha1inv_enable; + + if (args[0] == MGA_ARG2) { + /* Swap arguments */ + *reg ^= (TD0_color_arg1mul_alpha1 | + TD0_color_arg2mul_alpha2 | + TD0_color_alpha1inv_enable | + TD0_color_alpha2inv_enable); + } + + if (ctx->Texture._EnabledUnits != 0x03) { + /* Linear blending mode needs dualtex enabled */ + *(reg+1) = (TD0_color_arg2_prevstage | + TD0_color_sel_arg2 | + TD0_alpha_arg2_prevstage | + TD0_alpha_sel_arg2); + mmesa->force_dualtex = GL_TRUE; + } + break; + case GL_SUBTRACT: + if (args[0] == MGA_ALPHA || args[1] == MGA_ALPHA) { + /* Can't get alpha to the adder */ + return GL_FALSE; + } + if (texUnit->Combine.ScaleShiftRGB == 1) { + *reg |= TD0_color_add2x_enable; + } else if (texUnit->Combine.ScaleShiftRGB == 2) { + return GL_FALSE; + } + + *reg |= (TD0_color_add_sub | + TD0_color_sel_add); + + if (args[0] == MGA_ARG2) { + /* Swap arguments */ + *reg ^= (TD0_color_arg1_inv_enable | + TD0_color_arg2_inv_enable); + } + break; + case GL_MODULATE_SIGNED_ADD_ATI: + *reg |= TD0_color_addbias_enable; + /* fallthrough */ + case GL_MODULATE_ADD_ATI: + if (args[1] == MGA_ALPHA) { + /* Can't get alpha to the adder */ + return GL_FALSE; + } + if (texUnit->Combine.ScaleShiftRGB == 1) { + *reg |= TD0_color_add2x_enable; + } else if (texUnit->Combine.ScaleShiftRGB == 2) { + return GL_FALSE; + } + + *reg |= (TD0_color_add_add | + TD0_color_sel_add); + + if (args[1] == args[0] || args[1] == args[2]) { + *reg |= TD0_color_arg1add_mulout; + if (args[0] == MGA_ALPHA || args[2] == MGA_ALPHA) + *reg |= TD0_color_arg1mul_alpha1; + + if (args[1] == MGA_ARG1) { + /* Swap adder arguments */ + *reg ^= (TD0_color_arg1add_mulout | + TD0_color_arg2add_mulout); + if (args[0] == MGA_ALPHA || args[2] == MGA_ALPHA) { + /* Swap multiplier arguments */ + *reg ^= (TD0_color_arg1mul_alpha1 | + TD0_color_arg2mul_alpha2); + } + } + } else { + *reg |= (TD0_color_arg2mul_alpha2 | + TD0_color_arg1add_mulout); + + if (args[1] == MGA_ARG1) { + /* Swap arguments */ + *reg ^= (TD0_color_arg1mul_alpha1 | + TD0_color_arg2mul_alpha2 | + TD0_color_arg1add_mulout | + TD0_color_arg2add_mulout); + } + } + break; + case GL_MODULATE_SUBTRACT_ATI: + if (args[1] != MGA_ARG2) { + /* Can't swap arguments */ + return GL_FALSE; + } + if (texUnit->Combine.ScaleShiftRGB == 1) { + *reg |= TD0_color_add2x_enable; + } else if (texUnit->Combine.ScaleShiftRGB == 2) { + return GL_FALSE; + } + + *reg |= (TD0_color_add_sub | + TD0_color_sel_add); + + if (args[1] == args[0] || args[1] == args[2]) { + *reg |= TD0_color_arg1add_mulout; + if (args[0] == MGA_ALPHA || args[2] == MGA_ALPHA) + *reg |= TD0_color_arg1mul_alpha1; + } else { + *reg |= (TD0_color_arg2mul_alpha2 | + TD0_color_arg1add_mulout); + } + break; + } + + + /* ALPHA */ + for (i = 0; i < 2; i++) { + arg1[i] = 0; + arg2[i] = 0; + } + + for (i = 0; i < numAlphaArgs; i++) { + switch (texUnit->Combine.SourceA[i]) { + case GL_TEXTURE: + arg1[i] |= 0; + arg2[i] |= ARG_DISABLE; + break; + case GL_TEXTURE0: + if (source == 0) { + arg1[i] |= 0; + arg2[i] |= ARG_DISABLE; + } else { + if (ctx->Texture._EnabledUnits != 0x03) { + /* disable texturing */ + mmesa->setup.dwgctl &= DC_opcod_MASK; + mmesa->setup.dwgctl |= DC_opcod_trap; + mmesa->hw.alpha_sel = AC_alphasel_diffused; + /* return GL_TRUE since we don't need a fallback */ + return GL_TRUE; + } + arg1[i] |= ARG_DISABLE; + arg2[i] |= TD0_alpha_arg2_prevtex; + } + break; + case GL_TEXTURE1: + if (source == 0) { + if (ctx->Texture._EnabledUnits != 0x03) { + /* disable texturing */ + mmesa->setup.dwgctl &= DC_opcod_MASK; + mmesa->setup.dwgctl |= DC_opcod_trap; + mmesa->hw.alpha_sel = AC_alphasel_diffused; + /* return GL_TRUE since we don't need a fallback */ + return GL_TRUE; + } + arg1[i] |= ARG_DISABLE; + /* G400 specs (TDUALSTAGE0) */ + arg2[i] |= TD0_alpha_arg2_prevstage; + } else { + arg1[i] |= 0; + arg2[i] |= ARG_DISABLE; + } + break; + case GL_CONSTANT: + if (mmesa->fcol_used && + mmesa->envcolor[source] != mmesa->envcolor[!source]) + return GL_FALSE; + + arg1[i] |= ARG_DISABLE; + arg2[i] |= TD0_alpha_arg2_fcol; + + mmesa->setup.fcol = mmesa->envcolor[source]; + mmesa->fcol_used = GL_TRUE; + break; + case GL_PRIMARY_COLOR: + arg1[i] |= ARG_DISABLE; + /* G400 specs (TDUALSTAGE1) */ + if (unit == 0 || (mmesa->setup.tdualstage0 & + ((TD0_color_sel_mul & TD0_color_sel_add) | + (TD0_alpha_sel_mul & TD0_alpha_sel_add)))) { + arg2[i] |= TD0_alpha_arg2_diffuse; + } else { + arg2[i] |= ARG_DISABLE; + } + break; + case GL_PREVIOUS: + arg1[i] |= ARG_DISABLE; + if (unit == 0) { + arg2[i] |= TD0_alpha_arg2_diffuse; + } else { + arg2[i] |= TD0_alpha_arg2_prevstage; + } + break; + default: + return GL_FALSE; + } + + switch (texUnit->Combine.OperandA[i]) { + case GL_SRC_ALPHA: + arg1[i] |= 0; + arg2[i] |= 0; + break; + case GL_ONE_MINUS_SRC_ALPHA: + arg1[i] |= TD0_alpha_arg1_inv_enable; + arg2[i] |= TD0_alpha_arg2_inv_enable; + break; + } + } + + /* Find a working combo of arg1 and arg2 */ + if ((arg1[0] | arg2[1]) != ARG_DISABLE) { + *reg |= arg1[0] | arg2[1]; + args[0] = MGA_ARG1; args[1] = MGA_ARG2; + } else + if ((arg1[1] | arg2[0]) != ARG_DISABLE) { + *reg |= arg1[1] | arg2[0]; + args[0] = MGA_ARG2; args[1] = MGA_ARG1; + } else { + /* nothing suitable */ + return GL_FALSE; + } + + switch (texUnit->Combine.ModeA) { + case GL_REPLACE: + if (texUnit->Combine.ScaleShiftA) { + return GL_FALSE; + } + + if (args[0] == MGA_ARG1) { + *reg |= TD0_alpha_sel_arg1; + } else if (args[0] == MGA_ARG2) { + *reg |= TD0_alpha_sel_arg2; + } + break; + case GL_MODULATE: + if (texUnit->Combine.ScaleShiftA == 1) { + *reg |= TD0_alpha_modbright_2x; + } else if (texUnit->Combine.ScaleShiftA == 2) { + *reg |= TD0_alpha_modbright_4x; + } + + *reg |= TD0_alpha_sel_mul; + break; + case GL_ADD_SIGNED: + *reg |= TD0_alpha_addbias_enable; + /* fallthrough */ + case GL_ADD: + if (texUnit->Combine.ScaleShiftA == 1) { + *reg |= TD0_alpha_add2x_enable; + } else if (texUnit->Combine.ScaleShiftA == 2) { + return GL_FALSE; + } + + *reg |= (TD0_alpha_add_enable | + TD0_alpha_sel_add); + break; + case GL_SUBTRACT: + if (texUnit->Combine.ScaleShiftA == 1) { + *reg |= TD0_alpha_add2x_enable; + } else if (texUnit->Combine.ScaleShiftA == 2) { + return GL_FALSE; + } + + *reg |= (TD0_alpha_add_disable | + TD0_alpha_sel_add); + + if (args[0] == MGA_ARG2) { + /* Swap arguments */ + *reg ^= (TD0_alpha_arg1_inv_enable | + TD0_alpha_arg2_inv_enable); + } + break; + } + + return GL_TRUE; +} + + diff --git a/src/mga_texstate.c b/src/mga_texstate.c new file mode 100644 index 0000000..71d264b --- /dev/null +++ b/src/mga_texstate.c @@ -0,0 +1,902 @@ +/* + * Copyright 2000-2001 VA Linux Systems, Inc. + * (c) Copyright IBM Corporation 2002 + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Ian Romanick <idr@us.ibm.com> + * Keith Whitwell <keithw@tungstengraphics.com> + */ +/* $XFree86:$ */ + +#include <stdlib.h> +#include "mm.h" +#include "mgacontext.h" +#include "mgatex.h" +#include "mgaregs.h" +#include "mgatris.h" +#include "mgaioctl.h" + +#include "context.h" +#include "enums.h" +#include "macros.h" +#include "imports.h" + +#include "simple_list.h" +#include "texformat.h" + +#define MGA_USE_TABLE_FOR_FORMAT +#ifdef MGA_USE_TABLE_FOR_FORMAT +#define TMC_nr_tformat (MESA_FORMAT_YCBCR_REV + 1) +static const unsigned TMC_tformat[ TMC_nr_tformat ] = +{ + [MESA_FORMAT_ARGB8888] = TMC_tformat_tw32, + [MESA_FORMAT_RGB565] = TMC_tformat_tw16, + [MESA_FORMAT_ARGB4444] = TMC_tformat_tw12, + [MESA_FORMAT_ARGB1555] = TMC_tformat_tw15, + [MESA_FORMAT_AL88] = TMC_tformat_tw8al, + [MESA_FORMAT_I8] = TMC_tformat_tw8a, + [MESA_FORMAT_CI8] = TMC_tformat_tw8 , + [MESA_FORMAT_YCBCR] = TMC_tformat_tw422uyvy, + [MESA_FORMAT_YCBCR_REV] = TMC_tformat_tw422, +}; +#endif + +static void +mgaSetTexImages( mgaContextPtr mmesa, + const struct gl_texture_object * tObj ) +{ + mgaTextureObjectPtr t = (mgaTextureObjectPtr) tObj->DriverData; + struct gl_texture_image *baseImage = tObj->Image[0][ tObj->BaseLevel ]; + GLint totalSize; + GLint width, height; + GLint i; + GLint numLevels; + GLint log2Width, log2Height; + GLuint txformat = 0; + GLint ofs; + + /* Set the hardware texture format + */ +#ifndef MGA_USE_TABLE_FOR_FORMAT + switch (baseImage->TexFormat->MesaFormat) { + + case MESA_FORMAT_ARGB8888: txformat = TMC_tformat_tw32; break; + case MESA_FORMAT_RGB565: txformat = TMC_tformat_tw16; break; + case MESA_FORMAT_ARGB4444: txformat = TMC_tformat_tw12; break; + case MESA_FORMAT_ARGB1555: txformat = TMC_tformat_tw15; break; + case MESA_FORMAT_AL88: txformat = TMC_tformat_tw8al; break; + case MESA_FORMAT_I8: txformat = TMC_tformat_tw8a; break; + case MESA_FORMAT_CI8: txformat = TMC_tformat_tw8; break; + case MESA_FORMAT_YCBCR: txformat = TMC_tformat_tw422uyvy; break; + case MESA_FORMAT_YCBCR_REV: txformat = TMC_tformat_tw422; break; + + default: + _mesa_problem(NULL, "unexpected texture format in %s", __FUNCTION__); + return; + } +#else + if ( (baseImage->TexFormat->MesaFormat >= TMC_nr_tformat) + || (TMC_tformat[ baseImage->TexFormat->MesaFormat ] == 0) ) + { + _mesa_problem(NULL, "unexpected texture format in %s", __FUNCTION__); + return; + } + + txformat = TMC_tformat[ baseImage->TexFormat->MesaFormat ]; + +#endif /* MGA_USE_TABLE_FOR_FORMAT */ + + driCalculateTextureFirstLastLevel( (driTextureObject *) t ); + if (tObj->Target == GL_TEXTURE_RECTANGLE_NV) { + log2Width = 0; + log2Height = 0; + } else { + log2Width = tObj->Image[0][t->base.firstLevel]->WidthLog2; + log2Height = tObj->Image[0][t->base.firstLevel]->HeightLog2; + } + + width = tObj->Image[0][t->base.firstLevel]->Width; + height = tObj->Image[0][t->base.firstLevel]->Height; + + numLevels = MIN2( t->base.lastLevel - t->base.firstLevel + 1, + MGA_IS_G200(mmesa) ? G200_TEX_MAXLEVELS : G400_TEX_MAXLEVELS); + + + totalSize = 0; + for ( i = 0 ; i < numLevels ; i++ ) { + const struct gl_texture_image * const texImage = + tObj->Image[0][ i + t->base.firstLevel ]; + int size; + + if (texImage == NULL) + break; + + size = texImage->Width * texImage->Height * + baseImage->TexFormat->TexelBytes; + + t->offsets[i] = totalSize; + t->base.dirty_images[0] |= (1<<i); + + /* All mipmaps must be 32-byte aligned */ + totalSize += (size + 31) & ~31; + + /* Since G400 calculates the offsets in hardware + * it can't handle more than one < 32 byte mipmap. + * + * Further testing has indicated that it can't + * handle any < 32 byte mipmaps. + */ + if (MGA_IS_G400( mmesa ) && size <= 32) { + i++; + break; + } + } + + /* save these values */ + numLevels = i; + t->base.lastLevel = t->base.firstLevel + numLevels - 1; + t->base.totalSize = totalSize; + + /* setup hardware register values */ + t->setup.texctl &= (TMC_tformat_MASK & TMC_tpitch_MASK + & TMC_tpitchext_MASK); + t->setup.texctl |= txformat; + + + /* Set the texture width. In order to support non-power of 2 textures and + * textures larger than 1024 texels wide, "linear" pitch must be used. For + * the linear pitch, if the width is 2048, a value of zero is used. + */ + + t->setup.texctl |= TMC_tpitchlin_enable; + t->setup.texctl |= MGA_FIELD( TMC_tpitchext, width & (2048 - 1) ); + + + /* G400 specifies the number of mip levels in a strange way. Since there + * are up to 11 levels, it requires 4 bits. Three of the bits are at the + * high end of TEXFILTER. The other bit is in the middle. Weird. + */ + numLevels--; + t->setup.texfilter &= TF_mapnb_MASK & TF_mapnbhigh_MASK & TF_reserved_MASK; + t->setup.texfilter |= MGA_FIELD( TF_mapnb, numLevels & 0x7 ); + t->setup.texfilter |= MGA_FIELD( TF_mapnbhigh, (numLevels >> 3) & 0x1 ); + + /* warp texture registers */ + ofs = MGA_IS_G200(mmesa) ? 28 : 11; + + t->setup.texwidth = (MGA_FIELD(TW_twmask, width - 1) | + MGA_FIELD(TW_rfw, (10 - log2Width - 8) & 63 ) | + MGA_FIELD(TW_tw, (log2Width + ofs ) | 0x40 )); + + t->setup.texheight = (MGA_FIELD(TH_thmask, height - 1) | + MGA_FIELD(TH_rfh, (10 - log2Height - 8) & 63 ) | + MGA_FIELD(TH_th, (log2Height + ofs ) | 0x40 )); + + mgaUploadTexImages( mmesa, t ); +} + + +/* ================================================================ + * Texture unit state management + */ + +static void mgaUpdateTextureEnvG200( GLcontext *ctx, GLuint unit ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + struct gl_texture_object *tObj = ctx->Texture.Unit[0]._Current; + mgaTextureObjectPtr t = (mgaTextureObjectPtr) tObj->DriverData; + GLenum format = tObj->Image[0][tObj->BaseLevel]->_BaseFormat; + + if (tObj != ctx->Texture.Unit[0].Current2D && + tObj != ctx->Texture.Unit[0].CurrentRect) + return; + + + t->setup.texctl &= ~TMC_tmodulate_enable; + t->setup.texctl2 &= ~(TMC_decalblend_enable | + TMC_idecal_enable | + TMC_decaldis_enable); + + switch (ctx->Texture.Unit[0].EnvMode) { + case GL_REPLACE: + if (format == GL_ALPHA) + t->setup.texctl2 |= TMC_idecal_enable; + + if (format == GL_RGB || format == GL_LUMINANCE) + mmesa->hw.alpha_sel = AC_alphasel_diffused; + else + mmesa->hw.alpha_sel = AC_alphasel_fromtex; + break; + + case GL_MODULATE: + t->setup.texctl |= TMC_tmodulate_enable; + + if (format == GL_ALPHA) + t->setup.texctl2 |= (TMC_idecal_enable | + TMC_decaldis_enable); + + if (format == GL_RGB || format == GL_LUMINANCE) + mmesa->hw.alpha_sel = AC_alphasel_diffused; + else + mmesa->hw.alpha_sel = AC_alphasel_modulated; + break; + + case GL_DECAL: + if (format == GL_RGB || format == GL_RGBA) + t->setup.texctl2 |= TMC_decalblend_enable; + else + t->setup.texctl2 |= TMC_idecal_enable; + + mmesa->hw.alpha_sel = AC_alphasel_diffused; + break; + + case GL_BLEND: + if (format == GL_ALPHA) { + t->setup.texctl2 |= TMC_idecal_enable; + mmesa->hw.alpha_sel = AC_alphasel_modulated; + } else { + t->texenv_fallback = GL_TRUE; + } + break; + + default: + break; + } +} + + +#define MGA_REPLACE 0 +#define MGA_MODULATE 1 +#define MGA_DECAL 2 +#define MGA_ADD 3 +#define MGA_MAX_COMBFUNC 4 + +static const GLuint g400_color_combine[][MGA_MAX_COMBFUNC] = +{ + /* Unit 0: + */ + { + /* GL_REPLACE + * Cv = Cs + * Av = Af + */ + (TD0_color_sel_arg1 | + TD0_alpha_arg2_diffuse | + TD0_alpha_sel_arg2), + + /* GL_MODULATE + * Cv = Cf Cs + * Av = Af + */ + (TD0_color_arg2_diffuse | + TD0_color_sel_mul | + TD0_alpha_arg2_diffuse | + TD0_alpha_sel_arg2), + + /* GL_DECAL + * Cv = Cs + * Av = Af + */ + (TD0_color_sel_arg1 | + TD0_alpha_arg2_diffuse | + TD0_alpha_sel_arg2), + + /* GL_ADD + * Cv = Cf + Cs + * Av = Af + */ + (TD0_color_arg2_diffuse | + TD0_color_add_add | + TD0_color_sel_add | + TD0_alpha_arg2_diffuse | + TD0_alpha_sel_arg2), + }, + + /* Unit 1: + */ + { + /* GL_REPLACE + * Cv = Cs + * Av = Ap + */ + (TD0_color_sel_arg1 | + TD0_alpha_arg2_prevstage | + TD0_alpha_sel_arg2), + + /* GL_MODULATE + * Cv = Cp Cs + * Av = Ap + */ + (TD0_color_arg2_prevstage | + TD0_color_sel_mul | + TD0_alpha_arg2_prevstage | + TD0_alpha_sel_arg2), + + /* GL_DECAL + * Cv = Cs + * Av = Ap + */ + (TD0_color_sel_arg1 | + TD0_alpha_arg2_prevstage | + TD0_alpha_sel_arg2), + + /* GL_ADD + * Cv = Cp + Cs + * Av = Ap + */ + (TD0_color_arg2_prevstage | + TD0_color_add_add | + TD0_color_sel_add | + TD0_alpha_arg2_prevstage | + TD0_alpha_sel_arg2), + }, +}; + +static const GLuint g400_color_alpha_combine[][MGA_MAX_COMBFUNC] = +{ + /* Unit 0: + */ + { + /* GL_REPLACE + * Cv = Cs + * Av = As + */ + (TD0_color_sel_arg1 | + TD0_alpha_sel_arg1), + + /* GL_MODULATE + * Cv = Cf Cs + * Av = Af As + */ + (TD0_color_arg2_diffuse | + TD0_color_sel_mul | + TD0_alpha_arg2_diffuse | + TD0_alpha_sel_mul), + + /* GL_DECAL + * tmp = Cf ( 1 - As ) + * Cv = tmp + Cs As + * Av = Af + */ + (TD0_color_arg2_diffuse | + TD0_color_alpha_currtex | + TD0_color_alpha1inv_enable | + TD0_color_arg1mul_alpha1 | + TD0_color_blend_enable | + TD0_color_arg1add_mulout | + TD0_color_arg2add_mulout | + TD0_color_add_add | + TD0_color_sel_add | + TD0_alpha_arg2_diffuse | + TD0_alpha_sel_arg2), + + /* GL_ADD + * Cv = Cf + Cs + * Av = Af As + */ + (TD0_color_arg2_diffuse | + TD0_color_add_add | + TD0_color_sel_add | + TD0_alpha_arg2_diffuse | + TD0_alpha_sel_mul), + }, + + /* Unit 1: + */ + { + /* GL_REPLACE + * Cv = Cs + * Av = As + */ + (TD0_color_sel_arg1 | + TD0_alpha_sel_arg1), + + /* GL_MODULATE + * Cv = Cp Cs + * Av = Ap As + */ + (TD0_color_arg2_prevstage | + TD0_color_sel_mul | + TD0_alpha_arg2_prevstage | + TD0_alpha_sel_mul), + + /* GL_DECAL + * tmp = Cp ( 1 - As ) + * Cv = tmp + Cs As + * Av = Ap + */ + (TD0_color_arg2_prevstage | + TD0_color_alpha_currtex | + TD0_color_alpha1inv_enable | + TD0_color_arg1mul_alpha1 | + TD0_color_blend_enable | + TD0_color_arg1add_mulout | + TD0_color_arg2add_mulout | + TD0_color_add_add | + TD0_color_sel_add | + TD0_alpha_arg2_prevstage | + TD0_alpha_sel_arg2), + + /* GL_ADD + * Cv = Cp + Cs + * Av = Ap As + */ + (TD0_color_arg2_prevstage | + TD0_color_add_add | + TD0_color_sel_add | + TD0_alpha_arg2_prevstage | + TD0_alpha_sel_mul), + }, +}; + +static const GLuint g400_alpha_combine[][MGA_MAX_COMBFUNC] = +{ + /* Unit 0: + */ + { + /* GL_REPLACE + * Cv = Cf + * Av = As + */ + (TD0_color_arg2_diffuse | + TD0_color_sel_arg2 | + TD0_alpha_sel_arg1), + + /* GL_MODULATE + * Cv = Cf + * Av = Af As + */ + (TD0_color_arg2_diffuse | + TD0_color_sel_arg2 | + TD0_alpha_arg2_diffuse | + TD0_alpha_sel_mul), + + /* GL_DECAL (undefined) + * Cv = Cf + * Av = Af + */ + (TD0_color_arg2_diffuse | + TD0_color_sel_arg2 | + TD0_alpha_arg2_diffuse | + TD0_alpha_sel_arg2), + + /* GL_ADD + * Cv = Cf + * Av = Af As + */ + (TD0_color_arg2_diffuse | + TD0_color_sel_arg2 | + TD0_alpha_arg2_diffuse | + TD0_alpha_sel_mul), + }, + + /* Unit 1: + */ + { + /* GL_REPLACE + * Cv = Cp + * Av = As + */ + (TD0_color_arg2_prevstage | + TD0_color_sel_arg2 | + TD0_alpha_sel_arg1), + + /* GL_MODULATE + * Cv = Cp + * Av = Ap As + */ + (TD0_color_arg2_prevstage | + TD0_color_sel_arg2 | + TD0_alpha_arg2_prevstage | + TD0_alpha_sel_mul), + + /* GL_DECAL (undefined) + * Cv = Cp + * Av = Ap + */ + (TD0_color_arg2_prevstage | + TD0_color_sel_arg2 | + TD0_alpha_arg2_prevstage | + TD0_alpha_sel_arg2), + + /* GL_ADD + * Cv = Cp + * Av = Ap As + */ + (TD0_color_arg2_prevstage | + TD0_color_sel_arg2 | + TD0_alpha_arg2_prevstage | + TD0_alpha_sel_mul), + }, +}; + +static GLboolean mgaUpdateTextureEnvBlend( GLcontext *ctx, int unit ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + const int source = mmesa->tmu_source[unit]; + const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source]; + const struct gl_texture_object *tObj = texUnit->_Current; + GLuint *reg = ((GLuint *)&mmesa->setup.tdualstage0 + unit); + GLenum format = tObj->Image[0][tObj->BaseLevel]->_BaseFormat; + + *reg = 0; + + if (format == GL_ALPHA) { + /* Cv = Cf */ + *reg |= (TD0_color_arg2_diffuse | + TD0_color_sel_arg2); + /* Av = Af As */ + *reg |= (TD0_alpha_arg2_diffuse | + TD0_alpha_sel_mul); + return GL_TRUE; + } + + /* C1 = Cf ( 1 - Cs ) */ + *reg |= (TD0_color_arg1_inv_enable | + TD0_color_arg2_diffuse | + TD0_color_sel_mul); + + if (format == GL_RGB || format == GL_LUMINANCE) { + /* A1 = Af */ + *reg |= (TD0_alpha_arg2_diffuse | + TD0_alpha_sel_arg2); + } else + if (format == GL_RGBA || format == GL_LUMINANCE_ALPHA) { + /* A1 = Af As */ + *reg |= (TD0_alpha_arg2_diffuse | + TD0_alpha_sel_mul); + } else + if (format == GL_INTENSITY) { + /* A1 = Af ( 1 - As ) */ + *reg |= (TD0_alpha_arg1_inv_enable | + TD0_alpha_arg2_diffuse | + TD0_alpha_sel_mul); + } + + if (RGB_ZERO(mmesa->envcolor[source]) && + (format != GL_INTENSITY || ALPHA_ZERO(mmesa->envcolor[source]))) + return GL_TRUE; /* all done */ + + if (ctx->Texture._EnabledUnits == 0x03) + return GL_FALSE; /* need both units */ + + mmesa->force_dualtex = GL_TRUE; + reg = &mmesa->setup.tdualstage1; + *reg = 0; + + if (RGB_ZERO(mmesa->envcolor[source])) { + /* Cv = C1 */ + *reg |= (TD0_color_arg2_prevstage | + TD0_color_sel_arg2); + } else + if (RGB_ONE(mmesa->envcolor[source])) { + /* Cv = C1 + Cs */ + *reg |= (TD0_color_arg2_prevstage | + TD0_color_add_add | + TD0_color_sel_add); + } else + if (RGBA_EQUAL(mmesa->envcolor[source])) { + /* Cv = C1 + Cc Cs */ + *reg |= (TD0_color_arg2_prevstage | + TD0_color_alpha_fcol | + TD0_color_arg2mul_alpha2 | + TD0_color_arg1add_mulout | + TD0_color_add_add | + TD0_color_sel_add); + + mmesa->setup.fcol = mmesa->envcolor[source]; + } else { + return GL_FALSE; + } + + if (format != GL_INTENSITY || ALPHA_ZERO(mmesa->envcolor[source])) { + /* Av = A1 */ + *reg |= (TD0_alpha_arg2_prevstage | + TD0_alpha_sel_arg2); + } else + if (ALPHA_ONE(mmesa->envcolor[source])) { + /* Av = A1 + As */ + *reg |= (TD0_alpha_arg2_prevstage | + TD0_alpha_add_enable | + TD0_alpha_sel_add); + } else { + return GL_FALSE; + } + + return GL_TRUE; +} + +static void mgaUpdateTextureEnvG400( GLcontext *ctx, GLuint unit ) +{ + mgaContextPtr mmesa = MGA_CONTEXT( ctx ); + const int source = mmesa->tmu_source[unit]; + const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source]; + const struct gl_texture_object *tObj = texUnit->_Current; + GLuint *reg = ((GLuint *)&mmesa->setup.tdualstage0 + unit); + mgaTextureObjectPtr t = (mgaTextureObjectPtr) tObj->DriverData; + GLenum format = tObj->Image[0][tObj->BaseLevel]->_BaseFormat; + + if (tObj != ctx->Texture.Unit[source].Current2D && + tObj != ctx->Texture.Unit[source].CurrentRect) + return; + + switch (ctx->Texture.Unit[source].EnvMode) { + case GL_REPLACE: + if (format == GL_ALPHA) { + *reg = g400_alpha_combine[unit][MGA_REPLACE]; + } else if (format == GL_RGB || format == GL_LUMINANCE) { + *reg = g400_color_combine[unit][MGA_REPLACE]; + } else { + *reg = g400_color_alpha_combine[unit][MGA_REPLACE]; + } + break; + + case GL_MODULATE: + if (format == GL_ALPHA) { + *reg = g400_alpha_combine[unit][MGA_MODULATE]; + } else if (format == GL_RGB || format == GL_LUMINANCE) { + *reg = g400_color_combine[unit][MGA_MODULATE]; + } else { + *reg = g400_color_alpha_combine[unit][MGA_MODULATE]; + } + break; + + case GL_DECAL: + if (format == GL_RGB) { + *reg = g400_color_combine[unit][MGA_DECAL]; + } else if (format == GL_RGBA) { + *reg = g400_color_alpha_combine[unit][MGA_DECAL]; + if (ctx->Texture._EnabledUnits != 0x03) { + /* Linear blending mode needs dual texturing enabled */ + *(reg+1) = (TD0_color_arg2_prevstage | + TD0_color_sel_arg2 | + TD0_alpha_arg2_prevstage | + TD0_alpha_sel_arg2); + mmesa->force_dualtex = GL_TRUE; + } + } else { + /* Undefined */ + *reg = g400_alpha_combine[unit][MGA_DECAL]; + } + break; + + case GL_ADD: + if (format == GL_ALPHA) { + *reg = g400_alpha_combine[unit][MGA_ADD]; + } else if (format == GL_RGB || format == GL_LUMINANCE) { + *reg = g400_color_combine[unit][MGA_ADD]; + } else if (format == GL_RGBA || format == GL_LUMINANCE_ALPHA) { + *reg = g400_color_alpha_combine[unit][MGA_ADD]; + } else if (format == GL_INTENSITY) { + /* Cv = Cf + Cs + * Av = Af + As + */ + if (unit == 0) { + *reg = (TD0_color_arg2_diffuse | + TD0_color_add_add | + TD0_color_sel_add | + TD0_alpha_arg2_diffuse | + TD0_alpha_add_enable | + TD0_alpha_sel_add); + } else { + *reg = (TD0_color_arg2_prevstage | + TD0_color_add_add | + TD0_color_sel_add | + TD0_alpha_arg2_prevstage | + TD0_alpha_add_enable | + TD0_alpha_sel_add); + } + } + break; + + case GL_BLEND: + if (!mgaUpdateTextureEnvBlend(ctx, unit)) + t->texenv_fallback = GL_TRUE; + break; + + case GL_COMBINE: + if (!mgaUpdateTextureEnvCombine(ctx, unit)) + t->texenv_fallback = GL_TRUE; + break; + default: + break; + } +} + +static void disable_tex( GLcontext *ctx, int unit ) +{ + mgaContextPtr mmesa = MGA_CONTEXT( ctx ); + + /* Texture unit disabled */ + + if ( mmesa->CurrentTexObj[unit] != NULL ) { + /* The old texture is no longer bound to this texture unit. + * Mark it as such. + */ + + mmesa->CurrentTexObj[unit]->base.bound &= ~(1UL << unit); + mmesa->CurrentTexObj[unit] = NULL; + } + + if ( unit != 0 && !mmesa->force_dualtex ) { + mmesa->setup.tdualstage1 = mmesa->setup.tdualstage0; + } + + if ( ctx->Texture._EnabledUnits == 0 ) { + mmesa->setup.dwgctl &= DC_opcod_MASK; + mmesa->setup.dwgctl |= DC_opcod_trap; + mmesa->hw.alpha_sel = AC_alphasel_diffused; + } + + mmesa->dirty |= MGA_UPLOAD_CONTEXT | (MGA_UPLOAD_TEX0 << unit); +} + +static GLboolean enable_tex( GLcontext *ctx, int unit ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + const int source = mmesa->tmu_source[unit]; + const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source]; + const struct gl_texture_object *tObj = texUnit->_Current; + mgaTextureObjectPtr t = (mgaTextureObjectPtr) tObj->DriverData; + + /* Upload teximages (not pipelined) + */ + if (t->base.dirty_images[0]) { + FLUSH_BATCH( mmesa ); + mgaSetTexImages( mmesa, tObj ); + if ( t->base.memBlock == NULL ) { + return GL_FALSE; + } + } + + return GL_TRUE; +} + +static GLboolean update_tex_common( GLcontext *ctx, int unit ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + const int source = mmesa->tmu_source[unit]; + const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source]; + struct gl_texture_object *tObj = texUnit->_Current; + mgaTextureObjectPtr t = (mgaTextureObjectPtr) tObj->DriverData; + + /* Fallback if there's a texture border */ + if ( tObj->Image[0][tObj->BaseLevel]->Border > 0 ) { + return GL_FALSE; + } + + + /* Update state if this is a different texture object to last + * time. + */ + if ( mmesa->CurrentTexObj[unit] != t ) { + if ( mmesa->CurrentTexObj[unit] != NULL ) { + /* The old texture is no longer bound to this texture unit. + * Mark it as such. + */ + + mmesa->CurrentTexObj[unit]->base.bound &= ~(1UL << unit); + } + + mmesa->CurrentTexObj[unit] = t; + t->base.bound |= (1UL << unit); + + driUpdateTextureLRU( (driTextureObject *) t ); /* done too often */ + } + + /* register setup */ + if ( unit == 1 ) { + mmesa->setup.tdualstage1 = mmesa->setup.tdualstage0; + } + + t->texenv_fallback = GL_FALSE; + + /* Set this before mgaUpdateTextureEnvG400() since + * GL_ARB_texture_env_crossbar may have to disable texturing. + */ + mmesa->setup.dwgctl &= DC_opcod_MASK; + mmesa->setup.dwgctl |= DC_opcod_texture_trap; + + /* FIXME: The Radeon has some cached state so that it can avoid calling + * FIXME: UpdateTextureEnv in some cases. Is that possible here? + */ + if (MGA_IS_G400(mmesa)) { + /* G400: Regardless of texture env mode, we use the alpha from the + * texture unit (AC_alphasel_fromtex) since it will have already + * been modulated by the incoming fragment color, if needed. + * We don't want (AC_alphasel_modulate) since that'll effectively + * do the modulation twice. + */ + mmesa->hw.alpha_sel = AC_alphasel_fromtex; + + mgaUpdateTextureEnvG400( ctx, unit ); + } else { + mgaUpdateTextureEnvG200( ctx, unit ); + } + + t->setup.texctl2 &= TMC_dualtex_MASK; + if (ctx->Texture._EnabledUnits == 0x03 || mmesa->force_dualtex) { + t->setup.texctl2 |= TMC_dualtex_enable; + } + + mmesa->dirty |= MGA_UPLOAD_CONTEXT | (MGA_UPLOAD_TEX0 << unit); + + FALLBACK( ctx, MGA_FALLBACK_BORDER_MODE, t->border_fallback ); + return !t->border_fallback && !t->texenv_fallback; +} + + +static GLboolean updateTextureUnit( GLcontext *ctx, int unit ) +{ + mgaContextPtr mmesa = MGA_CONTEXT( ctx ); + const int source = mmesa->tmu_source[unit]; + const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source]; + + + if ( texUnit->_ReallyEnabled == TEXTURE_2D_BIT || + texUnit->_ReallyEnabled == TEXTURE_RECT_BIT ) { + return(enable_tex( ctx, unit ) && + update_tex_common( ctx, unit )); + } + else if ( texUnit->_ReallyEnabled ) { + return GL_FALSE; + } + else { + disable_tex( ctx, unit ); + return GL_TRUE; + } +} + +/* The G400 is now programmed quite differently wrt texture environment. + */ +void mgaUpdateTextureState( GLcontext *ctx ) +{ + mgaContextPtr mmesa = MGA_CONTEXT( ctx ); + GLboolean ok; + unsigned i; + + mmesa->force_dualtex = GL_FALSE; + mmesa->fcol_used = GL_FALSE; + + /* This works around a quirk with the MGA hardware. If only OpenGL + * TEXTURE1 is enabled, then the hardware TEXTURE0 must be used. The + * hardware TEXTURE1 can ONLY be used when hardware TEXTURE0 is also used. + */ + + mmesa->tmu_source[0] = 0; + mmesa->tmu_source[1] = 1; + + if ((ctx->Texture._EnabledUnits & 0x03) == 0x02) { + /* only texture 1 enabled */ + mmesa->tmu_source[0] = 1; + mmesa->tmu_source[1] = 0; + } + + for ( i = 0, ok = GL_TRUE + ; (i < ctx->Const.MaxTextureUnits) && ok + ; i++ ) { + ok = updateTextureUnit( ctx, i ); + } + + FALLBACK( ctx, MGA_FALLBACK_TEXTURE, !ok ); +} diff --git a/src/mga_xmesa.c b/src/mga_xmesa.c new file mode 100644 index 0000000..f4e651a --- /dev/null +++ b/src/mga_xmesa.c @@ -0,0 +1,1046 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mga_xmesa.c,v 1.19 2003/03/26 20:43:49 tsi Exp $ */ +/* + * Copyright 2000-2001 VA Linux Systems, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file mga_xmesa.c + * MGA screen and context initialization / creation code. + * + * \author Keith Whitwell <keith@tungstengraphics.com> + */ + +#include <stdlib.h> +#include <stdint.h> +#include "drm.h" +#include "mga_drm.h" +#include "mga_xmesa.h" +#include "context.h" +#include "matrix.h" +#include "simple_list.h" +#include "imports.h" +#include "framebuffer.h" +#include "renderbuffer.h" + +#include "swrast/swrast.h" +#include "swrast_setup/swrast_setup.h" +#include "tnl/tnl.h" +#include "vbo/vbo.h" + +#include "tnl/t_pipeline.h" + +#include "drivers/common/driverfuncs.h" + +#include "mgadd.h" +#include "mgastate.h" +#include "mgatex.h" +#include "mgaspan.h" +#include "mgaioctl.h" +#include "mgatris.h" +#include "mgavb.h" +#include "mgapixel.h" +#include "mga_xmesa.h" +#include "mga_dri.h" + +#include "utils.h" +#include "vblank.h" + +#include "extensions.h" +#include "drirenderbuffer.h" + +#include "GL/internal/dri_interface.h" + +#define need_GL_ARB_multisample +#define need_GL_ARB_texture_compression +#define need_GL_ARB_vertex_buffer_object +#define need_GL_ARB_vertex_program +#define need_GL_EXT_fog_coord +#define need_GL_EXT_multi_draw_arrays +#define need_GL_EXT_secondary_color +#if 0 +#define need_GL_EXT_paletted_texture +#endif +#define need_GL_NV_vertex_program +#include "extension_helper.h" + +/* MGA configuration + */ +#include "xmlpool.h" + +PUBLIC const char __driConfigOptions[] = +DRI_CONF_BEGIN + DRI_CONF_SECTION_PERFORMANCE + DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0) + DRI_CONF_SECTION_END + DRI_CONF_SECTION_QUALITY + DRI_CONF_TEXTURE_DEPTH(DRI_CONF_TEXTURE_DEPTH_FB) + DRI_CONF_COLOR_REDUCTION(DRI_CONF_COLOR_REDUCTION_DITHER) + DRI_CONF_SECTION_END + DRI_CONF_SECTION_SOFTWARE + DRI_CONF_ARB_VERTEX_PROGRAM(true) + DRI_CONF_NV_VERTEX_PROGRAM(true) + DRI_CONF_SECTION_END + DRI_CONF_SECTION_DEBUG + DRI_CONF_NO_RAST(false) + DRI_CONF_SECTION_END +DRI_CONF_END; +static const GLuint __driNConfigOptions = 6; + +#ifndef MGA_DEBUG +int MGA_DEBUG = 0; +#endif + +static int getSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo ); + +static __GLcontextModes * +mgaFillInModes( unsigned pixel_bits, unsigned depth_bits, + unsigned stencil_bits, GLboolean have_back_buffer ) +{ + __GLcontextModes * modes; + __GLcontextModes * m; + unsigned num_modes; + unsigned depth_buffer_factor; + unsigned back_buffer_factor; + GLenum fb_format; + GLenum fb_type; + + /* GLX_SWAP_COPY_OML is only supported because the MGA driver doesn't + * support pageflipping at all. + */ + static const GLenum back_buffer_modes[] = { + GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML + }; + + u_int8_t depth_bits_array[3]; + u_int8_t stencil_bits_array[3]; + + + depth_bits_array[0] = 0; + depth_bits_array[1] = depth_bits; + depth_bits_array[2] = depth_bits; + + /* Just like with the accumulation buffer, always provide some modes + * with a stencil buffer. It will be a sw fallback, but some apps won't + * care about that. + */ + stencil_bits_array[0] = 0; + stencil_bits_array[1] = 0; + stencil_bits_array[2] = (stencil_bits == 0) ? 8 : stencil_bits; + + depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 3 : 1; + back_buffer_factor = (have_back_buffer) ? 2 : 1; + + num_modes = depth_buffer_factor * back_buffer_factor * 4; + + if ( pixel_bits == 16 ) { + fb_format = GL_RGB; + fb_type = GL_UNSIGNED_SHORT_5_6_5; + } + else { + fb_format = GL_BGR; + fb_type = GL_UNSIGNED_INT_8_8_8_8_REV; + } + + modes = (*dri_interface->createContextModes)( num_modes, sizeof( __GLcontextModes ) ); + m = modes; + if ( ! driFillInModes( & m, fb_format, fb_type, + depth_bits_array, stencil_bits_array, depth_buffer_factor, + back_buffer_modes, back_buffer_factor, + GLX_TRUE_COLOR ) ) { + fprintf( stderr, "[%s:%u] Error creating FBConfig!\n", + __func__, __LINE__ ); + return NULL; + } + + if ( ! driFillInModes( & m, fb_format, fb_type, + depth_bits_array, stencil_bits_array, depth_buffer_factor, + back_buffer_modes, back_buffer_factor, + GLX_DIRECT_COLOR ) ) { + fprintf( stderr, "[%s:%u] Error creating FBConfig!\n", + __func__, __LINE__ ); + return NULL; + } + + /* Mark the visual as slow if there are "fake" stencil bits. + */ + for ( m = modes ; m != NULL ; m = m->next ) { + if ( (m->stencilBits != 0) && (m->stencilBits != stencil_bits) ) { + m->visualRating = GLX_SLOW_CONFIG; + } + } + + return modes; +} + + +static GLboolean +mgaInitDriver(__DRIscreenPrivate *sPriv) +{ + mgaScreenPrivate *mgaScreen; + MGADRIPtr serverInfo = (MGADRIPtr)sPriv->pDevPriv; + PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension = + (PFNGLXSCRENABLEEXTENSIONPROC) (*dri_interface->getProcAddress("glxEnableExtension")); + void * const psc = sPriv->psc->screenConfigs; + + if (sPriv->devPrivSize != sizeof(MGADRIRec)) { + fprintf(stderr,"\nERROR! sizeof(MGADRIRec) does not match passed size from device driver\n"); + return GL_FALSE; + } + + /* Allocate the private area */ + mgaScreen = (mgaScreenPrivate *)MALLOC(sizeof(mgaScreenPrivate)); + if (!mgaScreen) { + __driUtilMessage("Couldn't malloc screen struct"); + return GL_FALSE; + } + + mgaScreen->sPriv = sPriv; + sPriv->private = (void *)mgaScreen; + + if (sPriv->drmMinor >= 1) { + int ret; + drm_mga_getparam_t gp; + + gp.param = MGA_PARAM_IRQ_NR; + gp.value = &mgaScreen->irq; + mgaScreen->irq = 0; + + ret = drmCommandWriteRead( sPriv->fd, DRM_MGA_GETPARAM, + &gp, sizeof(gp)); + if (ret) { + fprintf(stderr, "drmMgaGetParam (MGA_PARAM_IRQ_NR): %d\n", ret); + FREE(mgaScreen); + sPriv->private = NULL; + return GL_FALSE; + } + } + + if ( glx_enable_extension != NULL ) { + (*glx_enable_extension)( psc, "GLX_MESA_swap_control" ); + (*glx_enable_extension)( psc, "GLX_MESA_swap_frame_usage" ); + (*glx_enable_extension)( psc, "GLX_SGI_make_current_read" ); + (*glx_enable_extension)( psc, "GLX_SGI_swap_control" ); + (*glx_enable_extension)( psc, "GLX_SGI_video_sync" ); + } + + if (serverInfo->chipset != MGA_CARD_TYPE_G200 && + serverInfo->chipset != MGA_CARD_TYPE_G400) { + FREE(mgaScreen); + sPriv->private = NULL; + __driUtilMessage("Unrecognized chipset"); + return GL_FALSE; + } + + + mgaScreen->chipset = serverInfo->chipset; + mgaScreen->cpp = serverInfo->cpp; + + mgaScreen->agpMode = serverInfo->agpMode; + + mgaScreen->frontPitch = serverInfo->frontPitch; + mgaScreen->frontOffset = serverInfo->frontOffset; + mgaScreen->backOffset = serverInfo->backOffset; + mgaScreen->backPitch = serverInfo->backPitch; + mgaScreen->depthOffset = serverInfo->depthOffset; + mgaScreen->depthPitch = serverInfo->depthPitch; + + + /* The only reason that the MMIO region needs to be accessable and the + * primary DMA region base address needs to be known is so that the driver + * can busy wait for certain DMA operations to complete (see + * mgaWaitForFrameCompletion in mgaioctl.c). + * + * Starting with MGA DRM version 3.2, these are completely unneeded as + * there is a new, in-kernel mechanism for handling the wait. + */ + + if (mgaScreen->sPriv->drmMinor < 2) { + mgaScreen->mmio.handle = serverInfo->registers.handle; + mgaScreen->mmio.size = serverInfo->registers.size; + if ( drmMap( sPriv->fd, + mgaScreen->mmio.handle, mgaScreen->mmio.size, + &mgaScreen->mmio.map ) < 0 ) { + FREE( mgaScreen ); + sPriv->private = NULL; + __driUtilMessage( "Couldn't map MMIO registers" ); + return GL_FALSE; + } + + mgaScreen->primary.handle = serverInfo->primary.handle; + mgaScreen->primary.size = serverInfo->primary.size; + } + else { + (void) memset( & mgaScreen->primary, 0, sizeof( mgaScreen->primary ) ); + (void) memset( & mgaScreen->mmio, 0, sizeof( mgaScreen->mmio ) ); + } + + mgaScreen->textureOffset[MGA_CARD_HEAP] = serverInfo->textureOffset; + mgaScreen->textureOffset[MGA_AGP_HEAP] = (serverInfo->agpTextureOffset | + PDEA_pagpxfer_enable | 1); + + mgaScreen->textureSize[MGA_CARD_HEAP] = serverInfo->textureSize; + mgaScreen->textureSize[MGA_AGP_HEAP] = serverInfo->agpTextureSize; + + + /* The texVirtual array stores the base addresses in the CPU's address + * space of the texture memory pools. The base address of the on-card + * memory pool is calculated as an offset of the base of video memory. The + * AGP texture pool has to be mapped into the processes address space by + * the DRM. + */ + + mgaScreen->texVirtual[MGA_CARD_HEAP] = (char *)(mgaScreen->sPriv->pFB + + serverInfo->textureOffset); + + if ( serverInfo->agpTextureSize > 0 ) { + if (drmMap(sPriv->fd, serverInfo->agpTextureOffset, + serverInfo->agpTextureSize, + (drmAddress *)&mgaScreen->texVirtual[MGA_AGP_HEAP]) != 0) { + FREE(mgaScreen); + sPriv->private = NULL; + __driUtilMessage("Couldn't map agptexture region"); + return GL_FALSE; + } + } + + + /* For calculating setupdma addresses. + */ + + mgaScreen->bufs = drmMapBufs(sPriv->fd); + if (!mgaScreen->bufs) { + FREE(mgaScreen); + sPriv->private = NULL; + __driUtilMessage("Couldn't map dma buffers"); + return GL_FALSE; + } + mgaScreen->sarea_priv_offset = serverInfo->sarea_priv_offset; + + /* parse information in __driConfigOptions */ + driParseOptionInfo (&mgaScreen->optionCache, + __driConfigOptions, __driNConfigOptions); + + return GL_TRUE; +} + + +static void +mgaDestroyScreen(__DRIscreenPrivate *sPriv) +{ + mgaScreenPrivate *mgaScreen = (mgaScreenPrivate *) sPriv->private; + + if (MGA_DEBUG&DEBUG_VERBOSE_DRI) + fprintf(stderr, "mgaDestroyScreen\n"); + + drmUnmapBufs(mgaScreen->bufs); + + + /* free all option information */ + driDestroyOptionInfo (&mgaScreen->optionCache); + + FREE(mgaScreen); + sPriv->private = NULL; +} + + +extern const struct tnl_pipeline_stage _mga_render_stage; + +static const struct tnl_pipeline_stage *mga_pipeline[] = { + &_tnl_vertex_transform_stage, + &_tnl_normal_transform_stage, + &_tnl_lighting_stage, + &_tnl_fog_coordinate_stage, + &_tnl_texgen_stage, + &_tnl_texture_transform_stage, + &_tnl_vertex_program_stage, + + /* REMOVE: point attenuation stage */ +#if 0 + &_mga_render_stage, /* ADD: unclipped rastersetup-to-dma */ + /* Need new ioctl for wacceptseq */ +#endif + &_tnl_render_stage, + 0, +}; + + +static const struct dri_extension g400_extensions[] = +{ + { "GL_ARB_multitexture", NULL }, + { "GL_ARB_texture_env_add", NULL }, + { "GL_ARB_texture_env_combine", NULL }, + { "GL_ARB_texture_env_crossbar", NULL }, + { "GL_EXT_texture_env_combine", NULL }, + { "GL_EXT_texture_edge_clamp", NULL }, + { "GL_ATI_texture_env_combine3", NULL }, + { NULL, NULL } +}; + +static const struct dri_extension card_extensions[] = +{ + { "GL_ARB_multisample", GL_ARB_multisample_functions }, + { "GL_ARB_texture_compression", GL_ARB_texture_compression_functions }, + { "GL_ARB_texture_rectangle", NULL }, + { "GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions }, + { "GL_EXT_blend_logic_op", NULL }, + { "GL_EXT_fog_coord", GL_EXT_fog_coord_functions }, + { "GL_EXT_multi_draw_arrays", GL_EXT_multi_draw_arrays_functions }, + /* paletted_textures currently doesn't work, but we could fix them later */ +#if defined( need_GL_EXT_paletted_texture ) + { "GL_EXT_shared_texture_palette", NULL }, + { "GL_EXT_paletted_texture", GL_EXT_paletted_texture_functions }, +#endif + { "GL_EXT_secondary_color", GL_EXT_secondary_color_functions }, + { "GL_EXT_stencil_wrap", NULL }, + { "GL_MESA_ycbcr_texture", NULL }, + { "GL_SGIS_generate_mipmap", NULL }, + { NULL, NULL } +}; + +static const struct dri_extension ARB_vp_extension[] = { + { "GL_ARB_vertex_program", GL_ARB_vertex_program_functions }, + { NULL, NULL } +}; + +static const struct dri_extension NV_vp_extensions[] = { + { "GL_NV_vertex_program", GL_NV_vertex_program_functions }, + { "GL_NV_vertex_program1_1", NULL }, + { NULL, NULL } +}; + +static const struct dri_debug_control debug_control[] = +{ + { "fall", DEBUG_VERBOSE_FALLBACK }, + { "tex", DEBUG_VERBOSE_TEXTURE }, + { "ioctl", DEBUG_VERBOSE_IOCTL }, + { "verb", DEBUG_VERBOSE_MSG }, + { "dri", DEBUG_VERBOSE_DRI }, + { NULL, 0 } +}; + + +static GLboolean +mgaCreateContext( const __GLcontextModes *mesaVis, + __DRIcontextPrivate *driContextPriv, + void *sharedContextPrivate ) +{ + int i; + unsigned maxlevels; + GLcontext *ctx, *shareCtx; + mgaContextPtr mmesa; + __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv; + mgaScreenPrivate *mgaScreen = (mgaScreenPrivate *)sPriv->private; + drm_mga_sarea_t *saPriv = (drm_mga_sarea_t *)(((char*)sPriv->pSAREA)+ + mgaScreen->sarea_priv_offset); + struct dd_function_table functions; + + if (MGA_DEBUG&DEBUG_VERBOSE_DRI) + fprintf(stderr, "mgaCreateContext\n"); + + /* allocate mga context */ + mmesa = (mgaContextPtr) CALLOC(sizeof(mgaContext)); + if (!mmesa) { + return GL_FALSE; + } + + /* Init default driver functions then plug in our Radeon-specific functions + * (the texture functions are especially important) + */ + _mesa_init_driver_functions( &functions ); + mgaInitDriverFuncs( &functions ); + mgaInitTextureFuncs( &functions ); + mgaInitIoctlFuncs( &functions ); + + /* Allocate the Mesa context */ + if (sharedContextPrivate) + shareCtx = ((mgaContextPtr) sharedContextPrivate)->glCtx; + else + shareCtx = NULL; + mmesa->glCtx = _mesa_create_context(mesaVis, shareCtx, + &functions, (void *) mmesa); + if (!mmesa->glCtx) { + FREE(mmesa); + return GL_FALSE; + } + driContextPriv->driverPrivate = mmesa; + + /* Init mga state */ + mmesa->hHWContext = driContextPriv->hHWContext; + mmesa->driFd = sPriv->fd; + mmesa->driHwLock = &sPriv->pSAREA->lock; + + mmesa->mgaScreen = mgaScreen; + mmesa->driScreen = sPriv; + mmesa->sarea = (void *)saPriv; + + /* Parse configuration files */ + driParseConfigFiles (&mmesa->optionCache, &mgaScreen->optionCache, + sPriv->myNum, "mga"); + + (void) memset( mmesa->texture_heaps, 0, sizeof( mmesa->texture_heaps ) ); + make_empty_list( & mmesa->swapped ); + + mmesa->nr_heaps = mgaScreen->texVirtual[MGA_AGP_HEAP] ? 2 : 1; + for ( i = 0 ; i < mmesa->nr_heaps ; i++ ) { + mmesa->texture_heaps[i] = driCreateTextureHeap( i, mmesa, + mgaScreen->textureSize[i], + 6, + MGA_NR_TEX_REGIONS, + (drmTextureRegionPtr)mmesa->sarea->texList[i], + &mmesa->sarea->texAge[i], + &mmesa->swapped, + sizeof( mgaTextureObject_t ), + (destroy_texture_object_t *) mgaDestroyTexObj ); + } + + /* Set the maximum texture size small enough that we can guarentee + * that both texture units can bind a maximal texture and have them + * on the card at once. + */ + ctx = mmesa->glCtx; + if ( mgaScreen->chipset == MGA_CARD_TYPE_G200 ) { + ctx->Const.MaxTextureUnits = 1; + ctx->Const.MaxTextureImageUnits = 1; + ctx->Const.MaxTextureCoordUnits = 1; + maxlevels = G200_TEX_MAXLEVELS; + + } + else { + ctx->Const.MaxTextureUnits = 2; + ctx->Const.MaxTextureImageUnits = 2; + ctx->Const.MaxTextureCoordUnits = 2; + maxlevels = G400_TEX_MAXLEVELS; + } + + driCalculateMaxTextureLevels( mmesa->texture_heaps, + mmesa->nr_heaps, + & ctx->Const, + 4, + 11, /* max 2D texture size is 2048x2048 */ + 0, /* 3D textures unsupported. */ + 0, /* cube textures unsupported. */ + 11, /* max texture rect size is 2048x2048 */ + maxlevels, + GL_FALSE, + 0 ); + + ctx->Const.MinLineWidth = 1.0; + ctx->Const.MinLineWidthAA = 1.0; + ctx->Const.MaxLineWidth = 10.0; + ctx->Const.MaxLineWidthAA = 10.0; + ctx->Const.LineWidthGranularity = 1.0; + + mmesa->texture_depth = driQueryOptioni (&mmesa->optionCache, + "texture_depth"); + if (mmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FB) + mmesa->texture_depth = ( mesaVis->rgbBits >= 24 ) ? + DRI_CONF_TEXTURE_DEPTH_32 : DRI_CONF_TEXTURE_DEPTH_16; + mmesa->hw_stencil = mesaVis->stencilBits && mesaVis->depthBits == 24; + + switch (mesaVis->depthBits) { + case 16: + mmesa->depth_scale = 1.0/(GLdouble)0xffff; + mmesa->depth_clear_mask = ~0; + mmesa->ClearDepth = 0xffff; + break; + case 24: + mmesa->depth_scale = 1.0/(GLdouble)0xffffff; + if (mmesa->hw_stencil) { + mmesa->depth_clear_mask = 0xffffff00; + mmesa->stencil_clear_mask = 0x000000ff; + } else + mmesa->depth_clear_mask = ~0; + mmesa->ClearDepth = 0xffffff00; + break; + case 32: + mmesa->depth_scale = 1.0/(GLdouble)0xffffffff; + mmesa->depth_clear_mask = ~0; + mmesa->ClearDepth = 0xffffffff; + break; + }; + + mmesa->haveHwStipple = GL_FALSE; + mmesa->RenderIndex = -1; /* impossible value */ + mmesa->dirty = ~0; + mmesa->vertex_format = 0; + mmesa->CurrentTexObj[0] = 0; + mmesa->CurrentTexObj[1] = 0; + mmesa->tmu_source[0] = 0; + mmesa->tmu_source[1] = 1; + + mmesa->texAge[0] = 0; + mmesa->texAge[1] = 0; + + /* Initialize the software rasterizer and helper modules. + */ + _swrast_CreateContext( ctx ); + _vbo_CreateContext( ctx ); + _tnl_CreateContext( ctx ); + + _swsetup_CreateContext( ctx ); + + /* Install the customized pipeline: + */ + _tnl_destroy_pipeline( ctx ); + _tnl_install_pipeline( ctx, mga_pipeline ); + + /* Configure swrast and T&L to match hardware characteristics: + */ + _swrast_allow_pixel_fog( ctx, GL_FALSE ); + _swrast_allow_vertex_fog( ctx, GL_TRUE ); + _tnl_allow_pixel_fog( ctx, GL_FALSE ); + _tnl_allow_vertex_fog( ctx, GL_TRUE ); + + mmesa->primary_offset = mmesa->mgaScreen->primary.handle; + + ctx->DriverCtx = (void *) mmesa; + mmesa->glCtx = ctx; + + driInitExtensions( ctx, card_extensions, GL_FALSE ); + + if (MGA_IS_G400(MGA_CONTEXT(ctx))) { + driInitExtensions( ctx, g400_extensions, GL_FALSE ); + } + + if ( driQueryOptionb( &mmesa->optionCache, "arb_vertex_program" ) ) { + driInitSingleExtension( ctx, ARB_vp_extension ); + } + + if ( driQueryOptionb( &mmesa->optionCache, "nv_vertex_program" ) ) { + driInitExtensions( ctx, NV_vp_extensions, GL_FALSE ); + } + + + /* XXX these should really go right after _mesa_init_driver_functions() */ + mgaDDInitStateFuncs( ctx ); + mgaDDInitSpanFuncs( ctx ); + mgaDDInitPixelFuncs( ctx ); + mgaDDInitTriFuncs( ctx ); + + mgaInitVB( ctx ); + mgaInitState( mmesa ); + + driContextPriv->driverPrivate = (void *) mmesa; + +#if DO_DEBUG + MGA_DEBUG = driParseDebugString( getenv( "MGA_DEBUG" ), + debug_control ); +#endif + + mmesa->vblank_flags = (mmesa->mgaScreen->irq == 0) + ? VBLANK_FLAG_NO_IRQ : driGetDefaultVBlankFlags(&mmesa->optionCache); + + (*dri_interface->getUST)( & mmesa->swap_ust ); + + if (driQueryOptionb(&mmesa->optionCache, "no_rast")) { + fprintf(stderr, "disabling 3D acceleration\n"); + FALLBACK(mmesa->glCtx, MGA_FALLBACK_DISABLE, 1); + } + + return GL_TRUE; +} + +static void +mgaDestroyContext(__DRIcontextPrivate *driContextPriv) +{ + mgaContextPtr mmesa = (mgaContextPtr) driContextPriv->driverPrivate; + + if (MGA_DEBUG&DEBUG_VERBOSE_DRI) + fprintf( stderr, "[%s:%d] mgaDestroyContext start\n", + __FILE__, __LINE__ ); + + assert(mmesa); /* should never be null */ + if (mmesa) { + GLboolean release_texture_heaps; + + + release_texture_heaps = (mmesa->glCtx->Shared->RefCount == 1); + _swsetup_DestroyContext( mmesa->glCtx ); + _tnl_DestroyContext( mmesa->glCtx ); + _vbo_DestroyContext( mmesa->glCtx ); + _swrast_DestroyContext( mmesa->glCtx ); + + mgaFreeVB( mmesa->glCtx ); + + /* free the Mesa context */ + mmesa->glCtx->DriverCtx = NULL; + _mesa_destroy_context(mmesa->glCtx); + + if ( release_texture_heaps ) { + /* This share group is about to go away, free our private + * texture object data. + */ + int i; + + for ( i = 0 ; i < mmesa->nr_heaps ; i++ ) { + driDestroyTextureHeap( mmesa->texture_heaps[ i ] ); + mmesa->texture_heaps[ i ] = NULL; + } + + assert( is_empty_list( & mmesa->swapped ) ); + } + + /* free the option cache */ + driDestroyOptionCache (&mmesa->optionCache); + + FREE(mmesa); + } + + if (MGA_DEBUG&DEBUG_VERBOSE_DRI) + fprintf( stderr, "[%s:%d] mgaDestroyContext done\n", + __FILE__, __LINE__ ); +} + + +static GLboolean +mgaCreateBuffer( __DRIscreenPrivate *driScrnPriv, + __DRIdrawablePrivate *driDrawPriv, + const __GLcontextModes *mesaVis, + GLboolean isPixmap ) +{ + mgaScreenPrivate *screen = (mgaScreenPrivate *) driScrnPriv->private; + + if (isPixmap) { + return GL_FALSE; /* not implemented */ + } + else { + GLboolean swStencil = (mesaVis->stencilBits > 0 && + mesaVis->depthBits != 24); + +#if 0 + driDrawPriv->driverPrivate = (void *) + _mesa_create_framebuffer(mesaVis, + GL_FALSE, /* software depth buffer? */ + swStencil, + mesaVis->accumRedBits > 0, + mesaVis->alphaBits > 0 ); +#else + struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis); + + { + driRenderbuffer *frontRb + = driNewRenderbuffer(GL_RGBA, + NULL, + screen->cpp, + screen->frontOffset, screen->frontPitch, + driDrawPriv); + mgaSetSpanFunctions(frontRb, mesaVis); + _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base); + } + + if (mesaVis->doubleBufferMode) { + driRenderbuffer *backRb + = driNewRenderbuffer(GL_RGBA, + NULL, + screen->cpp, + screen->backOffset, screen->backPitch, + driDrawPriv); + mgaSetSpanFunctions(backRb, mesaVis); + _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base); + } + + if (mesaVis->depthBits == 16) { + driRenderbuffer *depthRb + = driNewRenderbuffer(GL_DEPTH_COMPONENT16, + NULL, + screen->cpp, + screen->depthOffset, screen->depthPitch, + driDrawPriv); + mgaSetSpanFunctions(depthRb, mesaVis); + _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base); + } + else if (mesaVis->depthBits == 24) { + /* XXX is this right? */ + if (mesaVis->stencilBits) { + driRenderbuffer *depthRb + = driNewRenderbuffer(GL_DEPTH_COMPONENT24, + NULL, + screen->cpp, + screen->depthOffset, screen->depthPitch, + driDrawPriv); + mgaSetSpanFunctions(depthRb, mesaVis); + _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base); + } + else { + driRenderbuffer *depthRb + = driNewRenderbuffer(GL_DEPTH_COMPONENT32, + NULL, + screen->cpp, + screen->depthOffset, screen->depthPitch, + driDrawPriv); + mgaSetSpanFunctions(depthRb, mesaVis); + _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base); + } + } + else if (mesaVis->depthBits == 32) { + driRenderbuffer *depthRb + = driNewRenderbuffer(GL_DEPTH_COMPONENT32, + NULL, + screen->cpp, + screen->depthOffset, screen->depthPitch, + driDrawPriv); + mgaSetSpanFunctions(depthRb, mesaVis); + _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base); + } + + if (mesaVis->stencilBits > 0 && !swStencil) { + driRenderbuffer *stencilRb + = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT, + NULL, + screen->cpp, + screen->depthOffset, screen->depthPitch, + driDrawPriv); + mgaSetSpanFunctions(stencilRb, mesaVis); + _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base); + } + + _mesa_add_soft_renderbuffers(fb, + GL_FALSE, /* color */ + GL_FALSE, /* depth */ + swStencil, + mesaVis->accumRedBits > 0, + GL_FALSE, /* alpha */ + GL_FALSE /* aux */); + driDrawPriv->driverPrivate = (void *) fb; +#endif + + return (driDrawPriv->driverPrivate != NULL); + } +} + + +static void +mgaDestroyBuffer(__DRIdrawablePrivate *driDrawPriv) +{ + _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate))); +} + +static void +mgaSwapBuffers(__DRIdrawablePrivate *dPriv) +{ + if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) { + mgaContextPtr mmesa; + GLcontext *ctx; + mmesa = (mgaContextPtr) dPriv->driContextPriv->driverPrivate; + ctx = mmesa->glCtx; + + if (ctx->Visual.doubleBufferMode) { + _mesa_notifySwapBuffers( ctx ); + mgaCopyBuffer( dPriv ); + } + } else { + /* XXX this shouldn't be an error but we can't handle it for now */ + _mesa_problem(NULL, "%s: drawable has no context!\n", __FUNCTION__); + } +} + +static GLboolean +mgaUnbindContext(__DRIcontextPrivate *driContextPriv) +{ + mgaContextPtr mmesa = (mgaContextPtr) driContextPriv->driverPrivate; + if (mmesa) + mmesa->dirty = ~0; + + return GL_TRUE; +} + +/* This looks buggy to me - the 'b' variable isn't used anywhere... + * Hmm - It seems that the drawable is already hooked in to + * driDrawablePriv. + * + * But why are we doing context initialization here??? + */ +static GLboolean +mgaMakeCurrent(__DRIcontextPrivate *driContextPriv, + __DRIdrawablePrivate *driDrawPriv, + __DRIdrawablePrivate *driReadPriv) +{ + if (driContextPriv) { + mgaContextPtr mmesa = (mgaContextPtr) driContextPriv->driverPrivate; + + if (mmesa->driDrawable != driDrawPriv) { + driDrawableInitVBlank( driDrawPriv, mmesa->vblank_flags, + &mmesa->vbl_seq ); + mmesa->driDrawable = driDrawPriv; + mmesa->dirty = ~0; + mmesa->dirty_cliprects = (MGA_FRONT|MGA_BACK); + } + + mmesa->driReadable = driReadPriv; + + _mesa_make_current(mmesa->glCtx, + (GLframebuffer *) driDrawPriv->driverPrivate, + (GLframebuffer *) driReadPriv->driverPrivate); + } + else { + _mesa_make_current(NULL, NULL, NULL); + } + + return GL_TRUE; +} + + +void mgaGetLock( mgaContextPtr mmesa, GLuint flags ) +{ + __DRIdrawablePrivate *dPriv = mmesa->driDrawable; + drm_mga_sarea_t *sarea = mmesa->sarea; + int me = mmesa->hHWContext; + int i; + + drmGetLock(mmesa->driFd, mmesa->hHWContext, flags); + + DRI_VALIDATE_DRAWABLE_INFO( mmesa->driScreen, dPriv ); + if (*(dPriv->pStamp) != mmesa->lastStamp) { + mmesa->lastStamp = *(dPriv->pStamp); + mmesa->SetupNewInputs |= VERT_BIT_POS; + mmesa->dirty_cliprects = (MGA_FRONT|MGA_BACK); + mgaUpdateRects( mmesa, (MGA_FRONT|MGA_BACK) ); + driUpdateFramebufferSize(mmesa->glCtx, dPriv); + } + + mmesa->dirty |= MGA_UPLOAD_CONTEXT | MGA_UPLOAD_CLIPRECTS; + + mmesa->sarea->dirty |= MGA_UPLOAD_CONTEXT; + + if (sarea->ctxOwner != me) { + mmesa->dirty |= (MGA_UPLOAD_CONTEXT | MGA_UPLOAD_TEX0 | + MGA_UPLOAD_TEX1 | MGA_UPLOAD_PIPE); + sarea->ctxOwner=me; + } + + for ( i = 0 ; i < mmesa->nr_heaps ; i++ ) { + DRI_AGE_TEXTURES( mmesa->texture_heaps[ i ] ); + } +} + + +static const struct __DriverAPIRec mgaAPI = { + .InitDriver = mgaInitDriver, + .DestroyScreen = mgaDestroyScreen, + .CreateContext = mgaCreateContext, + .DestroyContext = mgaDestroyContext, + .CreateBuffer = mgaCreateBuffer, + .DestroyBuffer = mgaDestroyBuffer, + .SwapBuffers = mgaSwapBuffers, + .MakeCurrent = mgaMakeCurrent, + .UnbindContext = mgaUnbindContext, + .GetSwapInfo = getSwapInfo, + .GetMSC = driGetMSC32, + .WaitForMSC = driWaitForMSC32, + .WaitForSBC = NULL, + .SwapBuffersMSC = NULL +}; + + +/** + * This is the bootstrap function for the driver. libGL supplies all of the + * requisite information about the system, and the driver initializes itself. + * This routine also fills in the linked list pointed to by \c driver_modes + * with the \c __GLcontextModes that the driver can support for windows or + * pbuffers. + * + * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on + * failure. + */ +PUBLIC +void * __driCreateNewScreen_20050727( __DRInativeDisplay *dpy, int scrn, __DRIscreen *psc, + const __GLcontextModes * modes, + const __DRIversion * ddx_version, + const __DRIversion * dri_version, + const __DRIversion * drm_version, + const __DRIframebuffer * frame_buffer, + drmAddress pSAREA, int fd, + int internal_api_version, + const __DRIinterfaceMethods * interface, + __GLcontextModes ** driver_modes ) + +{ + __DRIscreenPrivate *psp; + static const __DRIversion ddx_expected = { 1, 2, 0 }; + static const __DRIversion dri_expected = { 4, 0, 0 }; + static const __DRIversion drm_expected = { 3, 0, 0 }; + + dri_interface = interface; + + if ( ! driCheckDriDdxDrmVersions2( "MGA", + dri_version, & dri_expected, + ddx_version, & ddx_expected, + drm_version, & drm_expected ) ) { + return NULL; + } + + psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL, + ddx_version, dri_version, drm_version, + frame_buffer, pSAREA, fd, + internal_api_version, &mgaAPI); + if ( psp != NULL ) { + MGADRIPtr dri_priv = (MGADRIPtr) psp->pDevPriv; + *driver_modes = mgaFillInModes( dri_priv->cpp * 8, + (dri_priv->cpp == 2) ? 16 : 24, + (dri_priv->cpp == 2) ? 0 : 8, + (dri_priv->backOffset != dri_priv->depthOffset) ); + + /* Calling driInitExtensions here, with a NULL context pointer, does not actually + * enable the extensions. It just makes sure that all the dispatch offsets for all + * the extensions that *might* be enables are known. This is needed because the + * dispatch offsets need to be known when _mesa_context_create is called, but we can't + * enable the extensions until we have a context pointer. + * + * Hello chicken. Hello egg. How are you two today? + */ + driInitExtensions( NULL, card_extensions, GL_FALSE ); + driInitExtensions( NULL, g400_extensions, GL_FALSE ); + driInitSingleExtension( NULL, ARB_vp_extension ); + driInitExtensions( NULL, NV_vp_extensions, GL_FALSE ); + + } + + return (void *) psp; +} + + +/** + * Get information about previous buffer swaps. + */ +static int +getSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo ) +{ + mgaContextPtr mmesa; + + if ( (dPriv == NULL) || (dPriv->driContextPriv == NULL) + || (dPriv->driContextPriv->driverPrivate == NULL) + || (sInfo == NULL) ) { + return -1; + } + + mmesa = (mgaContextPtr) dPriv->driContextPriv->driverPrivate; + sInfo->swap_count = mmesa->swap_count; + sInfo->swap_ust = mmesa->swap_ust; + sInfo->swap_missed_count = mmesa->swap_missed_count; + + sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0) + ? driCalculateSwapUsage( dPriv, 0, mmesa->swap_missed_ust ) + : 0.0; + + return 0; +} diff --git a/src/mga_xmesa.h b/src/mga_xmesa.h new file mode 100644 index 0000000..0ab0c63 --- /dev/null +++ b/src/mga_xmesa.h @@ -0,0 +1,155 @@ +/* + * Copyright 2000-2001 VA Linux Systems, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ +/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mga_xmesa.h,v 1.12 2002/12/16 16:18:52 dawes Exp $ */ + +#ifndef _MGA_INIT_H_ +#define _MGA_INIT_H_ + +#include <sys/time.h> +#include "dri_util.h" +#include "mga_drm.h" +#include "mtypes.h" +#include "mgaregs.h" +#include "xmlconfig.h" + +typedef struct mga_screen_private_s { + /** + * Chipset "family" of this card. Currently only \c MGA_CARD_TYPE_G200 and + * \c MGA_CARD_TYPE_G400 are possible. + */ + int chipset; + + + /** + * Characters (bytes) per-pixel for both the front and back buffers. + * + * \note + * This is also implicitly the bytes per-pixel for the depth-buffer. + */ + int cpp; + + GLint agpMode; + unsigned int irq; /**< IRQ number (0 means none) */ + + unsigned int frontOffset; + unsigned int frontPitch; + unsigned int backOffset; + unsigned int backPitch; + + unsigned int depthOffset; + unsigned int depthPitch; + + unsigned int textureOffset[MGA_NR_TEX_HEAPS]; + unsigned int textureSize[MGA_NR_TEX_HEAPS]; + char *texVirtual[MGA_NR_TEX_HEAPS]; + + + __DRIscreenPrivate *sPriv; + drmBufMapPtr bufs; + + drmRegion mmio; + drmRegion primary; + unsigned int sarea_priv_offset; + + /** Configuration cache with default values for all contexts */ + driOptionCache optionCache; +} mgaScreenPrivate; + + +/** + * mgaRenderbuffer, derived from Mesa's gl_renderbuffer + */ +typedef struct { + struct gl_renderbuffer Base; + /* XXX per-window info should go here */ + int foo, bar; +} mgaRenderbuffer; + + + +#include "mgacontext.h" + +extern void mgaGetLock( mgaContextPtr mmesa, GLuint flags ); +extern void mgaEmitHwStateLocked( mgaContextPtr mmesa ); +extern void mgaEmitScissorValues( mgaContextPtr mmesa, int box_nr, int emit ); + +#define GET_DISPATCH_AGE( mmesa ) mmesa->sarea->last_dispatch + + + +/* Lock the hardware and validate our state. + */ +#define LOCK_HARDWARE( mmesa ) \ + do { \ + char __ret=0; \ + DRM_CAS(mmesa->driHwLock, mmesa->hHWContext, \ + (DRM_LOCK_HELD|mmesa->hHWContext), __ret); \ + if (__ret) \ + mgaGetLock( mmesa, 0 ); \ + } while (0) + + +/* + */ +#define LOCK_HARDWARE_QUIESCENT( mmesa ) do { \ + LOCK_HARDWARE( mmesa ); \ + UPDATE_LOCK( mmesa, DRM_LOCK_QUIESCENT | DRM_LOCK_FLUSH ); \ +} while (0) + + +/* Unlock the hardware using the global current context + */ +#define UNLOCK_HARDWARE(mmesa) \ + DRM_UNLOCK(mmesa->driFd, mmesa->driHwLock, mmesa->hHWContext); + + +/* Freshen our snapshot of the drawables + */ +#define REFRESH_DRAWABLE_INFO( mmesa ) \ +do { \ + LOCK_HARDWARE( mmesa ); \ + mmesa->lastX = mmesa->drawX; \ + mmesa->lastY = mmesa->drawY; \ + UNLOCK_HARDWARE( mmesa ); \ +} while (0) + + +#define GET_DRAWABLE_LOCK( mmesa ) while(0) +#define RELEASE_DRAWABLE_LOCK( mmesa ) while(0) + + +/* The 2D driver macros are busted -- we can't use them here as they + * rely on the 2D driver data structures rather than taking an explicit + * base address. + */ +#define MGA_BASE( reg ) ((unsigned long)(mmesa->mgaScreen->mmio.map)) +#define MGA_ADDR( reg ) (MGA_BASE(reg) + reg) + +#define MGA_DEREF( reg ) *(volatile u_int32_t *)MGA_ADDR( reg ) +#define MGA_READ( reg ) MGA_DEREF( reg ) + +#endif diff --git a/src/mgacontext.h b/src/mgacontext.h new file mode 100644 index 0000000..2124006 --- /dev/null +++ b/src/mgacontext.h @@ -0,0 +1,365 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgacontext.h,v 1.7 2002/12/16 16:18:52 dawes Exp $*/ +/* + * Copyright 2000-2001 VA Linux Systems, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#ifndef MGALIB_INC +#define MGALIB_INC + +#include <stdint.h> +#include "drm.h" +#include "mga_drm.h" +#include "dri_util.h" +#include "mtypes.h" +#include "xf86drm.h" +#include "mm.h" +#include "colormac.h" +#include "texmem.h" +#include "macros.h" +#include "xmlconfig.h" + +#define MGA_SET_FIELD(reg,mask,val) reg = ((reg) & (mask)) | ((val) & ~(mask)) +#define MGA_FIELD(field,val) (((val) << (field ## _SHIFT)) & ~(field ## _MASK)) +#define MGA_GET_FIELD(field, val) ((val & ~(field ## _MASK)) >> (field ## _SHIFT)) + +#define MGA_IS_G200(mmesa) (mmesa->mgaScreen->chipset == MGA_CARD_TYPE_G200) +#define MGA_IS_G400(mmesa) (mmesa->mgaScreen->chipset == MGA_CARD_TYPE_G400) + + +/* SoftwareFallback + * - texture env GL_BLEND -- can be fixed + * - 1D and 3D textures + * - incomplete textures + * - GL_DEPTH_FUNC == GL_NEVER not in h/w + */ +#define MGA_FALLBACK_TEXTURE 0x1 +#define MGA_FALLBACK_DRAW_BUFFER 0x2 +#define MGA_FALLBACK_READ_BUFFER 0x4 +#define MGA_FALLBACK_BLEND 0x8 +#define MGA_FALLBACK_RENDERMODE 0x10 +#define MGA_FALLBACK_STENCIL 0x20 +#define MGA_FALLBACK_DEPTH 0x40 +#define MGA_FALLBACK_BORDER_MODE 0x80 +#define MGA_FALLBACK_DISABLE 0x100 + + +/* Use the templated vertex formats: + */ +#define TAG(x) mga##x +#include "tnl_dd/t_dd_vertex.h" +#undef TAG + +typedef struct mga_context_t mgaContext; +typedef struct mga_context_t *mgaContextPtr; + +typedef void (*mga_tri_func)( mgaContextPtr, mgaVertex *, mgaVertex *, + mgaVertex * ); +typedef void (*mga_line_func)( mgaContextPtr, mgaVertex *, mgaVertex * ); +typedef void (*mga_point_func)( mgaContextPtr, mgaVertex * ); + + + +/* Texture environment color + */ +#define RGB_ZERO(c) (((c) & 0xffffff) == 0x000000) +#define RGB_ONE(c) (((c) & 0xffffff) == 0xffffff) +#define ALPHA_ZERO(c) (((c) >> 24) == 0x00) +#define ALPHA_ONE(c) (((c) >> 24) == 0xff) +#define RGBA_EQUAL(c) ((c) == PACK_COLOR_8888( (c) & 0xff, (c) & 0xff, \ + (c) & 0xff, (c) & 0xff )) + +struct mga_texture_object_s; +struct mga_screen_private_s; + +#define G200_TEX_MAXLEVELS 5 +#define G400_TEX_MAXLEVELS 11 + +typedef struct mga_texture_object_s +{ + driTextureObject base; + + /* The G200 only has the ability to use 5 mipmap levels (including the + * base level). The G400 does not have this restriction, but it still + * only has 5 offset pointers in the hardware. The trick on the G400 is + * upto the first 4 offset pointers point to mipmap levels. The last + * offset pointer tells how large the preceeding mipmap is. This value is + * then used to determine where the remaining mipmaps are. + * + * For example, if the first offsets[0] through offsets[2] are used as + * pointers, then offset[3] will be the size of the mipmap pointed to by + * offsets[2]. So mipmap level 3 will be at (offsets[2]+offsets[3]). For + * each successive mipmap level, offsets[3] is divided by 4 and added to + * the previous address. So mipmap level 4 will be at + * (offsets[2]+offsets[3]+(offsets[3] / 4)). + * + * The last pointer is selected by setting TO_texorgoffsetsel in its + * pointer. In the previous example, offset[2] would have + * TO_texorgoffsetsel or'ed in before writing it to the hardware. + * + * In the current driver all of the mipmaps are packed together linearly + * with mipmap level 0. Therefore offsets[0] points to the base of the + * texture (and has TO_texorgoffsetsel or'ed in), and offsets[1] is the + * size of the base texture. + * + * There is a possible optimization available here. At times the driver + * may not be able to allocate a single block of memory for the complete + * texture without ejecting some other textures from memory. It may be + * possible to put some of the lower mipmap levels (i.e., the larger + * mipmaps) in memory separate from the higher levels. + * + * The implementation should be fairly obvious, but getting "right" would + * likely be non-trivial. A first allocation for the entire texture would + * be attempted with a flag that says "don't eject other textures." If + * that failed, an additional allocation would be attmpted for just the + * base map. The process would repeat with the block of lower maps. The + * tricky parts would be in detecting when some of the levels had been + * ejected from texture memory by other textures and preventing the + * 4th allocation (for all the smallest mipmap levels) from kicking out + * any of the first three. + * + * This array holds G400_TEX_MAXLEVELS pointers to remove an if-statement + * in a loop in mgaSetTexImages. Values past G200_TEX_MAXLEVELS are not + * used. + */ + GLuint offsets[G400_TEX_MAXLEVELS]; + + int texelBytes; + GLuint age; + + drm_mga_texture_regs_t setup; + + /* If one texture dimension wraps with GL_CLAMP and the other with + * GL_CLAMP_TO_EDGE, we have to fallback to software. We would also have + * to fallback for GL_CLAMP_TO_BORDER. + */ + GLboolean border_fallback; + /* Depending on multitxturing and environment color + * GL_BLEND may have to be a software fallback. + */ + GLboolean texenv_fallback; +} mgaTextureObject_t; + +struct mga_hw_state { + GLuint specen; + GLuint cull; + GLuint cull_dualtex; + GLuint stencil; + GLuint stencilctl; + GLuint stencil_enable; + GLuint zmode; + GLuint rop; + GLuint alpha_func; + GLuint alpha_func_enable; + GLuint blend_func; + GLuint blend_func_enable; + GLuint alpha_sel; +}; + +struct mga_context_t { + + GLcontext *glCtx; + unsigned int lastStamp; /* fullscreen breaks dpriv->laststamp, + * need to shadow it here. */ + + /* Hardware state management + */ + struct mga_hw_state hw; + + /* Bookkeeping for texturing + */ + unsigned nr_heaps; + driTexHeap * texture_heaps[ MGA_NR_TEX_HEAPS ]; + driTextureObject swapped; + + struct mga_texture_object_s *CurrentTexObj[2]; + + + /* Map GL texture units onto hardware. + */ + GLuint tmu_source[2]; + + int texture_depth; + + /* Manage fallbacks + */ + GLuint Fallback; + + /* Texture environment color. + */ + unsigned int envcolor[2]; + GLboolean fcol_used; + GLboolean force_dualtex; + + /* Rasterization state + */ + GLuint SetupNewInputs; + GLuint SetupIndex; + GLuint RenderIndex; + + GLuint hw_primitive; + GLenum raster_primitive; + GLenum render_primitive; + + GLubyte *verts; + GLint vertex_stride_shift; + GLuint vertex_format; + GLuint vertex_size; + + /* Fallback rasterization functions + */ + mga_point_func draw_point; + mga_line_func draw_line; + mga_tri_func draw_tri; + + + /* Manage driver and hardware state + */ + GLuint NewGLState; + GLuint dirty; + + drm_mga_context_regs_t setup; + + GLuint ClearColor; + GLuint ClearDepth; + GLuint poly_stipple; + GLfloat depth_scale; + + GLuint depth_clear_mask; + GLuint stencil_clear_mask; + GLuint hw_stencil; + GLuint haveHwStipple; + GLfloat hw_viewport[16]; + + /* Dma buffers + */ + drmBufPtr vertex_dma_buffer; + drmBufPtr iload_buffer; + + /* VBI + */ + GLuint vbl_seq; + GLuint vblank_flags; + + int64_t swap_ust; + int64_t swap_missed_ust; + + GLuint swap_count; + GLuint swap_missed_count; + + uint32_t last_frame_fence; + + /* Drawable, cliprect and scissor information + */ + int dirty_cliprects; /* which sets of cliprects are uptodate? */ + int draw_buffer; /* which buffer are we rendering to */ + unsigned int drawOffset; /* draw buffer address in space */ + int readOffset; + int drawX, drawY; /* origin of drawable in draw buffer */ + int lastX, lastY; /* detect DSTORG bug */ + GLuint numClipRects; /* cliprects for the draw buffer */ + drm_clip_rect_t *pClipRects; + drm_clip_rect_t draw_rect; + drm_clip_rect_t scissor_rect; + int scissor; + + drm_clip_rect_t tmp_boxes[2][MGA_NR_SAREA_CLIPRECTS]; + + + /* Texture aging and DMA based aging. + */ + unsigned int texAge[MGA_NR_TEX_HEAPS];/* texture LRU age */ + unsigned int dirtyAge; /* buffer age for synchronization */ + + GLuint primary_offset; + + /* Mirrors of some DRI state. + */ + drm_context_t hHWContext; + drm_hw_lock_t *driHwLock; + int driFd; + __DRIdrawablePrivate *driDrawable; + __DRIdrawablePrivate *driReadable; + + __DRIscreenPrivate *driScreen; + struct mga_screen_private_s *mgaScreen; + drm_mga_sarea_t *sarea; + + /* Configuration cache + */ + driOptionCache optionCache; +}; + +#define MGA_CONTEXT(ctx) ((mgaContextPtr)(ctx->DriverCtx)) + + + + +/* ================================================================ + * Debugging: + */ +#define DO_DEBUG 1 + +#if DO_DEBUG +extern int MGA_DEBUG; +#else +#define MGA_DEBUG 0 +#endif + +#define DEBUG_VERBOSE_MSG 0x01 +#define DEBUG_VERBOSE_DRI 0x02 +#define DEBUG_VERBOSE_IOCTL 0x04 +#define DEBUG_VERBOSE_TEXTURE 0x08 +#define DEBUG_VERBOSE_FALLBACK 0x10 + +static __inline__ GLuint mgaPackColor(GLuint cpp, + GLubyte r, GLubyte g, + GLubyte b, GLubyte a) +{ + switch (cpp) { + case 2: + return PACK_COLOR_565( r, g, b ); + case 4: + return PACK_COLOR_8888( a, r, g, b ); + default: + return 0; + } +} + + +/* + * Subpixel offsets for window coordinates: + */ +#define SUBPIXEL_X (-0.5F) +#define SUBPIXEL_Y (-0.5F + 0.125) + + +#define MGA_WA_TRIANGLES 0x18000000 +#define MGA_WA_TRISTRIP_T0 0x02010200 +#define MGA_WA_TRIFAN_T0 0x01000408 +#define MGA_WA_TRISTRIP_T0T1 0x02010400 +#define MGA_WA_TRIFAN_T0T1 0x01000810 + +#endif diff --git a/src/mgadd.c b/src/mgadd.c new file mode 100644 index 0000000..b1d5e0c --- /dev/null +++ b/src/mgadd.c @@ -0,0 +1,80 @@ +/* + * Copyright 2000-2001 VA Linux Systems, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ +/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgadd.c,v 1.14 2002/10/30 12:51:35 alanh Exp $ */ + + +#include "mtypes.h" +#include "framebuffer.h" + +#include "mm.h" +#include "mgacontext.h" +#include "mgadd.h" +#include "mgastate.h" +#include "mgaspan.h" +#include "mgatex.h" +#include "mgatris.h" +#include "mgavb.h" +#include "mga_xmesa.h" +#include "utils.h" + +#define DRIVER_DATE "20061030" + + +/*************************************** + * Mesa's Driver Functions + ***************************************/ + + +static const GLubyte *mgaGetString( GLcontext *ctx, GLenum name ) +{ + mgaContextPtr mmesa = MGA_CONTEXT( ctx ); + static char buffer[128]; + unsigned offset; + + switch ( name ) { + case GL_VENDOR: + return (GLubyte *) "VA Linux Systems Inc."; + + case GL_RENDERER: + offset = driGetRendererString( buffer, + MGA_IS_G400(mmesa) ? "G400" : + MGA_IS_G200(mmesa) ? "G200" : "MGA", + DRIVER_DATE, + mmesa->mgaScreen->agpMode ); + + return (GLubyte *)buffer; + + default: + return NULL; + } +} + + +void mgaInitDriverFuncs( struct dd_function_table *functions ) +{ + functions->GetString = mgaGetString; +} diff --git a/src/mgadd.h b/src/mgadd.h new file mode 100644 index 0000000..f98bfdc --- /dev/null +++ b/src/mgadd.h @@ -0,0 +1,36 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgadd.h,v 1.3 2002/10/30 12:51:35 alanh Exp $ */ +/* + * Copyright 2000-2001 VA Linux Systems, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#ifndef MGADD_INC +#define MGADD_INC + +#include "context.h" + +extern void mgaInitDriverFuncs( struct dd_function_table *functions ); + +#endif diff --git a/src/mgaioctl.c b/src/mgaioctl.c new file mode 100644 index 0000000..f8587fc --- /dev/null +++ b/src/mgaioctl.c @@ -0,0 +1,751 @@ +/* + * Copyright 2000-2001 VA Linux Systems, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file mgaioctl.c + * MGA IOCTL related wrapper functions. + * + * \author Keith Whitwell <keith@tungstengraphics.com> + * \author Gareth Hughes <gareth@valinux.com> + */ + +#include <errno.h> +#include "mtypes.h" +#include "macros.h" +#include "dd.h" +#include "swrast/swrast.h" + +#include "mm.h" +#include "drm.h" +#include "mga_drm.h" +#include "mgacontext.h" +#include "mgadd.h" +#include "mgastate.h" +#include "mgatex.h" +#include "mgavb.h" +#include "mgaioctl.h" +#include "mgatris.h" + +#include "vblank.h" + + +static int +mgaSetFence( mgaContextPtr mmesa, uint32_t * fence ) +{ + int ret = ENOSYS; + + if ( mmesa->driScreen->drmMinor >= 2 ) { + ret = drmCommandWriteRead( mmesa->driScreen->fd, DRM_MGA_SET_FENCE, + fence, sizeof( uint32_t )); + if (ret) { + fprintf(stderr, "drmMgaSetFence: %d\n", ret); + exit(1); + } + } + + return ret; +} + + +static int +mgaWaitFence( mgaContextPtr mmesa, uint32_t fence, uint32_t * curr_fence ) +{ + int ret = ENOSYS; + + if ( mmesa->driScreen->drmMinor >= 2 ) { + uint32_t temp = fence; + + ret = drmCommandWriteRead( mmesa->driScreen->fd, + DRM_MGA_WAIT_FENCE, + & temp, sizeof( uint32_t )); + if (ret) { + fprintf(stderr, "drmMgaSetFence: %d\n", ret); + exit(1); + } + + if ( curr_fence ) { + *curr_fence = temp; + } + } + + return ret; +} + + +static void mga_iload_dma_ioctl(mgaContextPtr mmesa, + unsigned long dest, + int length) +{ + drmBufPtr buf = mmesa->iload_buffer; + drm_mga_iload_t iload; + int ret, i; + + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "DRM_IOCTL_MGA_ILOAD idx %d dst %x length %d\n", + buf->idx, (int) dest, length); + + if ( (length & MGA_ILOAD_MASK) != 0 ) { + UNLOCK_HARDWARE( mmesa ); + fprintf( stderr, "%s: Invalid ILOAD datasize (%d), must be " + "multiple of %u.\n", __FUNCTION__, length, MGA_ILOAD_ALIGN ); + exit( 1 ); + } + + iload.idx = buf->idx; + iload.dstorg = dest; + iload.length = length; + + i = 0; + do { + ret = drmCommandWrite( mmesa->driFd, DRM_MGA_ILOAD, + &iload, sizeof(iload) ); + } while ( ret == -EBUSY && i++ < DRM_MGA_IDLE_RETRY ); + + if ( ret < 0 ) { + printf("send iload retcode = %d\n", ret); + exit(1); + } + + mmesa->iload_buffer = 0; + + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "finished iload dma put\n"); + +} + +drmBufPtr mga_get_buffer_ioctl( mgaContextPtr mmesa ) +{ + int idx = 0; + int size = 0; + drmDMAReq dma; + int retcode; + drmBufPtr buf; + + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "Getting dma buffer\n"); + + dma.context = mmesa->hHWContext; + dma.send_count = 0; + dma.send_list = NULL; + dma.send_sizes = NULL; + dma.flags = 0; + dma.request_count = 1; + dma.request_size = MGA_BUFFER_SIZE; + dma.request_list = &idx; + dma.request_sizes = &size; + dma.granted_count = 0; + + + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "drmDMA (get) ctx %d count %d size 0x%x\n", + dma.context, dma.request_count, + dma.request_size); + + while (1) { + retcode = drmDMA(mmesa->driFd, &dma); + + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "retcode %d sz %d idx %d count %d\n", + retcode, + dma.request_sizes[0], + dma.request_list[0], + dma.granted_count); + + if (retcode == 0 && + dma.request_sizes[0] && + dma.granted_count) + break; + + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "\n\nflush"); + + UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH | DRM_LOCK_QUIESCENT ); + } + + buf = &(mmesa->mgaScreen->bufs->list[idx]); + buf->used = 0; + + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, + "drmDMA (get) returns size[0] 0x%x idx[0] %d\n" + "dma_buffer now: buf idx: %d size: %d used: %d addr %p\n", + dma.request_sizes[0], dma.request_list[0], + buf->idx, buf->total, + buf->used, buf->address); + + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "finished getbuffer\n"); + + return buf; +} + + + + +static void +mgaClear( GLcontext *ctx, GLbitfield mask ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + __DRIdrawablePrivate *dPriv = mmesa->driDrawable; + GLuint flags = 0; + GLuint clear_color = mmesa->ClearColor; + GLuint clear_depth = 0; + GLuint color_mask = 0; + GLuint depth_mask = 0; + int ret; + int i; + static int nrclears; + drm_mga_clear_t clear; + GLint cx, cy, cw, ch; + + FLUSH_BATCH( mmesa ); + + if ( mask & BUFFER_BIT_FRONT_LEFT ) { + flags |= MGA_FRONT; + color_mask = mmesa->setup.plnwt; + mask &= ~BUFFER_BIT_FRONT_LEFT; + } + + if ( mask & BUFFER_BIT_BACK_LEFT ) { + flags |= MGA_BACK; + color_mask = mmesa->setup.plnwt; + mask &= ~BUFFER_BIT_BACK_LEFT; + } + + if ( (mask & BUFFER_BIT_DEPTH) && ctx->Depth.Mask ) { + flags |= MGA_DEPTH; + clear_depth = (mmesa->ClearDepth & mmesa->depth_clear_mask); + depth_mask |= mmesa->depth_clear_mask; + mask &= ~BUFFER_BIT_DEPTH; + } + + if ( (mask & BUFFER_BIT_STENCIL) && mmesa->hw_stencil ) { + flags |= MGA_DEPTH; + clear_depth |= (ctx->Stencil.Clear & mmesa->stencil_clear_mask); + depth_mask |= mmesa->stencil_clear_mask; + mask &= ~BUFFER_BIT_STENCIL; + } + + if ( flags ) { + LOCK_HARDWARE( mmesa ); + + /* compute region after locking: */ + cx = ctx->DrawBuffer->_Xmin; + cy = ctx->DrawBuffer->_Ymin; + cw = ctx->DrawBuffer->_Xmax - cx; + ch = ctx->DrawBuffer->_Ymax - cy; + + if ( mmesa->dirty_cliprects ) + mgaUpdateRects( mmesa, (MGA_FRONT | MGA_BACK) ); + + /* flip top to bottom */ + cy = dPriv->h-cy-ch; + cx += mmesa->drawX; + cy += mmesa->drawY; + + if ( MGA_DEBUG & DEBUG_VERBOSE_IOCTL ) + fprintf( stderr, "Clear, bufs %x nbox %d\n", + (int)flags, (int)mmesa->numClipRects ); + + for (i = 0 ; i < mmesa->numClipRects ; ) + { + int nr = MIN2(i + MGA_NR_SAREA_CLIPRECTS, mmesa->numClipRects); + drm_clip_rect_t *box = mmesa->pClipRects; + drm_clip_rect_t *b = mmesa->sarea->boxes; + int n = 0; + + if (cw != dPriv->w || ch != dPriv->h) { + /* clear subregion */ + for ( ; i < nr ; i++) { + GLint x = box[i].x1; + GLint y = box[i].y1; + GLint w = box[i].x2 - x; + GLint h = box[i].y2 - y; + + if (x < cx) w -= cx - x, x = cx; + if (y < cy) h -= cy - y, y = cy; + if (x + w > cx + cw) w = cx + cw - x; + if (y + h > cy + ch) h = cy + ch - y; + if (w <= 0) continue; + if (h <= 0) continue; + + b->x1 = x; + b->y1 = y; + b->x2 = x + w; + b->y2 = y + h; + b++; + n++; + } + } else { + /* clear whole window */ + for ( ; i < nr ; i++) { + *b++ = box[i]; + n++; + } + } + + + if ( MGA_DEBUG & DEBUG_VERBOSE_IOCTL ) + fprintf( stderr, + "DRM_IOCTL_MGA_CLEAR flag 0x%x color %x depth %x nbox %d\n", + flags, clear_color, clear_depth, mmesa->sarea->nbox ); + + mmesa->sarea->nbox = n; + + clear.flags = flags; + clear.clear_color = clear_color; + clear.clear_depth = clear_depth; + clear.color_mask = color_mask; + clear.depth_mask = depth_mask; + ret = drmCommandWrite( mmesa->driFd, DRM_MGA_CLEAR, + &clear, sizeof(clear)); + if ( ret ) { + fprintf( stderr, "send clear retcode = %d\n", ret ); + exit( 1 ); + } + if ( MGA_DEBUG & DEBUG_VERBOSE_IOCTL ) + fprintf( stderr, "finished clear %d\n", ++nrclears ); + } + + UNLOCK_HARDWARE( mmesa ); + mmesa->dirty |= MGA_UPLOAD_CLIPRECTS|MGA_UPLOAD_CONTEXT; + } + + if (mask) + _swrast_Clear( ctx, mask ); +} + + +/** + * Wait for the previous frame of rendering has completed. + * + * \param mmesa Hardware context pointer. + * + * \bug + * The loop in this function should have some sort of a timeout mechanism. + * + * \warning + * This routine used to assume that the hardware lock was held on entry. It + * now assumes that the lock is \b not held on entry. + */ + +static void mgaWaitForFrameCompletion( mgaContextPtr mmesa ) +{ + if ( mgaWaitFence( mmesa, mmesa->last_frame_fence, NULL ) == ENOSYS ) { + unsigned wait = 0; + GLuint last_frame; + GLuint last_wrap; + + + LOCK_HARDWARE( mmesa ); + last_frame = mmesa->sarea->last_frame.head; + last_wrap = mmesa->sarea->last_frame.wrap; + + /* The DMA routines in the kernel track a couple values in the SAREA + * that we use here. The number of times that the primary DMA buffer + * has "wrapped" around is tracked in last_wrap. In addition, the + * wrap count and the buffer position at the end of the last frame are + * stored in last_frame.wrap and last_frame.head. + * + * By comparing the wrap counts and the current DMA pointer value + * (read directly from the hardware) to last_frame.head, we can + * determine when the graphics processor has processed all of the + * commands for the last frame. + * + * In this case "last frame" means the frame of the *previous* swap- + * buffers call. This is done to prevent queuing a second buffer swap + * before the previous swap is executed. + */ + while ( 1 ) { + if ( last_wrap < mmesa->sarea->last_wrap || + ( last_wrap == mmesa->sarea->last_wrap && + last_frame <= (MGA_READ( MGAREG_PRIMADDRESS ) - + mmesa->primary_offset) ) ) { + break; + } + if ( 0 ) { + wait++; + fprintf( stderr, " last: head=0x%06x wrap=%d\n", + last_frame, last_wrap ); + fprintf( stderr, " head: head=0x%06lx wrap=%d\n", + (long)(MGA_READ( MGAREG_PRIMADDRESS ) - mmesa->primary_offset), + mmesa->sarea->last_wrap ); + } + UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH ); + + UNLOCK_HARDWARE( mmesa ); + DO_USLEEP( 1 ); + LOCK_HARDWARE( mmesa ); + } + if ( wait ) + fprintf( stderr, "\n" ); + + UNLOCK_HARDWARE( mmesa ); + } +} + + +/* + * Copy the back buffer to the front buffer. + */ +void mgaCopyBuffer( const __DRIdrawablePrivate *dPriv ) +{ + mgaContextPtr mmesa; + drm_clip_rect_t *pbox; + GLint nbox; + GLint ret; + GLint i; + GLboolean missed_target; + + + assert(dPriv); + assert(dPriv->driContextPriv); + assert(dPriv->driContextPriv->driverPrivate); + + mmesa = (mgaContextPtr) dPriv->driContextPriv->driverPrivate; + + FLUSH_BATCH( mmesa ); + + mgaWaitForFrameCompletion( mmesa ); + driWaitForVBlank( dPriv, & mmesa->vbl_seq, mmesa->vblank_flags, + & missed_target ); + if ( missed_target ) { + mmesa->swap_missed_count++; + (void) (*dri_interface->getUST)( & mmesa->swap_missed_ust ); + } + LOCK_HARDWARE( mmesa ); + + /* Use the frontbuffer cliprects + */ + if (mmesa->dirty_cliprects & MGA_FRONT) + mgaUpdateRects( mmesa, MGA_FRONT ); + + + pbox = dPriv->pClipRects; + nbox = dPriv->numClipRects; + + for (i = 0 ; i < nbox ; ) + { + int nr = MIN2(i + MGA_NR_SAREA_CLIPRECTS, dPriv->numClipRects); + drm_clip_rect_t *b = mmesa->sarea->boxes; + + mmesa->sarea->nbox = nr - i; + + for ( ; i < nr ; i++) + *b++ = pbox[i]; + + if (0) + fprintf(stderr, "DRM_IOCTL_MGA_SWAP\n"); + + ret = drmCommandNone( mmesa->driFd, DRM_MGA_SWAP ); + if ( ret ) { + printf("send swap retcode = %d\n", ret); + exit(1); + } + } + + (void) mgaSetFence( mmesa, & mmesa->last_frame_fence ); + UNLOCK_HARDWARE( mmesa ); + + mmesa->dirty |= MGA_UPLOAD_CLIPRECTS; + mmesa->swap_count++; + (void) (*dri_interface->getUST)( & mmesa->swap_ust ); +} + + +/** + * Implement the hardware-specific portion of \c glFinish. + * + * Flushes all pending commands to the hardware and wait for them to finish. + * + * \param ctx Context where the \c glFinish command was issued. + * + * \sa glFinish, mgaFlush, mgaFlushDMA + */ +static void mgaFinish( GLcontext *ctx ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + uint32_t fence; + + + LOCK_HARDWARE( mmesa ); + if ( mmesa->vertex_dma_buffer != NULL ) { + mgaFlushVerticesLocked( mmesa ); + } + + if ( mgaSetFence( mmesa, & fence ) == 0 ) { + UNLOCK_HARDWARE( mmesa ); + (void) mgaWaitFence( mmesa, fence, NULL ); + } + else { + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) { + fprintf(stderr, "mgaRegetLockQuiescent\n"); + } + + UPDATE_LOCK( mmesa, DRM_LOCK_QUIESCENT | DRM_LOCK_FLUSH ); + UNLOCK_HARDWARE( mmesa ); + } +} + + +/** + * Flush all commands upto at least a certain point to the hardware. + * + * \note + * The term "wait" in the name of this function is misleading. It doesn't + * actually wait for anything. It just makes sure that the commands have + * been flushed to the hardware. + * + * \warning + * As the name implies, this function assumes that the hardware lock is + * held on entry. + */ +void mgaWaitAgeLocked( mgaContextPtr mmesa, int age ) +{ + if (GET_DISPATCH_AGE(mmesa) < age) { + UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH ); + } +} + + +static GLboolean intersect_rect( drm_clip_rect_t *out, + const drm_clip_rect_t *a, + const drm_clip_rect_t *b ) +{ + *out = *a; + if (b->x1 > out->x1) out->x1 = b->x1; + if (b->y1 > out->y1) out->y1 = b->y1; + if (b->x2 < out->x2) out->x2 = b->x2; + if (b->y2 < out->y2) out->y2 = b->y2; + + return ((out->x1 < out->x2) && (out->y1 < out->y2)); +} + + + + +static void age_mmesa( mgaContextPtr mmesa, int age ) +{ + if (mmesa->CurrentTexObj[0]) mmesa->CurrentTexObj[0]->age = age; + if (mmesa->CurrentTexObj[1]) mmesa->CurrentTexObj[1]->age = age; +} + + +void mgaFlushVerticesLocked( mgaContextPtr mmesa ) +{ + drm_clip_rect_t *pbox = mmesa->pClipRects; + int nbox = mmesa->numClipRects; + drmBufPtr buffer = mmesa->vertex_dma_buffer; + drm_mga_vertex_t vertex; + int i; + + mmesa->vertex_dma_buffer = 0; + + if (!buffer) + return; + + if (mmesa->dirty_cliprects & mmesa->draw_buffer) + mgaUpdateRects( mmesa, mmesa->draw_buffer ); + + if (mmesa->dirty & ~MGA_UPLOAD_CLIPRECTS) + mgaEmitHwStateLocked( mmesa ); + + /* FIXME: Workaround bug in kernel module. + */ + mmesa->sarea->dirty |= MGA_UPLOAD_CONTEXT; + + if (!nbox) + buffer->used = 0; + + if (nbox >= MGA_NR_SAREA_CLIPRECTS) + mmesa->dirty |= MGA_UPLOAD_CLIPRECTS; + +#if 0 + if (!buffer->used || !(mmesa->dirty & MGA_UPLOAD_CLIPRECTS)) + { + if (nbox == 1) + mmesa->sarea->nbox = 0; + else + mmesa->sarea->nbox = nbox; + + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "Firing vertex -- case a nbox %d\n", nbox); + + vertex.idx = buffer->idx; + vertex.used = buffer->used; + vertex.discard = 1; + drmCommandWrite( mmesa->driFd, DRM_MGA_VERTEX, + &vertex, sizeof(drmMGAVertex) ); + + age_mmesa(mmesa, mmesa->sarea->last_enqueue); + } + else +#endif + { + for (i = 0 ; i < nbox ; ) + { + int nr = MIN2(i + MGA_NR_SAREA_CLIPRECTS, nbox); + drm_clip_rect_t *b = mmesa->sarea->boxes; + int discard = 0; + + if (mmesa->scissor) { + mmesa->sarea->nbox = 0; + + for ( ; i < nr ; i++) { + *b = pbox[i]; + if (intersect_rect(b, b, &mmesa->scissor_rect)) { + mmesa->sarea->nbox++; + b++; + } + } + + /* Culled? + */ + if (!mmesa->sarea->nbox) { + if (nr < nbox) continue; + buffer->used = 0; + } + } else { + mmesa->sarea->nbox = nr - i; + for ( ; i < nr ; i++) + *b++ = pbox[i]; + } + + /* Finished with the buffer? + */ + if (nr == nbox) + discard = 1; + + mmesa->sarea->dirty |= MGA_UPLOAD_CLIPRECTS; + + vertex.idx = buffer->idx; + vertex.used = buffer->used; + vertex.discard = discard; + drmCommandWrite( mmesa->driFd, DRM_MGA_VERTEX, + &vertex, sizeof(vertex) ); + + age_mmesa(mmesa, mmesa->sarea->last_enqueue); + } + } + + mmesa->dirty &= ~MGA_UPLOAD_CLIPRECTS; +} + +void mgaFlushVertices( mgaContextPtr mmesa ) +{ + LOCK_HARDWARE( mmesa ); + mgaFlushVerticesLocked( mmesa ); + UNLOCK_HARDWARE( mmesa ); +} + + +void mgaFireILoadLocked( mgaContextPtr mmesa, + GLuint offset, GLuint length ) +{ + if (!mmesa->iload_buffer) { + fprintf(stderr, "mgaFireILoad: no buffer\n"); + return; + } + + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "mgaFireILoad idx %d ofs 0x%x length %d\n", + mmesa->iload_buffer->idx, (int)offset, (int)length ); + + mga_iload_dma_ioctl( mmesa, offset, length ); +} + +void mgaGetILoadBufferLocked( mgaContextPtr mmesa ) +{ + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "mgaGetIloadBuffer (buffer now %p)\n", + (void *) mmesa->iload_buffer); + + mmesa->iload_buffer = mga_get_buffer_ioctl( mmesa ); +} + + +/** + * Implement the hardware-specific portion of \c glFlush. + * + * \param ctx Context to be flushed. + * + * \sa glFlush, mgaFinish, mgaFlushDMA + */ +static void mgaFlush( GLcontext *ctx ) +{ + mgaContextPtr mmesa = MGA_CONTEXT( ctx ); + + + LOCK_HARDWARE( mmesa ); + if ( mmesa->vertex_dma_buffer != NULL ) { + mgaFlushVerticesLocked( mmesa ); + } + + UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH ); + UNLOCK_HARDWARE( mmesa ); +} + + +int mgaFlushDMA( int fd, drmLockFlags flags ) +{ + drm_lock_t lock; + int ret, i = 0; + + memset( &lock, 0, sizeof(lock) ); + + lock.flags = flags & (DRM_LOCK_QUIESCENT | DRM_LOCK_FLUSH + | DRM_LOCK_FLUSH_ALL); + + do { + ret = drmCommandWrite( fd, DRM_MGA_FLUSH, &lock, sizeof(lock) ); + } while ( ret && errno == EBUSY && i++ < DRM_MGA_IDLE_RETRY ); + + if ( ret == 0 ) + return 0; + if ( errno != EBUSY ) + return -errno; + + if ( lock.flags & DRM_LOCK_QUIESCENT ) { + /* Only keep trying if we need quiescence. + */ + lock.flags &= ~(DRM_LOCK_FLUSH | DRM_LOCK_FLUSH_ALL); + + do { + ret = drmCommandWrite( fd, DRM_MGA_FLUSH, &lock, sizeof(lock) ); + } while ( ret && errno == EBUSY && i++ < DRM_MGA_IDLE_RETRY ); + } + + if ( ret == 0 ) { + return 0; + } else { + return -errno; + } +} + +void mgaInitIoctlFuncs( struct dd_function_table *functions ) +{ + functions->Clear = mgaClear; + functions->Flush = mgaFlush; + functions->Finish = mgaFinish; +} diff --git a/src/mgaioctl.h b/src/mgaioctl.h new file mode 100644 index 0000000..f3ae749 --- /dev/null +++ b/src/mgaioctl.h @@ -0,0 +1,111 @@ +/* + * Copyright 2000-2001 VA Linux Systems, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * Gareth Hughes <gareth@valinux.com> + */ +/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgaioctl.h,v 1.11 2002/10/30 12:51:36 alanh Exp $ */ + +#ifndef MGA_IOCTL_H +#define MGA_IOCTL_H + +#include "mgacontext.h" +#include "mga_xmesa.h" + +void mgaCopyBuffer( const __DRIdrawablePrivate *dPriv ); +void mgaWaitForVBlank( mgaContextPtr mmesa ); + +void mgaGetILoadBufferLocked( mgaContextPtr mmesa ); +void mgaFireILoadLocked( mgaContextPtr mmesa, + GLuint offset, GLuint length ); + +void mgaWaitAgeLocked( mgaContextPtr mmesa, int age ); + +void mgaFlushVertices( mgaContextPtr mmesa ); +void mgaFlushVerticesLocked( mgaContextPtr mmesa ); +int mgaFlushDMA( int fd, drmLockFlags flags ); + +void mgaInitIoctlFuncs( struct dd_function_table *functions ); + +#define FLUSH_BATCH(mmesa) do { \ + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) \ + fprintf(stderr, "FLUSH_BATCH in %s\n", __FUNCTION__); \ + if (mmesa->vertex_dma_buffer) mgaFlushVertices(mmesa); \ +} while (0) + +#define MGA_STATECHANGE(mmesa, flag) do { \ + FLUSH_BATCH(mmesa); \ + mmesa->dirty |= flag; \ +} while (0) + + +extern drmBufPtr mga_get_buffer_ioctl( mgaContextPtr mmesa ); + +static __inline +GLuint *mgaAllocDmaLow( mgaContextPtr mmesa, int bytes ) +{ + GLuint *head; + + /* If there is no DMA buffer currently allocated or the currently + * allocated DMA buffer doesn't have enough room left for this request, + * a new buffer will need to be allocated. + */ + if ( (mmesa->vertex_dma_buffer == NULL) + || ((mmesa->vertex_dma_buffer->used + bytes) + > mmesa->vertex_dma_buffer->total) ) { + LOCK_HARDWARE( mmesa ); + + /* In the case where the existing buffer does not have enough room, + * we need to flush it out to the hardware. + */ + if ( mmesa->vertex_dma_buffer != NULL ) { + mgaFlushVerticesLocked( mmesa ); + } + + mmesa->vertex_dma_buffer = mga_get_buffer_ioctl( mmesa ); + UNLOCK_HARDWARE( mmesa ); + } + + head = (GLuint *)((char *)mmesa->vertex_dma_buffer->address + + mmesa->vertex_dma_buffer->used); + + mmesa->vertex_dma_buffer->used += bytes; + return head; +} + + +#define UPDATE_LOCK( mmesa, flags ) \ +do { \ + GLint ret = mgaFlushDMA( mmesa->driFd, flags ); \ + if ( ret < 0 ) { \ + drmCommandNone( mmesa->driFd, DRM_MGA_RESET ); \ + UNLOCK_HARDWARE( mmesa ); \ + fprintf( stderr, "%s: flush return = %s (%d), flags = 0x%08x\n", \ + __FUNCTION__, strerror( -ret ), -ret, \ + (unsigned)(flags) ); \ + exit( 1 ); \ + } \ +} while (0) + +#endif diff --git a/src/mgapixel.c b/src/mgapixel.c new file mode 100644 index 0000000..2b9da8c --- /dev/null +++ b/src/mgapixel.c @@ -0,0 +1,656 @@ +/* + * Copyright 2000 Compaq Computer Inc. and VA Linux Systems, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file mgapixel.c + * Implement framebuffer pixel operations for MGA. + * + * \todo + * Someday the accelerated \c glReadPixels and \c glDrawPixels paths need to + * be resurrected. They are currently ifdef'ed out because they don't seem + * to work and they only get activated some very rare circumstances. + * + * \author Keith Whitwell <keith@tungstengraphics.com> + * \author Gareth Hughes <gareth@valinux.com> + */ +/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgapixel.c,v 1.9 2002/11/05 17:46:08 tsi Exp $ */ + +#include "mtypes.h" +#include "macros.h" +#include "mgadd.h" +#include "mgacontext.h" +#include "mgaioctl.h" +#include "mgapixel.h" +#include "mgastate.h" + +#include "swrast/swrast.h" +#include "imports.h" + +#if 0 +#define IS_AGP_MEM( mmesa, p ) \ + ((unsigned long)mmesa->mgaScreen->buffers.map <= ((unsigned long)p) && \ + (unsigned long)mmesa->mgaScreen->buffers.map + \ + (unsigned long)mmesa->mgaScreen->buffers.size > ((unsigned long)p)) +#define AGP_OFFSET( mmesa, p ) \ + (((unsigned long)p) - (unsigned long)mmesa->mgaScreen->buffers.map) + + +#if defined(MESA_packed_depth_stencil) +static GLboolean +check_depth_stencil_24_8( const GLcontext *ctx, GLenum type, + const struct gl_pixelstore_attrib *packing, + const void *pixels, GLint sz, + GLint pitch ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + + return ( type == GL_UNSIGNED_INT_24_8_MESA && + ctx->Visual->DepthBits == 24 && + ctx->Visual->StencilBits == 8 && + mmesa->mgaScreen->cpp == 4 && + mmesa->hw_stencil && + !ctx->Pixel.IndexShift && + !ctx->Pixel.IndexOffset && + !ctx->Pixel.MapStencilFlag && + ctx->Pixel.DepthBias == 0.0 && + ctx->Pixel.DepthScale == 1.0 && + !packing->SwapBytes && + pitch % 32 == 0 && + pitch < 4096 ); +} +#endif + + +static GLboolean +check_depth( const GLcontext *ctx, GLenum type, + const struct gl_pixelstore_attrib *packing, + const void *pixels, GLint sz, GLint pitch ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + + if ( IS_AGP_MEM( mmesa, pixels ) && + !( ( type == GL_UNSIGNED_INT && mmesa->mgaScreen->cpp == 4 ) || + ( type == GL_UNSIGNED_SHORT && mmesa->mgaScreen->cpp == 2 ) ) ) + return GL_FALSE; + + return ( ctx->Pixel.DepthBias == 0.0 && + ctx->Pixel.DepthScale == 1.0 && + !packing->SwapBytes && + pitch % 32 == 0 && + pitch < 4096 ); +} + + +static GLboolean +check_color( const GLcontext *ctx, GLenum type, GLenum format, + const struct gl_pixelstore_attrib *packing, + const void *pixels, GLint sz, GLint pitch ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + GLuint cpp = mmesa->mgaScreen->cpp; + + /* Can't do conversions on agp reads/draws. + */ + if ( IS_AGP_MEM( mmesa, pixels ) && + !( pitch % 32 == 0 && pitch < 4096 && + ( ( type == GL_UNSIGNED_BYTE && + cpp == 4 && format == GL_BGRA ) || + ( type == GL_UNSIGNED_INT_8_8_8_8 && + cpp == 4 && format == GL_BGRA ) || + ( type == GL_UNSIGNED_SHORT_5_6_5_REV && + cpp == 2 && format == GL_RGB ) ) ) ) + return GL_FALSE; + + return (!ctx->_ImageTransferState && + !packing->SwapBytes && + !packing->LsbFirst); +} + +static GLboolean +check_color_per_fragment_ops( const GLcontext *ctx ) +{ + return (!( ctx->Color.AlphaEnabled || + ctx->Depth.Test || + ctx->Fog.Enabled || + ctx->Scissor.Enabled || + ctx->Stencil.Enabled || + !ctx->Color.ColorMask[0] || + !ctx->Color.ColorMask[1] || + !ctx->Color.ColorMask[2] || + !ctx->Color.ColorMask[3] || + ctx->Color.ColorLogicOpEnabled || + ctx->Texture._EnabledUnits + ) && + ctx->Current.RasterPosValid && + ctx->Pixel.ZoomX == 1.0F && + (ctx->Pixel.ZoomY == 1.0F || ctx->Pixel.ZoomY == -1.0F)); +} + +static GLboolean +check_depth_per_fragment_ops( const GLcontext *ctx ) +{ + return ( ctx->Current.RasterPosValid && + ctx->Color.ColorMask[RCOMP] == 0 && + ctx->Color.ColorMask[BCOMP] == 0 && + ctx->Color.ColorMask[GCOMP] == 0 && + ctx->Color.ColorMask[ACOMP] == 0 && + ctx->Pixel.ZoomX == 1.0F && + ( ctx->Pixel.ZoomY == 1.0F || ctx->Pixel.ZoomY == -1.0F ) ); +} + +/* In addition to the requirements for depth: + */ +#if defined(MESA_packed_depth_stencil) +static GLboolean +check_stencil_per_fragment_ops( const GLcontext *ctx ) +{ + return ( !ctx->Pixel.IndexShift && + !ctx->Pixel.IndexOffset ); +} +#endif + + +static GLboolean +clip_pixelrect( const GLcontext *ctx, + const GLframebuffer *buffer, + GLint *x, GLint *y, + GLsizei *width, GLsizei *height, + GLint *skipPixels, GLint *skipRows, + GLint *size ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + + *width = MIN2(*width, MAX_WIDTH); /* redundant? */ + + /* left clipping */ + if (*x < buffer->_Xmin) { + *skipPixels += (buffer->_Xmin - *x); + *width -= (buffer->_Xmin - *x); + *x = buffer->_Xmin; + } + + /* right clipping */ + if (*x + *width > buffer->_Xmax) + *width -= (*x + *width - buffer->_Xmax - 1); + + if (*width <= 0) + return GL_FALSE; + + /* bottom clipping */ + if (*y < buffer->_Ymin) { + *skipRows += (buffer->_Ymin - *y); + *height -= (buffer->_Ymin - *y); + *y = buffer->_Ymin; + } + + /* top clipping */ + if (*y + *height > buffer->_Ymax) + *height -= (*y + *height - buffer->_Ymax - 1); + + if (*height <= 0) + return GL_FALSE; + + *size = ((*y + *height - 1) * mmesa->mgaScreen->frontPitch + + (*x + *width - 1) * mmesa->mgaScreen->cpp); + + return GL_TRUE; +} + +static GLboolean +mgaTryReadPixels( GLcontext *ctx, + GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *pack, + GLvoid *pixels ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + GLint size, skipPixels, skipRows; + GLint pitch = pack->RowLength ? pack->RowLength : width; + GLboolean ok; + + GLuint planemask; + GLuint source; +#if 0 + drmMGABlit blit; + GLuint dest; + GLint source_pitch, dest_pitch; + GLint delta_sx, delta_sy; + GLint delta_dx, delta_dy; + GLint blit_height, ydir; +#endif + + if (!clip_pixelrect(ctx, ctx->ReadBuffer, + &x, &y, &width, &height, + &skipPixels, &skipRows, &size)) { + return GL_TRUE; + } + + /* Only accelerate reading to agp buffers. + */ + if ( !IS_AGP_MEM(mmesa, (char *)pixels) || + !IS_AGP_MEM(mmesa, (char *)pixels + size) ) + return GL_FALSE; + + switch (format) { +#if defined(MESA_packed_depth_stencil) + case GL_DEPTH_STENCIL_MESA: + ok = check_depth_stencil_24_8(ctx, type, pack, pixels, size, pitch); + planemask = ~0; + source = mmesa->mgaScreen->depthOffset; + break; +#endif + + case GL_DEPTH_COMPONENT: + ok = check_depth(ctx, type, pack, pixels, size, pitch); + + /* Can't accelerate at this depth -- planemask does the wrong + * thing; it doesn't clear the low order bits in the + * destination, instead it leaves them untouched. + * + * Could get the acclerator to solid fill the destination with + * zeros first... Or get the cpu to do it... + */ + if (ctx->Visual.depthBits == 24) + return GL_FALSE; + + planemask = ~0; + source = mmesa->mgaScreen->depthOffset; + break; + + case GL_RGB: + case GL_BGRA: + ok = check_color(ctx, type, format, pack, pixels, size, pitch); + planemask = ~0; + source = (mmesa->draw_buffer == MGA_FRONT ? + mmesa->mgaScreen->frontOffset : + mmesa->mgaScreen->backOffset); + break; + + default: + return GL_FALSE; + } + + if (!ok) { + return GL_FALSE; + } + + + LOCK_HARDWARE( mmesa ); + +#if 0 + { + __DRIdrawablePrivate *dPriv = mmesa->driDrawable; + int nbox, retcode, i; + + UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH | DRM_LOCK_QUIESCENT ); + + if (mmesa->dirty_cliprects & MGA_FRONT) + mgaUpdateRects( mmesa, MGA_FRONT ); + + nbox = dPriv->numClipRects; + + y = dPriv->h - y - height; + x += mmesa->drawX; + y += mmesa->drawY; + + dest = ((mmesa->mgaScreen->agp.handle + AGP_OFFSET(mmesa, pixels)) | + DO_dstmap_sys | DO_dstacc_agp); + source_pitch = mmesa->mgaScreen->frontPitch / mmesa->mgaScreen->cpp; + dest_pitch = pitch; + delta_sx = 0; + delta_sy = 0; + delta_dx = -x; + delta_dy = -y; + blit_height = 2*y + height; + ydir = -1; + + if (0) fprintf(stderr, "XX doing readpixel blit src_pitch %d dst_pitch %d\n", + source_pitch, dest_pitch); + + + + for (i = 0 ; i < nbox ; ) + { + int nr = MIN2(i + MGA_NR_SAREA_CLIPRECTS, dPriv->numClipRects); + drm_clip_rect_t *box = dPriv->pClipRects; + drm_clip_rect_t *b = mmesa->sarea->boxes; + int n = 0; + + for ( ; i < nr ; i++) { + GLint bx = box[i].x1; + GLint by = box[i].y1; + GLint bw = box[i].x2 - bx; + GLint bh = box[i].y2 - by; + + if (bx < x) bw -= x - bx, bx = x; + if (by < y) bh -= y - by, by = y; + if (bx + bw > x + width) bw = x + width - bx; + if (by + bh > y + height) bh = y + height - by; + if (bw <= 0) continue; + if (bh <= 0) continue; + + b->x1 = bx; + b->y1 = by; + b->x2 = bx + bw; + b->y2 = by + bh; + b++; + n++; + } + + mmesa->sarea->nbox = n; + + if (n && (retcode = drmCommandWrite( mmesa->driFd, DRM_MGA_BLIT, + &blit, sizeof(drmMGABlit)))) { + fprintf(stderr, "blit ioctl failed, retcode = %d\n", retcode); + UNLOCK_HARDWARE( mmesa ); + exit(1); + } + } + + UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH | DRM_LOCK_QUIESCENT ); + } +#endif + + UNLOCK_HARDWARE( mmesa ); + + return GL_TRUE; +} + +static void +mgaDDReadPixels( GLcontext *ctx, + GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *pack, + GLvoid *pixels ) +{ + if (!mgaTryReadPixels( ctx, x, y, width, height, format, type, pack, pixels)) + _swrast_ReadPixels( ctx, x, y, width, height, format, type, pack, pixels); +} + + + + +static void do_draw_pix( GLcontext *ctx, + GLint x, GLint y, GLsizei width, GLsizei height, + GLint pitch, + const void *pixels, + GLuint dest, GLuint planemask) +{ +#if 0 + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + drmMGABlit blit; + __DRIdrawablePrivate *dPriv = mmesa->driDrawable; + drm_clip_rect_t pbox = dPriv->pClipRects; + int nbox = dPriv->numClipRects; + int retcode, i; + + y = dPriv->h - y - height; + x += mmesa->drawX; + y += mmesa->drawY; + + blit.dest = dest; + blit.planemask = planemask; + blit.source = ((mmesa->mgaScreen->agp.handle + AGP_OFFSET(mmesa, pixels)) + | SO_srcmap_sys | SO_srcacc_agp); + blit.dest_pitch = mmesa->mgaScreen->frontPitch / mmesa->mgaScreen->cpp; + blit.source_pitch = pitch; + blit.delta_sx = -x; + blit.delta_sy = -y; + blit.delta_dx = 0; + blit.delta_dy = 0; + if (ctx->Pixel.ZoomY == -1) { + blit.height = height; + blit.ydir = 1; + } else { + blit.height = height; + blit.ydir = -1; + } + + if (0) fprintf(stderr, + "doing drawpixel blit src_pitch %d dst_pitch %d\n", + blit.source_pitch, blit.dest_pitch); + + for (i = 0 ; i < nbox ; ) + { + int nr = MIN2(i + MGA_NR_SAREA_CLIPRECTS, dPriv->numClipRects); + drm_clip_rect_t *box = mmesa->pClipRects; + drm_clip_rect_t *b = mmesa->sarea->boxes; + int n = 0; + + for ( ; i < nr ; i++) { + GLint bx = box[i].x1; + GLint by = box[i].y1; + GLint bw = box[i].x2 - bx; + GLint bh = box[i].y2 - by; + + if (bx < x) bw -= x - bx, bx = x; + if (by < y) bh -= y - by, by = y; + if (bx + bw > x + width) bw = x + width - bx; + if (by + bh > y + height) bh = y + height - by; + if (bw <= 0) continue; + if (bh <= 0) continue; + + b->x1 = bx; + b->y1 = by; + b->x2 = bx + bw; + b->y2 = by + bh; + b++; + n++; + } + + mmesa->sarea->nbox = n; + + if (n && (retcode = drmCommandWrite( mmesa->driFd, DRM_MGA_BLIT, + &blit, sizeof(drmMGABlit)))) { + fprintf(stderr, "blit ioctl failed, retcode = %d\n", retcode); + UNLOCK_HARDWARE( mmesa ); + exit(1); + } + } +#endif +} + + + + +static GLboolean +mgaTryDrawPixels( GLcontext *ctx, + GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *unpack, + const GLvoid *pixels ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + GLint size, skipPixels, skipRows; + GLint pitch = unpack->RowLength ? unpack->RowLength : width; + GLuint dest, planemask; + GLuint cpp = mmesa->mgaScreen->cpp; + + if (!clip_pixelrect(ctx, ctx->DrawBuffer, + &x, &y, &width, &height, + &skipPixels, &skipRows, &size)) { + return GL_TRUE; + } + + + switch (format) { +#if defined(MESA_packed_depth_stencil) + case GL_DEPTH_STENCIL_MESA: + dest = mmesa->mgaScreen->depthOffset; + planemask = ~0; + if (!check_depth_stencil_24_8(ctx, type, unpack, pixels, size, pitch) || + !check_depth_per_fragment_ops(ctx) || + !check_stencil_per_fragment_ops(ctx)) + return GL_FALSE; + break; +#endif + + case GL_DEPTH_COMPONENT: + dest = mmesa->mgaScreen->depthOffset; + + if (ctx->Visual.depthBits == 24) + planemask = ~0xff; + else + planemask = ~0; + + if (!check_depth(ctx, type, unpack, pixels, size, pitch) || + !check_depth_per_fragment_ops(ctx)) + return GL_FALSE; + break; + + case GL_RGB: + case GL_BGRA: + dest = (mmesa->draw_buffer == MGA_FRONT ? + mmesa->mgaScreen->frontOffset : + mmesa->mgaScreen->backOffset); + + planemask = mgaPackColor(cpp, + ctx->Color.ColorMask[RCOMP], + ctx->Color.ColorMask[GCOMP], + ctx->Color.ColorMask[BCOMP], + ctx->Color.ColorMask[ACOMP]); + + if (cpp == 2) + planemask |= planemask << 16; + + if (!check_color(ctx, type, format, unpack, pixels, size, pitch)) { + return GL_FALSE; + } + if (!check_color_per_fragment_ops(ctx)) { + return GL_FALSE; + } + break; + + default: + return GL_FALSE; + } + + LOCK_HARDWARE_QUIESCENT( mmesa ); + + if (mmesa->dirty_cliprects & MGA_FRONT) + mgaUpdateRects( mmesa, MGA_FRONT ); + + if ( IS_AGP_MEM(mmesa, (char *)pixels) && + IS_AGP_MEM(mmesa, (char *)pixels + size) ) + { + do_draw_pix( ctx, x, y, width, height, pitch, pixels, + dest, planemask ); + UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH | DRM_LOCK_QUIESCENT ); + } + else + { + /* Pixels is in regular memory -- get dma buffers and perform + * upload through them. + */ +/* drmBufPtr buf = mgaGetBufferLocked(mmesa); */ + GLuint bufferpitch = (width*cpp+31)&~31; + + char *address = 0; /* mmesa->mgaScreen->agp.map; */ + + do { +/* GLuint rows = MIN2( height, MGA_DMA_BUF_SZ / bufferpitch ); */ + GLuint rows = height; + + + if (0) fprintf(stderr, "trying to upload %d rows (pitch %d)\n", + rows, bufferpitch); + + /* The texture conversion code is so slow that there is only + * negligble speedup when the buffers/images don't exactly + * match: + */ +#if 0 + if (cpp == 2) { + if (!_mesa_convert_texsubimage2d( MESA_FORMAT_RGB565, + 0, 0, width, rows, + bufferpitch, format, type, + unpack, pixels, address )) { +/* mgaReleaseBufLocked( mmesa, buf ); */ + UNLOCK_HARDWARE(mmesa); + return GL_FALSE; + } + } else { + if (!_mesa_convert_texsubimage2d( MESA_FORMAT_ARGB8888, + 0, 0, width, rows, + bufferpitch, format, type, + unpack, pixels, address )) { +/* mgaReleaseBufLocked( mmesa, buf ); */ + UNLOCK_HARDWARE(mmesa); + return GL_FALSE; + } + } +#else + MEMCPY( address, pixels, rows*bufferpitch ); +#endif + + do_draw_pix( ctx, x, y, width, rows, + bufferpitch/cpp, address, dest, planemask ); + + /* Fix me -- use multiple buffers to avoid flush. + */ + UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH | DRM_LOCK_QUIESCENT ); + + pixels = (void *)((char *) pixels + rows * pitch); + height -= rows; + y += rows; + } while (height); + +/* mgaReleaseBufLocked( mmesa, buf ); */ + } + + UNLOCK_HARDWARE( mmesa ); + mmesa->dirty |= MGA_UPLOAD_CLIPRECTS; + + return GL_TRUE; +} + +static void +mgaDDDrawPixels( GLcontext *ctx, + GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *unpack, + const GLvoid *pixels ) +{ + if (!mgaTryDrawPixels( ctx, x, y, width, height, format, type, + unpack, pixels )) + _swrast_DrawPixels( ctx, x, y, width, height, format, type, + unpack, pixels ); +} +#endif + + +/* Stub functions - not a real allocator, always returns pointer to + * the same block of agp space which isn't used for anything else at + * present. + */ +void mgaDDInitPixelFuncs( GLcontext *ctx ) +{ +#if 0 + /* evidently, these functions don't always work */ + if (getenv("MGA_BLIT_PIXELS")) { + ctx->Driver.ReadPixels = mgaDDReadPixels; /* requires agp dest */ + ctx->Driver.DrawPixels = mgaDDDrawPixels; /* works with agp/normal mem */ + } +#endif +} diff --git a/src/mgapixel.h b/src/mgapixel.h new file mode 100644 index 0000000..c44fd76 --- /dev/null +++ b/src/mgapixel.h @@ -0,0 +1,36 @@ +/* + * Copyright 2000-2001 Compaq Computer Inc. VA Linux Systems, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ +/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgapixel.h,v 1.5 2002/10/30 12:51:36 alanh Exp $ */ + +#ifndef MGA_PIXELS_H +#define MGA_PIXELS_H + +#include "mtypes.h" + +extern void mgaDDInitPixelFuncs( GLcontext *ctx ); + +#endif diff --git a/src/mgaregs.h b/src/mgaregs.h new file mode 100644 index 0000000..e1291ca --- /dev/null +++ b/src/mgaregs.h @@ -0,0 +1,1395 @@ +/* author: stephen crowley, crow@debian.org */ + +/* + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * STEPHEN CROWLEY, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgaregs.h,v 1.6 2003/01/12 03:55:46 tsi Exp $ */ + +#ifndef _MGAREGS_H_ +#define _MGAREGS_H_ + +/*************** (START) AUTOMATICLY GENERATED REGISTER FILE *****************/ +/* + * Generated on Wed Jan 26 13:44:46 MST 2000 + */ + + + +/* + * Power Graphic Mode Memory Space Registers + */ + +#define MGAREG_MGA_EXEC 0x0100 +#define MGAREG_AGP_PLL 0x1e4c + +# define AGP_PLL_agp2xpllen_MASK 0xfffffffe /* bit 0 */ +# define AGP_PLL_agp2xpllen_disable 0x0 +# define AGP_PLL_agp2xpllen_enable 0x1 + +#define MGAREG_CFG_OR 0x1e4c + +# define CFG_OR_comp_or_MASK 0xfffffff7 /* bit 3 */ +# define CFG_OR_comp_or_disable 0x0 +# define CFG_OR_comp_or_enable 0x8 +# define CFG_OR_compfreq_MASK 0xffffff0f /* bits 4-7 */ +# define CFG_OR_compfreq_SHIFT 4 +# define CFG_OR_comporup_MASK 0xfffff0ff /* bits 8-11 */ +# define CFG_OR_comporup_SHIFT 8 +# define CFG_OR_compordn_MASK 0xffff0fff /* bits 12-15 */ +# define CFG_OR_compordn_SHIFT 12 +# define CFG_OR_e2pq_MASK 0xfffeffff /* bit 16 */ +# define CFG_OR_e2pq_disable 0x0 +# define CFG_OR_e2pq_enable 0x10000 +# define CFG_OR_e2pqbypcsn_MASK 0xfffdffff /* bit 17 */ +# define CFG_OR_e2pqbypcsn_disable 0x0 +# define CFG_OR_e2pqbypcsn_enable 0x20000 +# define CFG_OR_e2pqbypd_MASK 0xfffbffff /* bit 18 */ +# define CFG_OR_e2pqbypd_disable 0x0 +# define CFG_OR_e2pqbypd_enable 0x40000 +# define CFG_OR_e2pbypclk_MASK 0xfff7ffff /* bit 19 */ +# define CFG_OR_e2pbypclk_disable 0x0 +# define CFG_OR_e2pbypclk_enable 0x80000 +# define CFG_OR_e2pbyp_MASK 0xffefffff /* bit 20 */ +# define CFG_OR_e2pbyp_disable 0x0 +# define CFG_OR_e2pbyp_enable 0x100000 +# define CFG_OR_rate_cap_or_MASK 0xff1fffff /* bits 21-23 */ +# define CFG_OR_rate_cap_or_SHIFT 21 +# define CFG_OR_rq_or_MASK 0xe0ffffff /* bits 24-28 */ +# define CFG_OR_rq_or_SHIFT 24 + +#define MGAREG_ALPHACTRL 0x2c7c + +# define AC_src_MASK 0xfffffff0 /* bits 0-3 */ +# define AC_src_zero 0x0 /* val 0, shift 0 */ +# define AC_src_one 0x1 /* val 1, shift 0 */ +# define AC_src_dst_color 0x2 /* val 2, shift 0 */ +# define AC_src_om_dst_color 0x3 /* val 3, shift 0 */ +# define AC_src_src_alpha 0x4 /* val 4, shift 0 */ +# define AC_src_om_src_alpha 0x5 /* val 5, shift 0 */ +# define AC_src_dst_alpha 0x6 /* val 6, shift 0 */ +# define AC_src_om_dst_alpha 0x7 /* val 7, shift 0 */ +# define AC_src_src_alpha_sat 0x8 /* val 8, shift 0 */ +# define AC_dst_MASK 0xffffff0f /* bits 4-7 */ +# define AC_dst_zero 0x0 /* val 0, shift 4 */ +# define AC_dst_one 0x10 /* val 1, shift 4 */ +# define AC_dst_src_color 0x20 /* val 2, shift 4 */ +# define AC_dst_om_src_color 0x30 /* val 3, shift 4 */ +# define AC_dst_src_alpha 0x40 /* val 4, shift 4 */ +# define AC_dst_om_src_alpha 0x50 /* val 5, shift 4 */ +# define AC_dst_dst_alpha 0x60 /* val 6, shift 4 */ +# define AC_dst_om_dst_alpha 0x70 /* val 7, shift 4 */ +# define AC_amode_MASK 0xfffffcff /* bits 8-9 */ +# define AC_amode_FCOL 0x0 /* val 0, shift 8 */ +# define AC_amode_alpha_channel 0x100 /* val 1, shift 8 */ +# define AC_amode_video_alpha 0x200 /* val 2, shift 8 */ +# define AC_amode_RSVD 0x300 /* val 3, shift 8 */ +# define AC_astipple_MASK 0xfffff7ff /* bit 11 */ +# define AC_astipple_disable 0x0 +# define AC_astipple_enable 0x800 +# define AC_aten_MASK 0xffffefff /* bit 12 */ +# define AC_aten_disable 0x0 +# define AC_aten_enable 0x1000 +# define AC_atmode_MASK 0xffff1fff /* bits 13-15 */ +# define AC_atmode_noacmp 0x0 /* val 0, shift 13 */ +# define AC_atmode_ae 0x4000 /* val 2, shift 13 */ +# define AC_atmode_ane 0x6000 /* val 3, shift 13 */ +# define AC_atmode_alt 0x8000 /* val 4, shift 13 */ +# define AC_atmode_alte 0xa000 /* val 5, shift 13 */ +# define AC_atmode_agt 0xc000 /* val 6, shift 13 */ +# define AC_atmode_agte 0xe000 /* val 7, shift 13 */ +# define AC_atref_MASK 0xff00ffff /* bits 16-23 */ +# define AC_atref_SHIFT 16 +# define AC_alphasel_MASK 0xfcffffff /* bits 24-25 */ +# define AC_alphasel_fromtex 0x0 /* val 0, shift 24 */ +# define AC_alphasel_diffused 0x1000000 /* val 1, shift 24 */ +# define AC_alphasel_modulated 0x2000000 /* val 2, shift 24 */ +# define AC_alphasel_trans 0x3000000 /* val 3, shift 24 */ + +#define MGAREG_ALPHASTART 0x2c70 +#define MGAREG_ALPHAXINC 0x2c74 +#define MGAREG_ALPHAYINC 0x2c78 +#define MGAREG_AR0 0x1c60 + +# define AR0_ar0_MASK 0xfffc0000 /* bits 0-17 */ +# define AR0_ar0_SHIFT 0 + +#define MGAREG_AR1 0x1c64 + +# define AR1_ar1_MASK 0xff000000 /* bits 0-23 */ +# define AR1_ar1_SHIFT 0 + +#define MGAREG_AR2 0x1c68 + +# define AR2_ar2_MASK 0xfffc0000 /* bits 0-17 */ +# define AR2_ar2_SHIFT 0 + +#define MGAREG_AR3 0x1c6c + +# define AR3_ar3_MASK 0xff000000 /* bits 0-23 */ +# define AR3_ar3_SHIFT 0 +# define AR3_spage_MASK 0xf8ffffff /* bits 24-26 */ +# define AR3_spage_SHIFT 24 + +#define MGAREG_AR4 0x1c70 + +# define AR4_ar4_MASK 0xfffc0000 /* bits 0-17 */ +# define AR4_ar4_SHIFT 0 + +#define MGAREG_AR5 0x1c74 + +# define AR5_ar5_MASK 0xfffc0000 /* bits 0-17 */ +# define AR5_ar5_SHIFT 0 + +#define MGAREG_AR6 0x1c78 + +# define AR6_ar6_MASK 0xfffc0000 /* bits 0-17 */ +# define AR6_ar6_SHIFT 0 + +#define MGAREG_BCOL 0x1c20 +#define MGAREG_BESA1CORG 0x3d10 +#define MGAREG_BESA1ORG 0x3d00 +#define MGAREG_BESA2CORG 0x3d14 +#define MGAREG_BESA2ORG 0x3d04 +#define MGAREG_BESB1CORG 0x3d18 +#define MGAREG_BESB1ORG 0x3d08 +#define MGAREG_BESB2CORG 0x3d1c +#define MGAREG_BESB2ORG 0x3d0c +#define MGAREG_BESCTL 0x3d20 + +# define BC_besen_MASK 0xfffffffe /* bit 0 */ +# define BC_besen_disable 0x0 +# define BC_besen_enable 0x1 +# define BC_besv1srcstp_MASK 0xffffffbf /* bit 6 */ +# define BC_besv1srcstp_even 0x0 +# define BC_besv1srcstp_odd 0x40 +# define BC_besv2srcstp_MASK 0xfffffeff /* bit 8 */ +# define BC_besv2srcstp_disable 0x0 +# define BC_besv2srcstp_enable 0x100 +# define BC_beshfen_MASK 0xfffffbff /* bit 10 */ +# define BC_beshfen_disable 0x0 +# define BC_beshfen_enable 0x400 +# define BC_besvfen_MASK 0xfffff7ff /* bit 11 */ +# define BC_besvfen_disable 0x0 +# define BC_besvfen_enable 0x800 +# define BC_beshfixc_MASK 0xffffefff /* bit 12 */ +# define BC_beshfixc_weight 0x0 +# define BC_beshfixc_coeff 0x1000 +# define BC_bescups_MASK 0xfffeffff /* bit 16 */ +# define BC_bescups_disable 0x0 +# define BC_bescups_enable 0x10000 +# define BC_bes420pl_MASK 0xfffdffff /* bit 17 */ +# define BC_bes420pl_422 0x0 +# define BC_bes420pl_420 0x20000 +# define BC_besdith_MASK 0xfffbffff /* bit 18 */ +# define BC_besdith_disable 0x0 +# define BC_besdith_enable 0x40000 +# define BC_beshmir_MASK 0xfff7ffff /* bit 19 */ +# define BC_beshmir_disable 0x0 +# define BC_beshmir_enable 0x80000 +# define BC_besbwen_MASK 0xffefffff /* bit 20 */ +# define BC_besbwen_color 0x0 +# define BC_besbwen_bw 0x100000 +# define BC_besblank_MASK 0xffdfffff /* bit 21 */ +# define BC_besblank_disable 0x0 +# define BC_besblank_enable 0x200000 +# define BC_besfselm_MASK 0xfeffffff /* bit 24 */ +# define BC_besfselm_soft 0x0 +# define BC_besfselm_hard 0x1000000 +# define BC_besfsel_MASK 0xf9ffffff /* bits 25-26 */ +# define BC_besfsel_a1 0x0 /* val 0, shift 25 */ +# define BC_besfsel_a2 0x2000000 /* val 1, shift 25 */ +# define BC_besfsel_b1 0x4000000 /* val 2, shift 25 */ +# define BC_besfsel_b2 0x6000000 /* val 3, shift 25 */ + +#define MGAREG_BESGLOBCTL 0x3dc0 + +# define BGC_beshzoom_MASK 0xfffffffe /* bit 0 */ +# define BGC_beshzoom_disable 0x0 +# define BGC_beshzoom_enable 0x1 +# define BGC_beshzoomf_MASK 0xfffffffd /* bit 1 */ +# define BGC_beshzoomf_disable 0x0 +# define BGC_beshzoomf_enable 0x2 +# define BGC_bescorder_MASK 0xfffffff7 /* bit 3 */ +# define BGC_bescorder_even 0x0 +# define BGC_bescorder_odd 0x8 +# define BGC_besreghup_MASK 0xffffffef /* bit 4 */ +# define BGC_besreghup_disable 0x0 +# define BGC_besreghup_enable 0x10 +# define BGC_besvcnt_MASK 0xf000ffff /* bits 16-27 */ +# define BGC_besvcnt_SHIFT 16 + +#define MGAREG_BESHCOORD 0x3d28 + +# define BHC_besright_MASK 0xfffff800 /* bits 0-10 */ +# define BHC_besright_SHIFT 0 +# define BHC_besleft_MASK 0xf800ffff /* bits 16-26 */ +# define BHC_besleft_SHIFT 16 + +#define MGAREG_BESHISCAL 0x3d30 + +# define BHISF_beshiscal_MASK 0xffe00003 /* bits 2-20 */ +# define BHISF_beshiscal_SHIFT 2 + +#define MGAREG_BESHSRCEND 0x3d3c + +# define BHSE_beshsrcend_MASK 0xfc000003 /* bits 2-25 */ +# define BHSE_beshsrcend_SHIFT 2 + +#define MGAREG_BESHSRCLST 0x3d50 + +# define BHSL_beshsrclst_MASK 0xfc00ffff /* bits 16-25 */ +# define BHSL_beshsrclst_SHIFT 16 + +#define MGAREG_BESHSRCST 0x3d38 + +# define BHSS_beshsrcst_MASK 0xfc000003 /* bits 2-25 */ +# define BHSS_beshsrcst_SHIFT 2 + +#define MGAREG_BESPITCH 0x3d24 + +# define BP_bespitch_MASK 0xfffff000 /* bits 0-11 */ +# define BP_bespitch_SHIFT 0 + +#define MGAREG_BESSTATUS 0x3dc4 + +# define BS_besstat_MASK 0xfffffffc /* bits 0-1 */ +# define BS_besstat_a1 0x0 /* val 0, shift 0 */ +# define BS_besstat_a2 0x1 /* val 1, shift 0 */ +# define BS_besstat_b1 0x2 /* val 2, shift 0 */ +# define BS_besstat_b2 0x3 /* val 3, shift 0 */ + +#define MGAREG_BESV1SRCLST 0x3d54 + +# define BSF_besv1srclast_MASK 0xfffffc00 /* bits 0-9 */ +# define BSF_besv1srclast_SHIFT 0 + +#define MGAREG_BESV2SRCLST 0x3d58 + +# define BSF_besv2srclst_MASK 0xfffffc00 /* bits 0-9 */ +# define BSF_besv2srclst_SHIFT 0 + +#define MGAREG_BESV1WGHT 0x3d48 + +# define BSF_besv1wght_MASK 0xffff0003 /* bits 2-15 */ +# define BSF_besv1wght_SHIFT 2 +# define BSF_besv1wghts_MASK 0xfffeffff /* bit 16 */ +# define BSF_besv1wghts_disable 0x0 +# define BSF_besv1wghts_enable 0x10000 + +#define MGAREG_BESV2WGHT 0x3d4c + +# define BSF_besv2wght_MASK 0xffff0003 /* bits 2-15 */ +# define BSF_besv2wght_SHIFT 2 +# define BSF_besv2wghts_MASK 0xfffeffff /* bit 16 */ +# define BSF_besv2wghts_disable 0x0 +# define BSF_besv2wghts_enable 0x10000 + +#define MGAREG_BESVCOORD 0x3d2c + +# define BVC_besbot_MASK 0xfffff800 /* bits 0-10 */ +# define BVC_besbot_SHIFT 0 +# define BVC_bestop_MASK 0xf800ffff /* bits 16-26 */ +# define BVC_bestop_SHIFT 16 + +#define MGAREG_BESVISCAL 0x3d34 + +# define BVISF_besviscal_MASK 0xffe00003 /* bits 2-20 */ +# define BVISF_besviscal_SHIFT 2 + +#define MGAREG_CODECADDR 0x3e44 +#define MGAREG_CODECCTL 0x3e40 +#define MGAREG_CODECHARDPTR 0x3e4c +#define MGAREG_CODECHOSTPTR 0x3e48 +#define MGAREG_CODECLCODE 0x3e50 +#define MGAREG_CXBNDRY 0x1c80 + +# define CXB_cxleft_MASK 0xfffff000 /* bits 0-11 */ +# define CXB_cxleft_SHIFT 0 +# define CXB_cxright_MASK 0xf000ffff /* bits 16-27 */ +# define CXB_cxright_SHIFT 16 + +#define MGAREG_CXLEFT 0x1ca0 +#define MGAREG_CXRIGHT 0x1ca4 +#define MGAREG_DMAMAP30 0x1e30 +#define MGAREG_DMAMAP74 0x1e34 +#define MGAREG_DMAMAPB8 0x1e38 +#define MGAREG_DMAMAPFC 0x1e3c +#define MGAREG_DMAPAD 0x1c54 +#define MGAREG_DR0_Z32LSB 0x2c50 +#define MGAREG_DR0_Z32MSB 0x2c54 +#define MGAREG_DR2_Z32LSB 0x2c60 +#define MGAREG_DR2_Z32MSB 0x2c64 +#define MGAREG_DR3_Z32LSB 0x2c68 +#define MGAREG_DR3_Z32MSB 0x2c6c +#define MGAREG_DR0 0x1cc0 +#define MGAREG_DR2 0x1cc8 +#define MGAREG_DR3 0x1ccc +#define MGAREG_DR4 0x1cd0 +#define MGAREG_DR6 0x1cd8 +#define MGAREG_DR7 0x1cdc +#define MGAREG_DR8 0x1ce0 +#define MGAREG_DR10 0x1ce8 +#define MGAREG_DR11 0x1cec +#define MGAREG_DR12 0x1cf0 +#define MGAREG_DR14 0x1cf8 +#define MGAREG_DR15 0x1cfc +#define MGAREG_DSTORG 0x2cb8 + +# define DO_dstmap_MASK 0xfffffffe /* bit 0 */ +# define DO_dstmap_fb 0x0 +# define DO_dstmap_sys 0x1 +# define DO_dstacc_MASK 0xfffffffd /* bit 1 */ +# define DO_dstacc_pci 0x0 +# define DO_dstacc_agp 0x2 +# define DO_dstorg_MASK 0x7 /* bits 3-31 */ +# define DO_dstorg_SHIFT 3 + +#define MGAREG_DWG_INDIR_WT 0x1e80 +#define MGAREG_DWGCTL 0x1c00 + +# define DC_opcod_MASK 0xfffffff0 /* bits 0-3 */ +# define DC_opcod_line_open 0x0 /* val 0, shift 0 */ +# define DC_opcod_autoline_open 0x1 /* val 1, shift 0 */ +# define DC_opcod_line_close 0x2 /* val 2, shift 0 */ +# define DC_opcod_autoline_close 0x3 /* val 3, shift 0 */ +# define DC_opcod_trap 0x4 /* val 4, shift 0 */ +# define DC_opcod_texture_trap 0x6 /* val 6, shift 0 */ +# define DC_opcod_bitblt 0x8 /* val 8, shift 0 */ +# define DC_opcod_iload 0x9 /* val 9, shift 0 */ +# define DC_atype_MASK 0xffffff8f /* bits 4-6 */ +# define DC_atype_rpl 0x0 /* val 0, shift 4 */ +# define DC_atype_rstr 0x10 /* val 1, shift 4 */ +# define DC_atype_zi 0x30 /* val 3, shift 4 */ +# define DC_atype_blk 0x40 /* val 4, shift 4 */ +# define DC_atype_i 0x70 /* val 7, shift 4 */ +# define DC_linear_MASK 0xffffff7f /* bit 7 */ +# define DC_linear_xy 0x0 +# define DC_linear_linear 0x80 +# define DC_zmode_MASK 0xfffff8ff /* bits 8-10 */ +# define DC_zmode_nozcmp 0x0 /* val 0, shift 8 */ +# define DC_zmode_ze 0x200 /* val 2, shift 8 */ +# define DC_zmode_zne 0x300 /* val 3, shift 8 */ +# define DC_zmode_zlt 0x400 /* val 4, shift 8 */ +# define DC_zmode_zlte 0x500 /* val 5, shift 8 */ +# define DC_zmode_zgt 0x600 /* val 6, shift 8 */ +# define DC_zmode_zgte 0x700 /* val 7, shift 8 */ +# define DC_solid_MASK 0xfffff7ff /* bit 11 */ +# define DC_solid_disable 0x0 +# define DC_solid_enable 0x800 +# define DC_arzero_MASK 0xffffefff /* bit 12 */ +# define DC_arzero_disable 0x0 +# define DC_arzero_enable 0x1000 +# define DC_sgnzero_MASK 0xffffdfff /* bit 13 */ +# define DC_sgnzero_disable 0x0 +# define DC_sgnzero_enable 0x2000 +# define DC_shftzero_MASK 0xffffbfff /* bit 14 */ +# define DC_shftzero_disable 0x0 +# define DC_shftzero_enable 0x4000 +# define DC_bop_MASK 0xfff0ffff /* bits 16-19 */ +# define DC_bop_SHIFT 16 +# define DC_trans_MASK 0xff0fffff /* bits 20-23 */ +# define DC_trans_SHIFT 20 +# define DC_bltmod_MASK 0xe1ffffff /* bits 25-28 */ +# define DC_bltmod_bmonolef 0x0 /* val 0, shift 25 */ +# define DC_bltmod_bmonowf 0x8000000 /* val 4, shift 25 */ +# define DC_bltmod_bplan 0x2000000 /* val 1, shift 25 */ +# define DC_bltmod_bfcol 0x4000000 /* val 2, shift 25 */ +# define DC_bltmod_bu32bgr 0x6000000 /* val 3, shift 25 */ +# define DC_bltmod_bu32rgb 0xe000000 /* val 7, shift 25 */ +# define DC_bltmod_bu24bgr 0x16000000 /* val 11, shift 25 */ +# define DC_bltmod_bu24rgb 0x1e000000 /* val 15, shift 25 */ +# define DC_pattern_MASK 0xdfffffff /* bit 29 */ +# define DC_pattern_disable 0x0 +# define DC_pattern_enable 0x20000000 +# define DC_transc_MASK 0xbfffffff /* bit 30 */ +# define DC_transc_disable 0x0 +# define DC_transc_enable 0x40000000 +# define DC_clipdis_MASK 0x7fffffff /* bit 31 */ +# define DC_clipdis_disable 0x0 +# define DC_clipdis_enable 0x80000000 + +#define MGAREG_DWGSYNC 0x2c4c + +# define DS_dwgsyncaddr_MASK 0x3 /* bits 2-31 */ +# define DS_dwgsyncaddr_SHIFT 2 + +#define MGAREG_FCOL 0x1c24 +#define MGAREG_FIFOSTATUS 0x1e10 + +# define FS_fifocount_MASK 0xffffff80 /* bits 0-6 */ +# define FS_fifocount_SHIFT 0 +# define FS_bfull_MASK 0xfffffeff /* bit 8 */ +# define FS_bfull_disable 0x0 +# define FS_bfull_enable 0x100 +# define FS_bempty_MASK 0xfffffdff /* bit 9 */ +# define FS_bempty_disable 0x0 +# define FS_bempty_enable 0x200 + +#define MGAREG_FOGCOL 0x1cf4 +#define MGAREG_FOGSTART 0x1cc4 +#define MGAREG_FOGXINC 0x1cd4 +#define MGAREG_FOGYINC 0x1ce4 +#define MGAREG_FXBNDRY 0x1c84 + +# define XA_fxleft_MASK 0xffff0000 /* bits 0-15 */ +# define XA_fxleft_SHIFT 0 +# define XA_fxright_MASK 0xffff /* bits 16-31 */ +# define XA_fxright_SHIFT 16 + +#define MGAREG_FXLEFT 0x1ca8 +#define MGAREG_FXRIGHT 0x1cac +#define MGAREG_ICLEAR 0x1e18 + +# define IC_softrapiclr_MASK 0xfffffffe /* bit 0 */ +# define IC_softrapiclr_disable 0x0 +# define IC_softrapiclr_enable 0x1 +# define IC_pickiclr_MASK 0xfffffffb /* bit 2 */ +# define IC_pickiclr_disable 0x0 +# define IC_pickiclr_enable 0x4 +# define IC_vlineiclr_MASK 0xffffffdf /* bit 5 */ +# define IC_vlineiclr_disable 0x0 +# define IC_vlineiclr_enable 0x20 +# define IC_wiclr_MASK 0xffffff7f /* bit 7 */ +# define IC_wiclr_disable 0x0 +# define IC_wiclr_enable 0x80 +# define IC_wciclr_MASK 0xfffffeff /* bit 8 */ +# define IC_wciclr_disable 0x0 +# define IC_wciclr_enable 0x100 + +#define MGAREG_IEN 0x1e1c + +# define IE_softrapien_MASK 0xfffffffe /* bit 0 */ +# define IE_softrapien_disable 0x0 +# define IE_softrapien_enable 0x1 +# define IE_pickien_MASK 0xfffffffb /* bit 2 */ +# define IE_pickien_disable 0x0 +# define IE_pickien_enable 0x4 +# define IE_vlineien_MASK 0xffffffdf /* bit 5 */ +# define IE_vlineien_disable 0x0 +# define IE_vlineien_enable 0x20 +# define IE_extien_MASK 0xffffffbf /* bit 6 */ +# define IE_extien_disable 0x0 +# define IE_extien_enable 0x40 +# define IE_wien_MASK 0xffffff7f /* bit 7 */ +# define IE_wien_disable 0x0 +# define IE_wien_enable 0x80 +# define IE_wcien_MASK 0xfffffeff /* bit 8 */ +# define IE_wcien_disable 0x0 +# define IE_wcien_enable 0x100 + +#define MGAREG_LEN 0x1c5c +#define MGAREG_MACCESS 0x1c04 + +# define MA_pwidth_MASK 0xfffffffc /* bits 0-1 */ +# define MA_pwidth_8 0x0 /* val 0, shift 0 */ +# define MA_pwidth_16 0x1 /* val 1, shift 0 */ +# define MA_pwidth_32 0x2 /* val 2, shift 0 */ +# define MA_pwidth_24 0x3 /* val 3, shift 0 */ +# define MA_zwidth_MASK 0xffffffe7 /* bits 3-4 */ +# define MA_zwidth_16 0x0 /* val 0, shift 3 */ +# define MA_zwidth_32 0x8 /* val 1, shift 3 */ +# define MA_zwidth_15 0x10 /* val 2, shift 3 */ +# define MA_zwidth_24 0x18 /* val 3, shift 3 */ +# define MA_memreset_MASK 0xffff7fff /* bit 15 */ +# define MA_memreset_disable 0x0 +# define MA_memreset_enable 0x8000 +# define MA_fogen_MASK 0xfbffffff /* bit 26 */ +# define MA_fogen_disable 0x0 +# define MA_fogen_enable 0x4000000 +# define MA_tlutload_MASK 0xdfffffff /* bit 29 */ +# define MA_tlutload_disable 0x0 +# define MA_tlutload_enable 0x20000000 +# define MA_nodither_MASK 0xbfffffff /* bit 30 */ +# define MA_nodither_disable 0x0 +# define MA_nodither_enable 0x40000000 +# define MA_dit555_MASK 0x7fffffff /* bit 31 */ +# define MA_dit555_disable 0x0 +# define MA_dit555_enable 0x80000000 + +#define MGAREG_MCTLWTST 0x1c08 + +# define MCWS_casltncy_MASK 0xfffffff8 /* bits 0-2 */ +# define MCWS_casltncy_SHIFT 0 +# define MCWS_rrddelay_MASK 0xffffffcf /* bits 4-5 */ +# define MCWS_rcddelay_MASK 0xfffffe7f /* bits 7-8 */ +# define MCWS_rasmin_MASK 0xffffe3ff /* bits 10-12 */ +# define MCWS_rasmin_SHIFT 10 +# define MCWS_rpdelay_MASK 0xffff3fff /* bits 14-15 */ +# define MCWS_wrdelay_MASK 0xfff3ffff /* bits 18-19 */ +# define MCWS_rddelay_MASK 0xffdfffff /* bit 21 */ +# define MCWS_rddelay_disable 0x0 +# define MCWS_rddelay_enable 0x200000 +# define MCWS_smrdelay_MASK 0xfe7fffff /* bits 23-24 */ +# define MCWS_bwcdelay_MASK 0xf3ffffff /* bits 26-27 */ +# define MCWS_bpldelay_MASK 0x1fffffff /* bits 29-31 */ +# define MCWS_bpldelay_SHIFT 29 + +#define MGAREG_MEMRDBK 0x1e44 + +# define MRB_mclkbrd0_MASK 0xfffffff0 /* bits 0-3 */ +# define MRB_mclkbrd0_SHIFT 0 +# define MRB_mclkbrd1_MASK 0xfffffe1f /* bits 5-8 */ +# define MRB_mclkbrd1_SHIFT 5 +# define MRB_strmfctl_MASK 0xff3fffff /* bits 22-23 */ +# define MRB_mrsopcod_MASK 0xe1ffffff /* bits 25-28 */ +# define MRB_mrsopcod_SHIFT 25 + +#define MGAREG_OPMODE 0x1e54 + +# define OM_dmamod_MASK 0xfffffff3 /* bits 2-3 */ +# define OM_dmamod_general 0x0 /* val 0, shift 2 */ +# define OM_dmamod_blit 0x4 /* val 1, shift 2 */ +# define OM_dmamod_vector 0x8 /* val 2, shift 2 */ +# define OM_dmamod_vertex 0xc /* val 3, shift 2 */ +# define OM_dmadatasiz_MASK 0xfffffcff /* bits 8-9 */ +# define OM_dmadatasiz_8 0x0 /* val 0, shift 8 */ +# define OM_dmadatasiz_16 0x100 /* val 1, shift 8 */ +# define OM_dmadatasiz_32 0x200 /* val 2, shift 8 */ +# define OM_dirdatasiz_MASK 0xfffcffff /* bits 16-17 */ +# define OM_dirdatasiz_8 0x0 /* val 0, shift 16 */ +# define OM_dirdatasiz_16 0x10000 /* val 1, shift 16 */ +# define OM_dirdatasiz_32 0x20000 /* val 2, shift 16 */ + +#define MGAREG_PAT0 0x1c10 +#define MGAREG_PAT1 0x1c14 +#define MGAREG_PITCH 0x1c8c + +# define P_iy_MASK 0xffffe000 /* bits 0-12 */ +# define P_iy_SHIFT 0 +# define P_ylin_MASK 0xffff7fff /* bit 15 */ +# define P_ylin_disable 0x0 +# define P_ylin_enable 0x8000 + +#define MGAREG_PLNWT 0x1c1c +#define MGAREG_PRIMADDRESS 0x1e58 + +# define PDCA_primod_MASK 0xfffffffc /* bits 0-1 */ +# define PDCA_primod_general 0x0 /* val 0, shift 0 */ +# define PDCA_primod_blit 0x1 /* val 1, shift 0 */ +# define PDCA_primod_vector 0x2 /* val 2, shift 0 */ +# define PDCA_primod_vertex 0x3 /* val 3, shift 0 */ +# define PDCA_primaddress_MASK 0x3 /* bits 2-31 */ +# define PDCA_primaddress_SHIFT 2 + +#define MGAREG_PRIMEND 0x1e5c + +# define PDEA_primnostart_MASK 0xfffffffe /* bit 0 */ +# define PDEA_primnostart_disable 0x0 +# define PDEA_primnostart_enable 0x1 +# define PDEA_pagpxfer_MASK 0xfffffffd /* bit 1 */ +# define PDEA_pagpxfer_disable 0x0 +# define PDEA_pagpxfer_enable 0x2 +# define PDEA_primend_MASK 0x3 /* bits 2-31 */ +# define PDEA_primend_SHIFT 2 + +#define MGAREG_PRIMPTR 0x1e50 + +# define PLS_primptren0_MASK 0xfffffffe /* bit 0 */ +# define PLS_primptren0_disable 0x0 +# define PLS_primptren0_enable 0x1 +# define PLS_primptren1_MASK 0xfffffffd /* bit 1 */ +# define PLS_primptren1_disable 0x0 +# define PLS_primptren1_enable 0x2 +# define PLS_primptr_MASK 0x7 /* bits 3-31 */ +# define PLS_primptr_SHIFT 3 + +#define MGAREG_RST 0x1e40 + +# define R_softreset_MASK 0xfffffffe /* bit 0 */ +# define R_softreset_disable 0x0 +# define R_softreset_enable 0x1 +# define R_softextrst_MASK 0xfffffffd /* bit 1 */ +# define R_softextrst_disable 0x0 +# define R_softextrst_enable 0x2 + +#define MGAREG_SECADDRESS 0x2c40 + +# define SDCA_secmod_MASK 0xfffffffc /* bits 0-1 */ +# define SDCA_secmod_general 0x0 /* val 0, shift 0 */ +# define SDCA_secmod_blit 0x1 /* val 1, shift 0 */ +# define SDCA_secmod_vector 0x2 /* val 2, shift 0 */ +# define SDCA_secmod_vertex 0x3 /* val 3, shift 0 */ +# define SDCA_secaddress_MASK 0x3 /* bits 2-31 */ +# define SDCA_secaddress_SHIFT 2 + +#define MGAREG_SECEND 0x2c44 + +# define SDEA_sagpxfer_MASK 0xfffffffd /* bit 1 */ +# define SDEA_sagpxfer_disable 0x0 +# define SDEA_sagpxfer_enable 0x2 +# define SDEA_secend_MASK 0x3 /* bits 2-31 */ +# define SDEA_secend_SHIFT 2 + +#define MGAREG_SETUPADDRESS 0x2cd0 + +# define SETADD_mode_MASK 0xfffffffc /* bits 0-1 */ +# define SETADD_mode_vertlist 0x0 /* val 0, shift 0 */ +# define SETADD_address_MASK 0x3 /* bits 2-31 */ +# define SETADD_address_SHIFT 2 + +#define MGAREG_SETUPEND 0x2cd4 + +# define SETEND_agpxfer_MASK 0xfffffffd /* bit 1 */ +# define SETEND_agpxfer_disable 0x0 +# define SETEND_agpxfer_enable 0x2 +# define SETEND_address_MASK 0x3 /* bits 2-31 */ +# define SETEND_address_SHIFT 2 + +#define MGAREG_SGN 0x1c58 + +# define S_sdydxl_MASK 0xfffffffe /* bit 0 */ +# define S_sdydxl_y 0x0 +# define S_sdydxl_x 0x1 +# define S_scanleft_MASK 0xfffffffe /* bit 0 */ +# define S_scanleft_disable 0x0 +# define S_scanleft_enable 0x1 +# define S_sdxl_MASK 0xfffffffd /* bit 1 */ +# define S_sdxl_pos 0x0 +# define S_sdxl_neg 0x2 +# define S_sdy_MASK 0xfffffffb /* bit 2 */ +# define S_sdy_pos 0x0 +# define S_sdy_neg 0x4 +# define S_sdxr_MASK 0xffffffdf /* bit 5 */ +# define S_sdxr_pos 0x0 +# define S_sdxr_neg 0x20 +# define S_brkleft_MASK 0xfffffeff /* bit 8 */ +# define S_brkleft_disable 0x0 +# define S_brkleft_enable 0x100 +# define S_errorinit_MASK 0x7fffffff /* bit 31 */ +# define S_errorinit_disable 0x0 +# define S_errorinit_enable 0x80000000 + +#define MGAREG_SHIFT 0x1c50 + +# define FSC_x_off_MASK 0xfffffff0 /* bits 0-3 */ +# define FSC_x_off_SHIFT 0 +# define FSC_funcnt_MASK 0xffffff80 /* bits 0-6 */ +# define FSC_funcnt_SHIFT 0 +# define FSC_y_off_MASK 0xffffff8f /* bits 4-6 */ +# define FSC_y_off_SHIFT 4 +# define FSC_funoff_MASK 0xffc0ffff /* bits 16-21 */ +# define FSC_funoff_SHIFT 16 +# define FSC_stylelen_MASK 0xffc0ffff /* bits 16-21 */ +# define FSC_stylelen_SHIFT 16 + +#define MGAREG_SOFTRAP 0x2c48 + +# define STH_softraphand_MASK 0x3 /* bits 2-31 */ +# define STH_softraphand_SHIFT 2 + +#define MGAREG_SPECBSTART 0x2c98 +#define MGAREG_SPECBXINC 0x2c9c +#define MGAREG_SPECBYINC 0x2ca0 +#define MGAREG_SPECGSTART 0x2c8c +#define MGAREG_SPECGXINC 0x2c90 +#define MGAREG_SPECGYINC 0x2c94 +#define MGAREG_SPECRSTART 0x2c80 +#define MGAREG_SPECRXINC 0x2c84 +#define MGAREG_SPECRYINC 0x2c88 +#define MGAREG_SRC0 0x1c30 +#define MGAREG_SRC1 0x1c34 +#define MGAREG_SRC2 0x1c38 +#define MGAREG_SRC3 0x1c3c +#define MGAREG_SRCORG 0x2cb4 + +# define SO_srcmap_MASK 0xfffffffe /* bit 0 */ +# define SO_srcmap_fb 0x0 +# define SO_srcmap_sys 0x1 +# define SO_srcacc_MASK 0xfffffffd /* bit 1 */ +# define SO_srcacc_pci 0x0 +# define SO_srcacc_agp 0x2 +# define SO_srcorg_MASK 0x7 /* bits 3-31 */ +# define SO_srcorg_SHIFT 3 + +#define MGAREG_STATUS 0x1e14 + +# define STAT_softrapen_MASK 0xfffffffe /* bit 0 */ +# define STAT_softrapen_disable 0x0 +# define STAT_softrapen_enable 0x1 +# define STAT_pickpen_MASK 0xfffffffb /* bit 2 */ +# define STAT_pickpen_disable 0x0 +# define STAT_pickpen_enable 0x4 +# define STAT_vsyncsts_MASK 0xfffffff7 /* bit 3 */ +# define STAT_vsyncsts_disable 0x0 +# define STAT_vsyncsts_enable 0x8 +# define STAT_vsyncpen_MASK 0xffffffef /* bit 4 */ +# define STAT_vsyncpen_disable 0x0 +# define STAT_vsyncpen_enable 0x10 +# define STAT_vlinepen_MASK 0xffffffdf /* bit 5 */ +# define STAT_vlinepen_disable 0x0 +# define STAT_vlinepen_enable 0x20 +# define STAT_extpen_MASK 0xffffffbf /* bit 6 */ +# define STAT_extpen_disable 0x0 +# define STAT_extpen_enable 0x40 +# define STAT_wpen_MASK 0xffffff7f /* bit 7 */ +# define STAT_wpen_disable 0x0 +# define STAT_wpen_enable 0x80 +# define STAT_wcpen_MASK 0xfffffeff /* bit 8 */ +# define STAT_wcpen_disable 0x0 +# define STAT_wcpen_enable 0x100 +# define STAT_dwgengsts_MASK 0xfffeffff /* bit 16 */ +# define STAT_dwgengsts_disable 0x0 +# define STAT_dwgengsts_enable 0x10000 +# define STAT_endprdmasts_MASK 0xfffdffff /* bit 17 */ +# define STAT_endprdmasts_disable 0x0 +# define STAT_endprdmasts_enable 0x20000 +# define STAT_wbusy_MASK 0xfffbffff /* bit 18 */ +# define STAT_wbusy_disable 0x0 +# define STAT_wbusy_enable 0x40000 +# define STAT_swflag_MASK 0xfffffff /* bits 28-31 */ +# define STAT_swflag_SHIFT 28 + +#define MGAREG_STENCIL 0x2cc8 + +# define S_sref_MASK 0xffffff00 /* bits 0-7 */ +# define S_sref_SHIFT 0 +# define S_smsk_MASK 0xffff00ff /* bits 8-15 */ +# define S_smsk_SHIFT 8 +# define S_swtmsk_MASK 0xff00ffff /* bits 16-23 */ +# define S_swtmsk_SHIFT 16 + +#define MGAREG_STENCILCTL 0x2ccc + +# define SC_smode_MASK 0xfffffff8 /* bits 0-2 */ +# define SC_smode_salways 0x0 /* val 0, shift 0 */ +# define SC_smode_snever 0x1 /* val 1, shift 0 */ +# define SC_smode_se 0x2 /* val 2, shift 0 */ +# define SC_smode_sne 0x3 /* val 3, shift 0 */ +# define SC_smode_slt 0x4 /* val 4, shift 0 */ +# define SC_smode_slte 0x5 /* val 5, shift 0 */ +# define SC_smode_sgt 0x6 /* val 6, shift 0 */ +# define SC_smode_sgte 0x7 /* val 7, shift 0 */ +# define SC_sfailop_MASK 0xffffffc7 /* bits 3-5 */ +# define SC_sfailop_keep 0x0 /* val 0, shift 3 */ +# define SC_sfailop_zero 0x8 /* val 1, shift 3 */ +# define SC_sfailop_replace 0x10 /* val 2, shift 3 */ +# define SC_sfailop_incrsat 0x18 /* val 3, shift 3 */ +# define SC_sfailop_decrsat 0x20 /* val 4, shift 3 */ +# define SC_sfailop_invert 0x28 /* val 5, shift 3 */ +# define SC_sfailop_incr 0x30 /* val 6, shift 3 */ +# define SC_sfailop_decr 0x38 /* val 7, shift 3 */ +# define SC_szfailop_MASK 0xfffffe3f /* bits 6-8 */ +# define SC_szfailop_keep 0x0 /* val 0, shift 6 */ +# define SC_szfailop_zero 0x40 /* val 1, shift 6 */ +# define SC_szfailop_replace 0x80 /* val 2, shift 6 */ +# define SC_szfailop_incrsat 0xc0 /* val 3, shift 6 */ +# define SC_szfailop_decrsat 0x100 /* val 4, shift 6 */ +# define SC_szfailop_invert 0x140 /* val 5, shift 6 */ +# define SC_szfailop_incr 0x180 /* val 6, shift 6 */ +# define SC_szfailop_decr 0x1c0 /* val 7, shift 6 */ +# define SC_szpassop_MASK 0xfffff1ff /* bits 9-11 */ +# define SC_szpassop_keep 0x0 /* val 0, shift 9 */ +# define SC_szpassop_zero 0x200 /* val 1, shift 9 */ +# define SC_szpassop_replace 0x400 /* val 2, shift 9 */ +# define SC_szpassop_incrsat 0x600 /* val 3, shift 9 */ +# define SC_szpassop_decrsat 0x800 /* val 4, shift 9 */ +# define SC_szpassop_invert 0xa00 /* val 5, shift 9 */ +# define SC_szpassop_incr 0xc00 /* val 6, shift 9 */ +# define SC_szpassop_decr 0xe00 /* val 7, shift 9 */ + +#define MGAREG_TDUALSTAGE0 0x2cf8 + +# define TD0_color_arg2_MASK 0xfffffffc /* bits 0-1 */ +# define TD0_color_arg2_diffuse 0x0 /* val 0, shift 0 */ +# define TD0_color_arg2_specular 0x1 /* val 1, shift 0 */ +# define TD0_color_arg2_fcol 0x2 /* val 2, shift 0 */ +# define TD0_color_arg2_prevstage 0x3 /* val 3, shift 0 */ +# define TD0_color_alpha_MASK 0xffffffe3 /* bits 2-4 */ +# define TD0_color_alpha_diffuse 0x0 /* val 0, shift 2 */ +# define TD0_color_alpha_fcol 0x4 /* val 1, shift 2 */ +# define TD0_color_alpha_currtex 0x8 /* val 2, shift 2 */ +# define TD0_color_alpha_prevtex 0xc /* val 3, shift 2 */ +# define TD0_color_alpha_prevstage 0x10 /* val 4, shift 2 */ +# define TD0_color_arg1_replicatealpha_MASK 0xffffffdf /* bit 5 */ +# define TD0_color_arg1_replicatealpha_disable 0x0 +# define TD0_color_arg1_replicatealpha_enable 0x20 +# define TD0_color_arg1_inv_MASK 0xffffffbf /* bit 6 */ +# define TD0_color_arg1_inv_disable 0x0 +# define TD0_color_arg1_inv_enable 0x40 +# define TD0_color_arg2_replicatealpha_MASK 0xffffff7f /* bit 7 */ +# define TD0_color_arg2_replicatealpha_disable 0x0 +# define TD0_color_arg2_replicatealpha_enable 0x80 +# define TD0_color_arg2_inv_MASK 0xfffffeff /* bit 8 */ +# define TD0_color_arg2_inv_disable 0x0 +# define TD0_color_arg2_inv_enable 0x100 +# define TD0_color_alpha1inv_MASK 0xfffffdff /* bit 9 */ +# define TD0_color_alpha1inv_disable 0x0 +# define TD0_color_alpha1inv_enable 0x200 +# define TD0_color_alpha2inv_MASK 0xfffffbff /* bit 10 */ +# define TD0_color_alpha2inv_disable 0x0 +# define TD0_color_alpha2inv_enable 0x400 +# define TD0_color_arg1mul_MASK 0xfffff7ff /* bit 11 */ +# define TD0_color_arg1mul_disable 0x0 /* val 0, shift 11 */ +# define TD0_color_arg1mul_alpha1 0x800 /* val 1, shift 11 */ +# define TD0_color_arg2mul_MASK 0xffffefff /* bit 12 */ +# define TD0_color_arg2mul_disable 0x0 /* val 0, shift 12 */ +# define TD0_color_arg2mul_alpha2 0x1000 /* val 1, shift 12 */ +# define TD0_color_arg1add_MASK 0xffffdfff /* bit 13 */ +# define TD0_color_arg1add_disable 0x0 /* val 0, shift 13 */ +# define TD0_color_arg1add_mulout 0x2000 /* val 1, shift 13 */ +# define TD0_color_arg2add_MASK 0xffffbfff /* bit 14 */ +# define TD0_color_arg2add_disable 0x0 /* val 0, shift 14 */ +# define TD0_color_arg2add_mulout 0x4000 /* val 1, shift 14 */ +# define TD0_color_modbright_MASK 0xfffe7fff /* bits 15-16 */ +# define TD0_color_modbright_disable 0x0 /* val 0, shift 15 */ +# define TD0_color_modbright_2x 0x8000 /* val 1, shift 15 */ +# define TD0_color_modbright_4x 0x10000 /* val 2, shift 15 */ +# define TD0_color_add_MASK 0xfffdffff /* bit 17 */ +# define TD0_color_add_sub 0x0 /* val 0, shift 17 */ +# define TD0_color_add_add 0x20000 /* val 1, shift 17 */ +# define TD0_color_add2x_MASK 0xfffbffff /* bit 18 */ +# define TD0_color_add2x_disable 0x0 +# define TD0_color_add2x_enable 0x40000 +# define TD0_color_addbias_MASK 0xfff7ffff /* bit 19 */ +# define TD0_color_addbias_disable 0x0 +# define TD0_color_addbias_enable 0x80000 +# define TD0_color_blend_MASK 0xffefffff /* bit 20 */ +# define TD0_color_blend_disable 0x0 +# define TD0_color_blend_enable 0x100000 +# define TD0_color_sel_MASK 0xff9fffff /* bits 21-22 */ +# define TD0_color_sel_arg1 0x0 /* val 0, shift 21 */ +# define TD0_color_sel_arg2 0x200000 /* val 1, shift 21 */ +# define TD0_color_sel_add 0x400000 /* val 2, shift 21 */ +# define TD0_color_sel_mul 0x600000 /* val 3, shift 21 */ +# define TD0_alpha_arg1_inv_MASK 0xff7fffff /* bit 23 */ +# define TD0_alpha_arg1_inv_disable 0x0 +# define TD0_alpha_arg1_inv_enable 0x800000 +# define TD0_alpha_arg2_MASK 0xfcffffff /* bits 24-25 */ +# define TD0_alpha_arg2_diffuse 0x0 /* val 0, shift 24 */ +# define TD0_alpha_arg2_fcol 0x1000000 /* val 1, shift 24 */ +# define TD0_alpha_arg2_prevtex 0x2000000 /* val 2, shift 24 */ +# define TD0_alpha_arg2_prevstage 0x3000000 /* val 3, shift 24 */ +# define TD0_alpha_arg2_inv_MASK 0xfbffffff /* bit 26 */ +# define TD0_alpha_arg2_inv_disable 0x0 +# define TD0_alpha_arg2_inv_enable 0x4000000 +# define TD0_alpha_add_MASK 0xf7ffffff /* bit 27 */ +# define TD0_alpha_add_disable 0x0 +# define TD0_alpha_add_enable 0x8000000 +# define TD0_alpha_addbias_MASK 0xefffffff /* bit 28 */ +# define TD0_alpha_addbias_disable 0x0 +# define TD0_alpha_addbias_enable 0x10000000 +# define TD0_alpha_add2x_MASK 0xdfffffff /* bit 29 */ +# define TD0_alpha_add2x_disable 0x0 +# define TD0_alpha_add2x_enable 0x20000000 +# define TD0_alpha_modbright_MASK 0xcfffffff /* bits 28-29 */ +# define TD0_alpha_modbright_disable 0x0 /* val 0, shift 28 */ +# define TD0_alpha_modbright_2x 0x10000000 /* val 1, shift 28 */ +# define TD0_alpha_modbright_4x 0x20000000 /* val 2, shift 28 */ +# define TD0_alpha_sel_MASK 0x3fffffff /* bits 30-31 */ +# define TD0_alpha_sel_arg1 0x0 /* val 0, shift 30 */ +# define TD0_alpha_sel_arg2 0x40000000 /* val 1, shift 30 */ +# define TD0_alpha_sel_add 0x80000000 /* val 2, shift 30 */ +# define TD0_alpha_sel_mul 0xc0000000 /* val 3, shift 30 */ + +#define MGAREG_TDUALSTAGE1 0x2cfc + +# define TD1_color_arg2_MASK 0xfffffffc /* bits 0-1 */ +# define TD1_color_arg2_diffuse 0x0 /* val 0, shift 0 */ +# define TD1_color_arg2_specular 0x1 /* val 1, shift 0 */ +# define TD1_color_arg2_fcol 0x2 /* val 2, shift 0 */ +# define TD1_color_arg2_prevstage 0x3 /* val 3, shift 0 */ +# define TD1_color_alpha_MASK 0xffffffe3 /* bits 2-4 */ +# define TD1_color_alpha_diffuse 0x0 /* val 0, shift 2 */ +# define TD1_color_alpha_fcol 0x4 /* val 1, shift 2 */ +# define TD1_color_alpha_tex0 0x8 /* val 2, shift 2 */ +# define TD1_color_alpha_prevtex 0xc /* val 3, shift 2 */ +# define TD1_color_alpha_prevstage 0x10 /* val 4, shift 2 */ +# define TD1_color_arg1_replicatealpha_MASK 0xffffffdf /* bit 5 */ +# define TD1_color_arg1_replicatealpha_disable 0x0 +# define TD1_color_arg1_replicatealpha_enable 0x20 +# define TD1_color_arg1_inv_MASK 0xffffffbf /* bit 6 */ +# define TD1_color_arg1_inv_disable 0x0 +# define TD1_color_arg1_inv_enable 0x40 +# define TD1_color_arg2_replicatealpha_MASK 0xffffff7f /* bit 7 */ +# define TD1_color_arg2_replicatealpha_disable 0x0 +# define TD1_color_arg2_replicatealpha_enable 0x80 +# define TD1_color_arg2_inv_MASK 0xfffffeff /* bit 8 */ +# define TD1_color_arg2_inv_disable 0x0 +# define TD1_color_arg2_inv_enable 0x100 +# define TD1_color_alpha1inv_MASK 0xfffffdff /* bit 9 */ +# define TD1_color_alpha1inv_disable 0x0 +# define TD1_color_alpha1inv_enable 0x200 +# define TD1_color_alpha2inv_MASK 0xfffffbff /* bit 10 */ +# define TD1_color_alpha2inv_disable 0x0 +# define TD1_color_alpha2inv_enable 0x400 +# define TD1_color_arg1mul_MASK 0xfffff7ff /* bit 11 */ +# define TD1_color_arg1mul_disable 0x0 /* val 0, shift 11 */ +# define TD1_color_arg1mul_alpha1 0x800 /* val 1, shift 11 */ +# define TD1_color_arg2mul_MASK 0xffffefff /* bit 12 */ +# define TD1_color_arg2mul_disable 0x0 /* val 0, shift 12 */ +# define TD1_color_arg2mul_alpha2 0x1000 /* val 1, shift 12 */ +# define TD1_color_arg1add_MASK 0xffffdfff /* bit 13 */ +# define TD1_color_arg1add_disable 0x0 /* val 0, shift 13 */ +# define TD1_color_arg1add_mulout 0x2000 /* val 1, shift 13 */ +# define TD1_color_arg2add_MASK 0xffffbfff /* bit 14 */ +# define TD1_color_arg2add_disable 0x0 /* val 0, shift 14 */ +# define TD1_color_arg2add_mulout 0x4000 /* val 1, shift 14 */ +# define TD1_color_modbright_MASK 0xfffe7fff /* bits 15-16 */ +# define TD1_color_modbright_disable 0x0 /* val 0, shift 15 */ +# define TD1_color_modbright_2x 0x8000 /* val 1, shift 15 */ +# define TD1_color_modbright_4x 0x10000 /* val 2, shift 15 */ +# define TD1_color_add_MASK 0xfffdffff /* bit 17 */ +# define TD1_color_add_sub 0x0 /* val 0, shift 17 */ +# define TD1_color_add_add 0x20000 /* val 1, shift 17 */ +# define TD1_color_add2x_MASK 0xfffbffff /* bit 18 */ +# define TD1_color_add2x_disable 0x0 +# define TD1_color_add2x_enable 0x40000 +# define TD1_color_addbias_MASK 0xfff7ffff /* bit 19 */ +# define TD1_color_addbias_disable 0x0 +# define TD1_color_addbias_enable 0x80000 +# define TD1_color_blend_MASK 0xffefffff /* bit 20 */ +# define TD1_color_blend_disable 0x0 +# define TD1_color_blend_enable 0x100000 +# define TD1_color_sel_MASK 0xff9fffff /* bits 21-22 */ +# define TD1_color_sel_arg1 0x0 /* val 0, shift 21 */ +# define TD1_color_sel_arg2 0x200000 /* val 1, shift 21 */ +# define TD1_color_sel_add 0x400000 /* val 2, shift 21 */ +# define TD1_color_sel_mul 0x600000 /* val 3, shift 21 */ +# define TD1_alpha_arg1_inv_MASK 0xff7fffff /* bit 23 */ +# define TD1_alpha_arg1_inv_disable 0x0 +# define TD1_alpha_arg1_inv_enable 0x800000 +# define TD1_alpha_arg2_MASK 0xfcffffff /* bits 24-25 */ +# define TD1_alpha_arg2_diffuse 0x0 /* val 0, shift 24 */ +# define TD1_alpha_arg2_fcol 0x1000000 /* val 1, shift 24 */ +# define TD1_alpha_arg2_prevtex 0x2000000 /* val 2, shift 24 */ +# define TD1_alpha_arg2_prevstage 0x3000000 /* val 3, shift 24 */ +# define TD1_alpha_arg2_inv_MASK 0xfbffffff /* bit 26 */ +# define TD1_alpha_arg2_inv_disable 0x0 +# define TD1_alpha_arg2_inv_enable 0x4000000 +# define TD1_alpha_add_MASK 0xf7ffffff /* bit 27 */ +# define TD1_alpha_add_disable 0x0 +# define TD1_alpha_add_enable 0x8000000 +# define TD1_alpha_addbias_MASK 0xefffffff /* bit 28 */ +# define TD1_alpha_addbias_disable 0x0 +# define TD1_alpha_addbias_enable 0x10000000 +# define TD1_alpha_add2x_MASK 0xdfffffff /* bit 29 */ +# define TD1_alpha_add2x_disable 0x0 +# define TD1_alpha_add2x_enable 0x20000000 +# define TD1_alpha_modbright_MASK 0xcfffffff /* bits 28-29 */ +# define TD1_alpha_modbright_disable 0x0 /* val 0, shift 28 */ +# define TD1_alpha_modbright_2x 0x10000000 /* val 1, shift 28 */ +# define TD1_alpha_modbright_4x 0x20000000 /* val 2, shift 28 */ +# define TD1_alpha_sel_MASK 0x3fffffff /* bits 30-31 */ +# define TD1_alpha_sel_arg1 0x0 /* val 0, shift 30 */ +# define TD1_alpha_sel_arg2 0x40000000 /* val 1, shift 30 */ +# define TD1_alpha_sel_add 0x80000000 /* val 2, shift 30 */ +# define TD1_alpha_sel_mul 0xc0000000 /* val 3, shift 30 */ + +#define MGAREG_TEST0 0x1e48 + +# define TST_ramtsten_MASK 0xfffffffe /* bit 0 */ +# define TST_ramtsten_disable 0x0 +# define TST_ramtsten_enable 0x1 +# define TST_ramtstdone_MASK 0xfffffffd /* bit 1 */ +# define TST_ramtstdone_disable 0x0 +# define TST_ramtstdone_enable 0x2 +# define TST_wramtstpass_MASK 0xfffffffb /* bit 2 */ +# define TST_wramtstpass_disable 0x0 +# define TST_wramtstpass_enable 0x4 +# define TST_tcachetstpass_MASK 0xfffffff7 /* bit 3 */ +# define TST_tcachetstpass_disable 0x0 +# define TST_tcachetstpass_enable 0x8 +# define TST_tluttstpass_MASK 0xffffffef /* bit 4 */ +# define TST_tluttstpass_disable 0x0 +# define TST_tluttstpass_enable 0x10 +# define TST_luttstpass_MASK 0xffffffdf /* bit 5 */ +# define TST_luttstpass_disable 0x0 +# define TST_luttstpass_enable 0x20 +# define TST_besramtstpass_MASK 0xffffffbf /* bit 6 */ +# define TST_besramtstpass_disable 0x0 +# define TST_besramtstpass_enable 0x40 +# define TST_ringen_MASK 0xfffffeff /* bit 8 */ +# define TST_ringen_disable 0x0 +# define TST_ringen_enable 0x100 +# define TST_apllbyp_MASK 0xfffffdff /* bit 9 */ +# define TST_apllbyp_disable 0x0 +# define TST_apllbyp_enable 0x200 +# define TST_hiten_MASK 0xfffffbff /* bit 10 */ +# define TST_hiten_disable 0x0 +# define TST_hiten_enable 0x400 +# define TST_tmode_MASK 0xffffc7ff /* bits 11-13 */ +# define TST_tmode_SHIFT 11 +# define TST_tclksel_MASK 0xfffe3fff /* bits 14-16 */ +# define TST_tclksel_SHIFT 14 +# define TST_ringcnten_MASK 0xfffdffff /* bit 17 */ +# define TST_ringcnten_disable 0x0 +# define TST_ringcnten_enable 0x20000 +# define TST_ringcnt_MASK 0xc003ffff /* bits 18-29 */ +# define TST_ringcnt_SHIFT 18 +# define TST_ringcntclksl_MASK 0xbfffffff /* bit 30 */ +# define TST_ringcntclksl_disable 0x0 +# define TST_ringcntclksl_enable 0x40000000 +# define TST_biosboot_MASK 0x7fffffff /* bit 31 */ +# define TST_biosboot_disable 0x0 +# define TST_biosboot_enable 0x80000000 + +#define MGAREG_TEXBORDERCOL 0x2c5c +#define MGAREG_TEXCTL 0x2c30 + +# define TMC_tformat_MASK 0xfffffff0 /* bits 0-3 */ +# define TMC_tformat_tw4 0x0 /* val 0, shift 0 */ +# define TMC_tformat_tw8 0x1 /* val 1, shift 0 */ +# define TMC_tformat_tw15 0x2 /* val 2, shift 0 */ +# define TMC_tformat_tw16 0x3 /* val 3, shift 0 */ +# define TMC_tformat_tw12 0x4 /* val 4, shift 0 */ +# define TMC_tformat_tw32 0x6 /* val 6, shift 0 */ +# define TMC_tformat_tw8a 0x7 /* val 7, shift 0 */ +# define TMC_tformat_tw8al 0x8 /* val 8, shift 0 */ +# define TMC_tformat_tw422 0xa /* val 10, shift 0 */ +# define TMC_tformat_tw422uyvy 0xb /* val 11, shift 0 */ +# define TMC_tpitchlin_MASK 0xfffffeff /* bit 8 */ +# define TMC_tpitchlin_disable 0x0 +# define TMC_tpitchlin_enable 0x100 +# define TMC_tpitchext_MASK 0xfff001ff /* bits 9-19 */ +# define TMC_tpitchext_SHIFT 9 +# define TMC_tpitch_MASK 0xfff8ffff /* bits 16-18 */ +# define TMC_tpitch_SHIFT 16 +# define TMC_owalpha_MASK 0xffbfffff /* bit 22 */ +# define TMC_owalpha_disable 0x0 +# define TMC_owalpha_enable 0x400000 +# define TMC_azeroextend_MASK 0xff7fffff /* bit 23 */ +# define TMC_azeroextend_disable 0x0 +# define TMC_azeroextend_enable 0x800000 +# define TMC_decalckey_MASK 0xfeffffff /* bit 24 */ +# define TMC_decalckey_disable 0x0 +# define TMC_decalckey_enable 0x1000000 +# define TMC_takey_MASK 0xfdffffff /* bit 25 */ +# define TMC_takey_0 0x0 +# define TMC_takey_1 0x2000000 +# define TMC_tamask_MASK 0xfbffffff /* bit 26 */ +# define TMC_tamask_0 0x0 +# define TMC_tamask_1 0x4000000 +# define TMC_clampv_MASK 0xf7ffffff /* bit 27 */ +# define TMC_clampv_disable 0x0 +# define TMC_clampv_enable 0x8000000 +# define TMC_clampu_MASK 0xefffffff /* bit 28 */ +# define TMC_clampu_disable 0x0 +# define TMC_clampu_enable 0x10000000 +# define TMC_tmodulate_MASK 0xdfffffff /* bit 29 */ +# define TMC_tmodulate_disable 0x0 +# define TMC_tmodulate_enable 0x20000000 +# define TMC_strans_MASK 0xbfffffff /* bit 30 */ +# define TMC_strans_disable 0x0 +# define TMC_strans_enable 0x40000000 +# define TMC_itrans_MASK 0x7fffffff /* bit 31 */ +# define TMC_itrans_disable 0x0 +# define TMC_itrans_enable 0x80000000 + +#define MGAREG_TEXCTL2 0x2c3c + +# define TMC_decalblend_MASK 0xfffffffe /* bit 0 */ +# define TMC_decalblend_disable 0x0 +# define TMC_decalblend_enable 0x1 +# define TMC_idecal_MASK 0xfffffffd /* bit 1 */ +# define TMC_idecal_disable 0x0 +# define TMC_idecal_enable 0x2 +# define TMC_decaldis_MASK 0xfffffffb /* bit 2 */ +# define TMC_decaldis_disable 0x0 +# define TMC_decaldis_enable 0x4 +# define TMC_ckstransdis_MASK 0xffffffef /* bit 4 */ +# define TMC_ckstransdis_disable 0x0 +# define TMC_ckstransdis_enable 0x10 +# define TMC_borderen_MASK 0xffffffdf /* bit 5 */ +# define TMC_borderen_disable 0x0 +# define TMC_borderen_enable 0x20 +# define TMC_specen_MASK 0xffffffbf /* bit 6 */ +# define TMC_specen_disable 0x0 +# define TMC_specen_enable 0x40 +# define TMC_dualtex_MASK 0xffffff7f /* bit 7 */ +# define TMC_dualtex_disable 0x0 +# define TMC_dualtex_enable 0x80 +# define TMC_tablefog_MASK 0xfffffeff /* bit 8 */ +# define TMC_tablefog_disable 0x0 +# define TMC_tablefog_enable 0x100 +# define TMC_bumpmap_MASK 0xfffffdff /* bit 9 */ +# define TMC_bumpmap_disable 0x0 +# define TMC_bumpmap_enable 0x200 +# define TMC_map1_MASK 0x7fffffff /* bit 31 */ +# define TMC_map1_disable 0x0 +# define TMC_map1_enable 0x80000000 + +#define MGAREG_TEXFILTER 0x2c58 + +# define TF_minfilter_MASK 0xfffffff0 /* bits 0-3 */ +# define TF_minfilter_nrst 0x0 /* val 0, shift 0 */ +# define TF_minfilter_bilin 0x2 /* val 2, shift 0 */ +# define TF_minfilter_cnst 0x3 /* val 3, shift 0 */ +# define TF_minfilter_mm1s 0x8 /* val 8, shift 0 */ +# define TF_minfilter_mm2s 0x9 /* val 9, shift 0 */ +# define TF_minfilter_mm4s 0xa /* val 10, shift 0 */ +# define TF_minfilter_mm8s 0xc /* val 12, shift 0 */ +# define TF_magfilter_MASK 0xffffff0f /* bits 4-7 */ +# define TF_magfilter_nrst 0x0 /* val 0, shift 4 */ +# define TF_magfilter_bilin 0x20 /* val 2, shift 4 */ +# define TF_magfilter_cnst 0x30 /* val 3, shift 4 */ +# define TF_uvoffset_SHIFT 17 +# define TF_uvoffset_OGL (0U << TF_uvoffset_SHIFT) +# define TF_uvoffset_D3D (1U << TF_uvoffset_SHIFT) +# define TF_uvoffset_MASK (~(1U << TF_uvoffset_SHIFT)) +# define TF_reserved_MASK (~0x1ff00) /* bits 8-16 */ +# define TF_mapnbhigh_SHIFT 18 +# define TF_mapnbhigh_MASK (~(1U << TF_mapnbhigh_SHIFT)) +# define TF_avgstride_MASK 0xfff7ffff /* bit 19 */ +# define TF_avgstride_disable 0x0 +# define TF_avgstride_enable 0x80000 +# define TF_filteralpha_MASK 0xffefffff /* bit 20 */ +# define TF_filteralpha_disable 0x0 +# define TF_filteralpha_enable 0x100000 +# define TF_fthres_MASK 0xe01fffff /* bits 21-28 */ +# define TF_fthres_SHIFT 21 +# define TF_mapnb_MASK 0x1fffffff /* bits 29-31 */ +# define TF_mapnb_SHIFT 29 + +#define MGAREG_TEXHEIGHT 0x2c2c + +# define TH_th_MASK 0xffffffc0 /* bits 0-5 */ +# define TH_th_SHIFT 0 +# define TH_rfh_MASK 0xffff81ff /* bits 9-14 */ +# define TH_rfh_SHIFT 9 +# define TH_thmask_MASK 0xe003ffff /* bits 18-28 */ +# define TH_thmask_SHIFT 18 + +#define MGAREG_TEXORG 0x2c24 + +# define TO_texorgmap_MASK 0xfffffffe /* bit 0 */ +# define TO_texorgmap_fb 0x0 +# define TO_texorgmap_sys 0x1 +# define TO_texorgacc_MASK 0xfffffffd /* bit 1 */ +# define TO_texorgacc_pci 0x0 +# define TO_texorgacc_agp 0x2 +# define TO_texorgoffsetsel 0x4 +# define TO_texorg_MASK 0x1f /* bits 5-31 */ +# define TO_texorg_SHIFT 5 + +#define MGAREG_TEXORG1 0x2ca4 +#define MGAREG_TEXORG2 0x2ca8 +#define MGAREG_TEXORG3 0x2cac +#define MGAREG_TEXORG4 0x2cb0 +#define MGAREG_TEXTRANS 0x2c34 + +# define TT_tckey_MASK 0xffff0000 /* bits 0-15 */ +# define TT_tckey_SHIFT 0 +# define TT_tkmask_MASK 0xffff /* bits 16-31 */ +# define TT_tkmask_SHIFT 16 + +#define MGAREG_TEXTRANSHIGH 0x2c38 + +# define TT_tckeyh_MASK 0xffff0000 /* bits 0-15 */ +# define TT_tckeyh_SHIFT 0 +# define TT_tkmaskh_MASK 0xffff /* bits 16-31 */ +# define TT_tkmaskh_SHIFT 16 + +#define MGAREG_TEXWIDTH 0x2c28 + +# define TW_tw_MASK 0xffffffc0 /* bits 0-5 */ +# define TW_tw_SHIFT 0 +# define TW_rfw_MASK 0xffff81ff /* bits 9-14 */ +# define TW_rfw_SHIFT 9 +# define TW_twmask_MASK 0xe003ffff /* bits 18-28 */ +# define TW_twmask_SHIFT 18 + +#define MGAREG_TMR0 0x2c00 +#define MGAREG_TMR1 0x2c04 +#define MGAREG_TMR2 0x2c08 +#define MGAREG_TMR3 0x2c0c +#define MGAREG_TMR4 0x2c10 +#define MGAREG_TMR5 0x2c14 +#define MGAREG_TMR6 0x2c18 +#define MGAREG_TMR7 0x2c1c +#define MGAREG_TMR8 0x2c20 +#define MGAREG_VBIADDR0 0x3e08 +#define MGAREG_VBIADDR1 0x3e0c +#define MGAREG_VCOUNT 0x1e20 +#define MGAREG_WACCEPTSEQ 0x1dd4 + +# define WAS_seqdst0_MASK 0xffffffc0 /* bits 0-5 */ +# define WAS_seqdst0_SHIFT 0 +# define WAS_seqdst1_MASK 0xfffff03f /* bits 6-11 */ +# define WAS_seqdst1_SHIFT 6 +# define WAS_seqdst2_MASK 0xfffc0fff /* bits 12-17 */ +# define WAS_seqdst2_SHIFT 12 +# define WAS_seqdst3_MASK 0xff03ffff /* bits 18-23 */ +# define WAS_seqdst3_SHIFT 18 +# define WAS_seqlen_MASK 0xfcffffff /* bits 24-25 */ +# define WAS_wfirsttag_MASK 0xfbffffff /* bit 26 */ +# define WAS_wfirsttag_disable 0x0 +# define WAS_wfirsttag_enable 0x4000000 +# define WAS_wsametag_MASK 0xf7ffffff /* bit 27 */ +# define WAS_wsametag_disable 0x0 +# define WAS_wsametag_enable 0x8000000 +# define WAS_seqoff_MASK 0xefffffff /* bit 28 */ +# define WAS_seqoff_disable 0x0 +# define WAS_seqoff_enable 0x10000000 + +#define MGAREG_WCODEADDR 0x1e6c + +# define WMA_wcodeaddr_MASK 0xff /* bits 8-31 */ +# define WMA_wcodeaddr_SHIFT 8 + +#define MGAREG_WFLAG 0x1dc4 + +# define WF_walustsflag_MASK 0xffffff00 /* bits 0-7 */ +# define WF_walustsflag_SHIFT 0 +# define WF_walucfgflag_MASK 0xffff00ff /* bits 8-15 */ +# define WF_walucfgflag_SHIFT 8 +# define WF_wprgflag_MASK 0xffff /* bits 16-31 */ +# define WF_wprgflag_SHIFT 16 + +#define MGAREG_WFLAG1 0x1de0 + +# define WF1_walustsflag1_MASK 0xffffff00 /* bits 0-7 */ +# define WF1_walustsflag1_SHIFT 0 +# define WF1_walucfgflag1_MASK 0xffff00ff /* bits 8-15 */ +# define WF1_walucfgflag1_SHIFT 8 +# define WF1_wprgflag1_MASK 0xffff /* bits 16-31 */ +# define WF1_wprgflag1_SHIFT 16 + +#define MGAREG_WFLAGNB 0x1e64 +#define MGAREG_WFLAGNB1 0x1e08 +#define MGAREG_WGETMSB 0x1dc8 + +# define WGV_wgetmsbmin_MASK 0xffffffe0 /* bits 0-4 */ +# define WGV_wgetmsbmin_SHIFT 0 +# define WGV_wgetmsbmax_MASK 0xffffe0ff /* bits 8-12 */ +# define WGV_wgetmsbmax_SHIFT 8 +# define WGV_wbrklefttop_MASK 0xfffeffff /* bit 16 */ +# define WGV_wbrklefttop_disable 0x0 +# define WGV_wbrklefttop_enable 0x10000 +# define WGV_wfastcrop_MASK 0xfffdffff /* bit 17 */ +# define WGV_wfastcrop_disable 0x0 +# define WGV_wfastcrop_enable 0x20000 +# define WGV_wcentersnap_MASK 0xfffbffff /* bit 18 */ +# define WGV_wcentersnap_disable 0x0 +# define WGV_wcentersnap_enable 0x40000 +# define WGV_wbrkrighttop_MASK 0xfff7ffff /* bit 19 */ +# define WGV_wbrkrighttop_disable 0x0 +# define WGV_wbrkrighttop_enable 0x80000 + +#define MGAREG_WIADDR 0x1dc0 + +# define WIA_wmode_MASK 0xfffffffc /* bits 0-1 */ +# define WIA_wmode_suspend 0x0 /* val 0, shift 0 */ +# define WIA_wmode_resume 0x1 /* val 1, shift 0 */ +# define WIA_wmode_jump 0x2 /* val 2, shift 0 */ +# define WIA_wmode_start 0x3 /* val 3, shift 0 */ +# define WIA_wagp_MASK 0xfffffffb /* bit 2 */ +# define WIA_wagp_pci 0x0 +# define WIA_wagp_agp 0x4 +# define WIA_wiaddr_MASK 0x7 /* bits 3-31 */ +# define WIA_wiaddr_SHIFT 3 + +#define MGAREG_WIADDR2 0x1dd8 + +# define WIA2_wmode_MASK 0xfffffffc /* bits 0-1 */ +# define WIA2_wmode_suspend 0x0 /* val 0, shift 0 */ +# define WIA2_wmode_resume 0x1 /* val 1, shift 0 */ +# define WIA2_wmode_jump 0x2 /* val 2, shift 0 */ +# define WIA2_wmode_start 0x3 /* val 3, shift 0 */ +# define WIA2_wagp_MASK 0xfffffffb /* bit 2 */ +# define WIA2_wagp_pci 0x0 +# define WIA2_wagp_agp 0x4 +# define WIA2_wiaddr_MASK 0x7 /* bits 3-31 */ +# define WIA2_wiaddr_SHIFT 3 + +#define MGAREG_WIADDRNB 0x1e60 +#define MGAREG_WIADDRNB1 0x1e04 +#define MGAREG_WIADDRNB2 0x1e00 +#define MGAREG_WIMEMADDR 0x1e68 + +# define WIMA_wimemaddr_MASK 0xffffff00 /* bits 0-7 */ +# define WIMA_wimemaddr_SHIFT 0 + +#define MGAREG_WIMEMDATA 0x2000 +#define MGAREG_WIMEMDATA1 0x2100 +#define MGAREG_WMISC 0x1e70 + +# define WM_wucodecache_MASK 0xfffffffe /* bit 0 */ +# define WM_wucodecache_disable 0x0 +# define WM_wucodecache_enable 0x1 +# define WM_wmaster_MASK 0xfffffffd /* bit 1 */ +# define WM_wmaster_disable 0x0 +# define WM_wmaster_enable 0x2 +# define WM_wcacheflush_MASK 0xfffffff7 /* bit 3 */ +# define WM_wcacheflush_disable 0x0 +# define WM_wcacheflush_enable 0x8 + +#define MGAREG_WR 0x2d00 +#define MGAREG_WVRTXSZ 0x1dcc + +# define WVS_wvrtxsz_MASK 0xffffffc0 /* bits 0-5 */ +# define WVS_wvrtxsz_SHIFT 0 +# define WVS_primsz_MASK 0xffffc0ff /* bits 8-13 */ +# define WVS_primsz_SHIFT 8 + +#define MGAREG_XDST 0x1cb0 +#define MGAREG_XYEND 0x1c44 + +# define XYEA_x_end_MASK 0xffff0000 /* bits 0-15 */ +# define XYEA_x_end_SHIFT 0 +# define XYEA_y_end_MASK 0xffff /* bits 16-31 */ +# define XYEA_y_end_SHIFT 16 + +#define MGAREG_XYSTRT 0x1c40 + +# define XYSA_x_start_MASK 0xffff0000 /* bits 0-15 */ +# define XYSA_x_start_SHIFT 0 +# define XYSA_y_start_MASK 0xffff /* bits 16-31 */ +# define XYSA_y_start_SHIFT 16 + +#define MGAREG_YBOT 0x1c9c +#define MGAREG_YDST 0x1c90 + +# define YA_ydst_MASK 0xff800000 /* bits 0-22 */ +# define YA_ydst_SHIFT 0 +# define YA_sellin_MASK 0x1fffffff /* bits 29-31 */ +# define YA_sellin_SHIFT 29 + +#define MGAREG_YDSTLEN 0x1c88 + +# define YDL_length_MASK 0xffff0000 /* bits 0-15 */ +# define YDL_length_SHIFT 0 +# define YDL_yval_MASK 0xffff /* bits 16-31 */ +# define YDL_yval_SHIFT 16 + +#define MGAREG_YDSTORG 0x1c94 +#define MGAREG_YTOP 0x1c98 +#define MGAREG_ZORG 0x1c0c + +# define ZO_zorgmap_MASK 0xfffffffe /* bit 0 */ +# define ZO_zorgmap_fb 0x0 +# define ZO_zorgmap_sys 0x1 +# define ZO_zorgacc_MASK 0xfffffffd /* bit 1 */ +# define ZO_zorgacc_pci 0x0 +# define ZO_zorgacc_agp 0x2 +# define ZO_zorg_MASK 0x3 /* bits 2-31 */ +# define ZO_zorg_SHIFT 2 + + + + +/**************** (END) AUTOMATICLY GENERATED REGISTER FILE ******************/ + +/* Copied from mga_drv.h kernel file. + */ + +#define MGA_ILOAD_ALIGN 64 +#define MGA_ILOAD_MASK (MGA_ILOAD_ALIGN - 1) + +#endif /* _MGAREGS_H_ */ + diff --git a/src/mgarender.c b/src/mgarender.c new file mode 100644 index 0000000..c151f79 --- /dev/null +++ b/src/mgarender.c @@ -0,0 +1,172 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgarender.c,v 1.4 2002/10/30 12:51:36 alanh Exp $ */ +/************************************************************************** + +Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and + VA Linux Systems Inc., Fremont, California. + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * + */ + + +/* + * Render unclipped vertex buffers by emitting vertices directly to + * dma buffers. Use strip/fan hardware primitives where possible. + * Simulate missing primitives with indexed vertices. + */ +#include "glheader.h" +#include "context.h" +#include "macros.h" +#include "imports.h" +#include "mtypes.h" + +#include "tnl/t_context.h" + +#include "mgacontext.h" +#include "mgatris.h" +#include "mgastate.h" +#include "mgaioctl.h" +#include "mgavb.h" + +#define HAVE_POINTS 0 +#define HAVE_LINES 0 +#define HAVE_LINE_STRIPS 0 +#define HAVE_TRIANGLES 1 +#define HAVE_TRI_STRIPS 1 +#define HAVE_TRI_STRIP_1 0 +#define HAVE_TRI_FANS 1 +#define HAVE_POLYGONS 0 +#define HAVE_QUADS 0 +#define HAVE_QUAD_STRIPS 0 + +#define HAVE_ELTS 0 /* for now */ + +static void mgaDmaPrimitive( GLcontext *ctx, GLenum prim ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + GLuint hwprim; + + switch (prim) { + case GL_TRIANGLES: + hwprim = MGA_WA_TRIANGLES; + break; + case GL_TRIANGLE_STRIP: + if (mmesa->vertex_size == 8) + hwprim = MGA_WA_TRISTRIP_T0; + else + hwprim = MGA_WA_TRISTRIP_T0T1; + break; + case GL_TRIANGLE_FAN: + if (mmesa->vertex_size == 8) + hwprim = MGA_WA_TRIFAN_T0; + else + hwprim = MGA_WA_TRIFAN_T0T1; + break; + default: + return; + } + + mgaRasterPrimitive( ctx, GL_TRIANGLES, hwprim ); +} + + +#define LOCAL_VARS mgaContextPtr mmesa = MGA_CONTEXT(ctx) +#define INIT( prim ) do { \ + if (0) fprintf(stderr, "%s\n", __FUNCTION__); \ + FLUSH_BATCH(mmesa); \ + mgaDmaPrimitive( ctx, prim ); \ +} while (0) +#define FLUSH() FLUSH_BATCH( mmesa ) +#define GET_CURRENT_VB_MAX_VERTS() \ + 0 /* fix me */ +#define GET_SUBSEQUENT_VB_MAX_VERTS() \ + MGA_BUFFER_SIZE / (mmesa->vertex_size * 4) + + +#define ALLOC_VERTS( nr ) \ + mgaAllocDmaLow( mmesa, (nr) * mmesa->vertex_size * 4) +#define EMIT_VERTS( ctx, j, nr, buf ) \ + mga_emit_contiguous_verts(ctx, j, (j)+(nr), buf) + + +#define TAG(x) mga_##x +#include "tnl_dd/t_dd_dmatmp.h" + + + +/**********************************************************************/ +/* Render pipeline stage */ +/**********************************************************************/ + + +static GLboolean mga_run_render( GLcontext *ctx, + struct tnl_pipeline_stage *stage ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &tnl->vb; + GLuint i; + + /* Don't handle clipping or indexed vertices or vertex manipulations. + */ + if (mmesa->RenderIndex != 0 || + !mga_validate_render( ctx, VB )) { + return GL_TRUE; + } + + tnl->Driver.Render.Start( ctx ); + mmesa->SetupNewInputs = ~0; + + for (i = 0 ; i < VB->PrimitiveCount ; i++) + { + GLuint prim = _tnl_translate_prim(&VB->Primitive[i]); + GLuint start = VB->Primitive[i].start; + GLuint length = VB->Primitive[i].count; + + if (!length) + continue; + + mga_render_tab_verts[prim & PRIM_MODE_MASK]( ctx, start, start + length, + prim); + } + + tnl->Driver.Render.Finish( ctx ); + + return GL_FALSE; /* finished the pipe */ +} + + +const struct tnl_pipeline_stage _mga_render_stage = +{ + "mga render", + NULL, + NULL, + NULL, + NULL, + mga_run_render /* run */ +}; diff --git a/src/mgaspan.c b/src/mgaspan.c new file mode 100644 index 0000000..05dcbb8 --- /dev/null +++ b/src/mgaspan.c @@ -0,0 +1,223 @@ +/* + * Copyright 2000-2001 VA Linux Systems, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#include "mtypes.h" +#include "mgadd.h" +#include "mgacontext.h" +#include "mgaspan.h" +#include "mgaioctl.h" +#include "swrast/swrast.h" + +#define DBG 0 + +#define LOCAL_VARS \ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); \ + __DRIscreenPrivate *sPriv = mmesa->driScreen; \ + driRenderbuffer *drb = (driRenderbuffer *) rb; \ + const __DRIdrawablePrivate *dPriv = drb->dPriv; \ + GLuint pitch = drb->pitch; \ + GLuint height = dPriv->h; \ + char *buf = (char *)(sPriv->pFB + \ + drb->offset + \ + dPriv->x * drb->cpp + \ + dPriv->y * pitch); \ + GLuint p; \ + (void) buf; (void) p + + + +#define LOCAL_DEPTH_VARS \ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); \ + __DRIscreenPrivate *sPriv = mmesa->driScreen; \ + driRenderbuffer *drb = (driRenderbuffer *) rb; \ + const __DRIdrawablePrivate *dPriv = drb->dPriv; \ + GLuint pitch = drb->pitch; \ + GLuint height = dPriv->h; \ + char *buf = (char *)(sPriv->pFB + \ + drb->offset + \ + dPriv->x * drb->cpp + \ + dPriv->y * pitch) + +#define LOCAL_STENCIL_VARS LOCAL_DEPTH_VARS + +#define HW_LOCK() + +/* FIXME could/should we use dPriv->numClipRects like the other drivers? */ +#define HW_CLIPLOOP() \ + do { \ + int _nc = mmesa->numClipRects; \ + while (_nc--) { \ + int minx = mmesa->pClipRects[_nc].x1 - mmesa->drawX; \ + int miny = mmesa->pClipRects[_nc].y1 - mmesa->drawY; \ + int maxx = mmesa->pClipRects[_nc].x2 - mmesa->drawX; \ + int maxy = mmesa->pClipRects[_nc].y2 - mmesa->drawY; + +#define HW_ENDCLIPLOOP() \ + } \ + } while (0) + +#define HW_UNLOCK() + + + +#define Y_FLIP(_y) (height - _y - 1) + +/* 16 bit, RGB565 color spanline and pixel functions + */ +#define SPANTMP_PIXEL_FMT GL_RGB +#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_SHORT_5_6_5 + +#define TAG(x) mga##x##_565 +#define TAG2(x,y) mga##x##_565##y +#include "spantmp2.h" + +/* 32 bit, ARGB8888 color spanline and pixel functions + */ +#define SPANTMP_PIXEL_FMT GL_BGRA +#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV + +#define TAG(x) mga##x##_8888 +#define TAG2(x,y) mga##x##_8888##y +#include "spantmp2.h" + + +/* 16 bit depthbuffer functions. + */ +#define WRITE_DEPTH( _x, _y, d ) \ + *(GLushort *)(buf + (_x)*2 + (_y)*pitch) = d; + +#define READ_DEPTH( d, _x, _y ) \ + d = *(GLushort *)(buf + (_x)*2 + (_y)*pitch); + +#define TAG(x) mga##x##_z16 +#include "depthtmp.h" + + + + +/* 32 bit depthbuffer functions. + */ +#define WRITE_DEPTH( _x, _y, d ) \ + *(GLuint *)(buf + (_x)*4 + (_y)*pitch) = d; + +#define READ_DEPTH( d, _x, _y ) \ + d = *(GLuint *)(buf + (_x)*4 + (_y)*pitch); + +#define TAG(x) mga##x##_z32 +#include "depthtmp.h" + + + +/* 24/8 bit interleaved depth/stencil functions + */ +#define WRITE_DEPTH( _x, _y, d ) { \ + GLuint tmp = *(GLuint *)(buf + (_x)*4 + (_y)*pitch); \ + tmp &= 0xff; \ + tmp |= (d) << 8; \ + *(GLuint *)(buf + (_x)*4 + (_y)*pitch) = tmp; \ +} + +#define READ_DEPTH( d, _x, _y ) { \ + d = (*(GLuint *)(buf + (_x)*4 + (_y)*pitch) & ~0xff) >> 8; \ +} + +#define TAG(x) mga##x##_z24_s8 +#include "depthtmp.h" + +#define WRITE_STENCIL( _x, _y, d ) { \ + GLuint tmp = *(GLuint *)(buf + _x*4 + _y*pitch); \ + tmp &= 0xffffff00; \ + tmp |= d & 0xff; \ + *(GLuint *)(buf + _x*4 + _y*pitch) = tmp; \ +} + +#define READ_STENCIL( d, _x, _y ) \ + d = *(GLuint *)(buf + _x*4 + _y*pitch) & 0xff; + +#define TAG(x) mga##x##_z24_s8 +#include "stenciltmp.h" + + +static void +mgaSpanRenderStart( GLcontext *ctx ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + FLUSH_BATCH( mmesa ); + LOCK_HARDWARE_QUIESCENT( mmesa ); +} + +static void +mgaSpanRenderFinish( GLcontext *ctx ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + _swrast_flush( ctx ); + UNLOCK_HARDWARE( mmesa ); +} + +/** + * Initialize the driver callbacks for the read / write span functions. + * + * \bug + * To really support RGB888 and RGBA8888 visuals, we need separate read and + * write routines for 888 and 8888. We also need to determine whether or not + * the visual has destination alpha. + */ +void mgaDDInitSpanFuncs( GLcontext *ctx ) +{ + struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx); + swdd->SpanRenderStart = mgaSpanRenderStart; + swdd->SpanRenderFinish = mgaSpanRenderFinish; +} + + +/** + * Plug in the Get/Put routines for the given driRenderbuffer. + */ +void +mgaSetSpanFunctions(driRenderbuffer *drb, const GLvisual *vis) +{ + if (drb->Base.InternalFormat == GL_RGBA) { + if (vis->redBits == 5 && vis->greenBits == 6 && vis->blueBits == 5) { + mgaInitPointers_565(&drb->Base); + } + else { + mgaInitPointers_8888(&drb->Base); + } + } + else if (drb->Base.InternalFormat == GL_DEPTH_COMPONENT16) { + mgaInitDepthPointers_z16(&drb->Base); + } + else if (drb->Base.InternalFormat == GL_DEPTH_COMPONENT24) { + mgaInitDepthPointers_z24_s8(&drb->Base); + } + else if (drb->Base.InternalFormat == GL_DEPTH_COMPONENT32) { + mgaInitDepthPointers_z32(&drb->Base); + } + else if (drb->Base.InternalFormat == GL_STENCIL_INDEX8_EXT) { + mgaInitStencilPointers_z24_s8(&drb->Base); + } +} diff --git a/src/mgaspan.h b/src/mgaspan.h new file mode 100644 index 0000000..f133a51 --- /dev/null +++ b/src/mgaspan.h @@ -0,0 +1,40 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgaspan.h,v 1.3 2002/10/30 12:51:36 alanh Exp $ */ +/* + * Copyright 2000-2001 VA Linux Systems, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#ifndef _MGA_SPAN_H +#define _MGA_SPAN_H + +#include "drirenderbuffer.h" + +extern void mgaDDInitSpanFuncs( GLcontext *ctx ); + +extern void +mgaSetSpanFunctions(driRenderbuffer *rb, const GLvisual *vis); + + +#endif diff --git a/src/mgastate.c b/src/mgastate.c new file mode 100644 index 0000000..c20a76f --- /dev/null +++ b/src/mgastate.c @@ -0,0 +1,1205 @@ +/* + * Copyright 2000-2001 VA Linux Systems, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + + +#include "mtypes.h" +#include "colormac.h" +#include "dd.h" + +#include "mm.h" +#include "mgacontext.h" +#include "mgadd.h" +#include "mgastate.h" +#include "mgatex.h" +#include "mgavb.h" +#include "mgatris.h" +#include "mgaioctl.h" +#include "mgaregs.h" + +#include "swrast/swrast.h" +#include "vbo/vbo.h" +#include "tnl/tnl.h" +#include "tnl/t_context.h" +#include "tnl/t_pipeline.h" +#include "swrast_setup/swrast_setup.h" + +#include "xmlpool.h" +#include "drirenderbuffer.h" + + +static void updateSpecularLighting( GLcontext *ctx ); + +static const GLuint mgarop_NoBLK[16] = { + DC_atype_rpl | 0x00000000, DC_atype_rstr | 0x00080000, + DC_atype_rstr | 0x00040000, DC_atype_rpl | 0x000c0000, + DC_atype_rstr | 0x00020000, DC_atype_rstr | 0x000a0000, + DC_atype_rstr | 0x00060000, DC_atype_rstr | 0x000e0000, + DC_atype_rstr | 0x00010000, DC_atype_rstr | 0x00090000, + DC_atype_rstr | 0x00050000, DC_atype_rstr | 0x000d0000, + DC_atype_rpl | 0x00030000, DC_atype_rstr | 0x000b0000, + DC_atype_rstr | 0x00070000, DC_atype_rpl | 0x000f0000 +}; + +/* ============================================================= + * Alpha blending + */ + +static void mgaDDAlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + GLubyte refByte; + GLuint a; + + CLAMPED_FLOAT_TO_UBYTE(refByte, ref); + + switch ( func ) { + case GL_NEVER: + a = AC_atmode_alt; + refByte = 0; + break; + case GL_LESS: + a = AC_atmode_alt; + break; + case GL_GEQUAL: + a = AC_atmode_agte; + break; + case GL_LEQUAL: + a = AC_atmode_alte; + break; + case GL_GREATER: + a = AC_atmode_agt; + break; + case GL_NOTEQUAL: + a = AC_atmode_ane; + break; + case GL_EQUAL: + a = AC_atmode_ae; + break; + case GL_ALWAYS: + a = AC_atmode_noacmp; + break; + default: + a = 0; + break; + } + + MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT ); + mmesa->hw.alpha_func = a | MGA_FIELD( AC_atref, refByte ); +} + +static void updateBlendLogicOp(GLcontext *ctx) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + GLboolean logicOp = RGBA_LOGICOP_ENABLED(ctx); + + MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT ); + + mmesa->hw.blend_func_enable = + (ctx->Color.BlendEnabled && !logicOp) ? ~0 : 0; + + FALLBACK( ctx, MGA_FALLBACK_BLEND, + ctx->Color.BlendEnabled && !logicOp && + mmesa->hw.blend_func == (AC_src_src_alpha_sat | AC_dst_zero) ); +} + +static void mgaDDBlendEquationSeparate(GLcontext *ctx, + GLenum modeRGB, GLenum modeA) +{ + assert( modeRGB == modeA ); + updateBlendLogicOp( ctx ); +} + +static void mgaDDBlendFuncSeparate( GLcontext *ctx, GLenum sfactorRGB, + GLenum dfactorRGB, GLenum sfactorA, + GLenum dfactorA ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + GLuint src; + GLuint dst; + + switch (ctx->Color.BlendSrcRGB) { + case GL_ZERO: + src = AC_src_zero; break; + case GL_SRC_ALPHA: + src = AC_src_src_alpha; break; + case GL_ONE: + default: /* never happens */ + src = AC_src_one; break; + case GL_DST_COLOR: + src = AC_src_dst_color; break; + case GL_ONE_MINUS_DST_COLOR: + src = AC_src_om_dst_color; break; + case GL_ONE_MINUS_SRC_ALPHA: + src = AC_src_om_src_alpha; break; + case GL_DST_ALPHA: + src = (ctx->Visual.alphaBits > 0) + ? AC_src_dst_alpha : AC_src_one; + break; + case GL_ONE_MINUS_DST_ALPHA: + src = (ctx->Visual.alphaBits > 0) + ? AC_src_om_dst_alpha : AC_src_zero; + break; + case GL_SRC_ALPHA_SATURATE: + src = (ctx->Visual.alphaBits > 0) + ? AC_src_src_alpha_sat : AC_src_zero; + break; + } + + switch (ctx->Color.BlendDstRGB) { + case GL_SRC_ALPHA: + dst = AC_dst_src_alpha; break; + case GL_ONE_MINUS_SRC_ALPHA: + dst = AC_dst_om_src_alpha; break; + default: /* never happens */ + case GL_ZERO: + dst = AC_dst_zero; break; + case GL_ONE: + dst = AC_dst_one; break; + case GL_SRC_COLOR: + dst = AC_dst_src_color; break; + case GL_ONE_MINUS_SRC_COLOR: + dst = AC_dst_om_src_color; break; + case GL_DST_ALPHA: + dst = (ctx->Visual.alphaBits > 0) + ? AC_dst_dst_alpha : AC_dst_one; + break; + case GL_ONE_MINUS_DST_ALPHA: + dst = (ctx->Visual.alphaBits > 0) + ? AC_dst_om_dst_alpha : AC_dst_zero; + break; + } + + MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT ); + mmesa->hw.blend_func = (src | dst); + + FALLBACK( ctx, MGA_FALLBACK_BLEND, + ctx->Color.BlendEnabled && !RGBA_LOGICOP_ENABLED(ctx) && + mmesa->hw.blend_func == (AC_src_src_alpha_sat | AC_dst_zero) ); +} + +/* ============================================================= + * Depth testing + */ + +static void mgaDDDepthFunc(GLcontext *ctx, GLenum func) +{ + mgaContextPtr mmesa = MGA_CONTEXT( ctx ); + int zmode; + + switch (func) { + case GL_NEVER: + /* can't do this in h/w, we'll use a s/w fallback */ + FALLBACK (ctx, MGA_FALLBACK_DEPTH, ctx->Depth.Test); + + /* FALLTHROUGH */ + case GL_ALWAYS: + zmode = DC_zmode_nozcmp; break; + case GL_LESS: + zmode = DC_zmode_zlt; break; + case GL_LEQUAL: + zmode = DC_zmode_zlte; break; + case GL_EQUAL: + zmode = DC_zmode_ze; break; + case GL_GREATER: + zmode = DC_zmode_zgt; break; + case GL_GEQUAL: + zmode = DC_zmode_zgte; break; + case GL_NOTEQUAL: + zmode = DC_zmode_zne; break; + default: + zmode = 0; break; + } + + MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT ); + mmesa->hw.zmode &= DC_zmode_MASK; + mmesa->hw.zmode |= zmode; +} + +static void mgaDDDepthMask(GLcontext *ctx, GLboolean flag) +{ + mgaContextPtr mmesa = MGA_CONTEXT( ctx ); + + + MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT ); + mmesa->hw.zmode &= DC_atype_MASK; + mmesa->hw.zmode |= (flag) ? DC_atype_zi : DC_atype_i; +} + + +static void mgaDDClearDepth(GLcontext *ctx, GLclampd d) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + + /* Select the Z depth. The ~ is used because the _MASK values in the + * MGA driver are used to mask OFF the selected bits. In this case, + * we want to mask off everything except the MA_zwidth bits. + */ + switch (mmesa->setup.maccess & ~MA_zwidth_MASK) { + case MA_zwidth_16: mmesa->ClearDepth = d * 0x0000ffff; break; + case MA_zwidth_24: mmesa->ClearDepth = d * 0xffffff00; break; + case MA_zwidth_32: mmesa->ClearDepth = d * 0xffffffff; break; + default: return; + } +} + + +/* ============================================================= + * Fog + */ + + +static void mgaDDFogfv(GLcontext *ctx, GLenum pname, const GLfloat *param) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + + if (pname == GL_FOG_COLOR) { + GLuint color = PACK_COLOR_888((GLubyte)(ctx->Fog.Color[0]*255.0F), + (GLubyte)(ctx->Fog.Color[1]*255.0F), + (GLubyte)(ctx->Fog.Color[2]*255.0F)); + + MGA_STATECHANGE(mmesa, MGA_UPLOAD_CONTEXT); + mmesa->setup.fogcolor = color; + } +} + + +/* ============================================================= + * Scissoring + */ + + +void mgaUpdateClipping(const GLcontext *ctx) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + + if (mmesa->driDrawable) + { + int x1 = mmesa->driDrawable->x + ctx->Scissor.X; + int y1 = mmesa->driDrawable->y + mmesa->driDrawable->h + - (ctx->Scissor.Y + ctx->Scissor.Height); + int x2 = x1 + ctx->Scissor.Width; + int y2 = y1 + ctx->Scissor.Height; + + if (x1 < 0) x1 = 0; + if (y1 < 0) y1 = 0; + if (x2 < 0) x2 = 0; + if (y2 < 0) y2 = 0; + + mmesa->scissor_rect.x1 = x1; + mmesa->scissor_rect.y1 = y1; + mmesa->scissor_rect.x2 = x2; + mmesa->scissor_rect.y2 = y2; + + mmesa->dirty |= MGA_UPLOAD_CLIPRECTS; + } +} + + +static void mgaDDScissor( GLcontext *ctx, GLint x, GLint y, + GLsizei w, GLsizei h ) +{ + if ( ctx->Scissor.Enabled ) { + FLUSH_BATCH( MGA_CONTEXT(ctx) ); /* don't pipeline cliprect changes */ + mgaUpdateClipping( ctx ); + } +} + + +/* ============================================================= + * Culling + */ + + +#define _CULL_DISABLE 0 +#define _CULL_NEGATIVE ((1<<11)|(1<<5)|(1<<16)) +#define _CULL_POSITIVE (1<<11) + +static void mgaDDCullFaceFrontFace(GLcontext *ctx, GLenum unused) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + + MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT ); + if (ctx->Polygon.CullFlag && + ctx->Polygon.CullFaceMode != GL_FRONT_AND_BACK) + { + mmesa->hw.cull = _CULL_NEGATIVE; + + if (ctx->Polygon.CullFaceMode == GL_FRONT) + mmesa->hw.cull ^= (_CULL_POSITIVE ^ _CULL_NEGATIVE); + + if (ctx->Polygon.FrontFace != GL_CCW) + mmesa->hw.cull ^= (_CULL_POSITIVE ^ _CULL_NEGATIVE); + + mmesa->hw.cull_dualtex = mmesa->hw.cull ^ + (_CULL_POSITIVE ^ _CULL_NEGATIVE); /* warp bug? */ + } + else { + mmesa->hw.cull = _CULL_DISABLE; + mmesa->hw.cull_dualtex = _CULL_DISABLE; + } +} + + +/* ============================================================= + * Masks + */ + +static void mgaDDColorMask(GLcontext *ctx, + GLboolean r, GLboolean g, + GLboolean b, GLboolean a ) +{ + mgaContextPtr mmesa = MGA_CONTEXT( ctx ); + mgaScreenPrivate *mgaScreen = mmesa->mgaScreen; + + + GLuint mask = mgaPackColor(mgaScreen->cpp, + ctx->Color.ColorMask[RCOMP], + ctx->Color.ColorMask[GCOMP], + ctx->Color.ColorMask[BCOMP], + ctx->Color.ColorMask[ACOMP]); + + if (mgaScreen->cpp == 2) + mask = mask | (mask << 16); + + if (mmesa->setup.plnwt != mask) { + MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT ); + mmesa->setup.plnwt = mask; + } +} + + +/* ============================================================= + * Polygon state + */ + +static int mgaStipples[16] = { + 0xffff, + 0xa5a5, + 0x5a5a, + 0xa0a0, + 0x5050, + 0x0a0a, + 0x0505, + 0x8020, + 0x0401, + 0x1040, + 0x0208, + 0x0802, + 0x4010, + 0x0104, + 0x2080, + 0x0000 +}; + +/** + * The MGA supports a subset of possible 4x4 stipples natively, GL + * wants 32x32. Fortunately stipple is usually a repeating pattern. + * + * \param ctx GL rendering context to be affected + * \param mask Pointer to the 32x32 stipple mask + */ + +static void mgaDDPolygonStipple( GLcontext *ctx, const GLubyte *mask ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + const GLubyte *m = mask; + GLubyte p[4]; + int i,j,k; + int active = (ctx->Polygon.StippleFlag && + mmesa->raster_primitive == GL_TRIANGLES); + GLuint stipple; + + FLUSH_BATCH(mmesa); + mmesa->haveHwStipple = 0; + + if (active) { + mmesa->dirty |= MGA_UPLOAD_CONTEXT; + mmesa->setup.dwgctl &= ~(0xf<<20); + } + + p[0] = mask[0] & 0xf; p[0] |= p[0] << 4; + p[1] = mask[4] & 0xf; p[1] |= p[1] << 4; + p[2] = mask[8] & 0xf; p[2] |= p[2] << 4; + p[3] = mask[12] & 0xf; p[3] |= p[3] << 4; + + for (k = 0 ; k < 8 ; k++) + for (j = 0 ; j < 4; j++) + for (i = 0 ; i < 4 ; i++) + if (*m++ != p[j]) { + return; + } + + stipple = ( ((p[0] & 0xf) << 0) | + ((p[1] & 0xf) << 4) | + ((p[2] & 0xf) << 8) | + ((p[3] & 0xf) << 12) ); + + for (i = 0 ; i < 16 ; i++) + if (mgaStipples[i] == stipple) { + mmesa->poly_stipple = i<<20; + mmesa->haveHwStipple = 1; + break; + } + + if (active) { + mmesa->setup.dwgctl &= ~(0xf<<20); + mmesa->setup.dwgctl |= mmesa->poly_stipple; + } +} + + +/* ============================================================= + * Rendering attributes + * + * We really don't want to recalculate all this every time we bind a + * texture. These things shouldn't change all that often, so it makes + * sense to break them out of the core texture state update routines. + */ + +static void updateSpecularLighting( GLcontext *ctx ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + unsigned int specen; + + specen = NEED_SECONDARY_COLOR(ctx) ? TMC_specen_enable : 0; + + if ( specen != mmesa->hw.specen ) { + mmesa->hw.specen = specen; + mmesa->dirty |= MGA_UPLOAD_TEX0 | MGA_UPLOAD_TEX1; + } +} + + +/* ============================================================= + * Materials + */ + + +static void mgaDDLightModelfv(GLcontext *ctx, GLenum pname, + const GLfloat *param) +{ + if (pname == GL_LIGHT_MODEL_COLOR_CONTROL) { + FLUSH_BATCH( MGA_CONTEXT(ctx) ); + updateSpecularLighting( ctx ); + } +} + + +/* ============================================================= + * Stencil + */ + + +static void +mgaDDStencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func, GLint ref, + GLuint mask) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + GLuint stencil; + GLuint stencilctl; + + stencil = MGA_FIELD( S_sref, ref ) | MGA_FIELD( S_smsk, mask ); + switch (func) + { + case GL_NEVER: + stencilctl = SC_smode_snever; + break; + case GL_LESS: + stencilctl = SC_smode_slt; + break; + case GL_LEQUAL: + stencilctl = SC_smode_slte; + break; + case GL_GREATER: + stencilctl = SC_smode_sgt; + break; + case GL_GEQUAL: + stencilctl = SC_smode_sgte; + break; + case GL_NOTEQUAL: + stencilctl = SC_smode_sne; + break; + case GL_EQUAL: + stencilctl = SC_smode_se; + break; + case GL_ALWAYS: + default: + stencilctl = SC_smode_salways; + break; + } + + MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT ); + mmesa->hw.stencil &= (S_sref_MASK & S_smsk_MASK); + mmesa->hw.stencil |= stencil; + mmesa->hw.stencilctl &= SC_smode_MASK; + mmesa->hw.stencilctl |= stencilctl; +} + +static void +mgaDDStencilMaskSeparate(GLcontext *ctx, GLenum face, GLuint mask) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + + MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT ); + mmesa->hw.stencil &= S_swtmsk_MASK; + mmesa->hw.stencil |= MGA_FIELD( S_swtmsk, mask ); +} + +static void +mgaDDStencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail, GLenum zfail, + GLenum zpass) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + GLuint stencilctl; + + stencilctl = 0; + switch (ctx->Stencil.FailFunc[0]) + { + case GL_KEEP: + stencilctl |= SC_sfailop_keep; + break; + case GL_ZERO: + stencilctl |= SC_sfailop_zero; + break; + case GL_REPLACE: + stencilctl |= SC_sfailop_replace; + break; + case GL_INCR: + stencilctl |= SC_sfailop_incrsat; + break; + case GL_DECR: + stencilctl |= SC_sfailop_decrsat; + break; + case GL_INCR_WRAP: + stencilctl |= SC_sfailop_incr; + break; + case GL_DECR_WRAP: + stencilctl |= SC_sfailop_decr; + break; + case GL_INVERT: + stencilctl |= SC_sfailop_invert; + break; + default: + break; + } + + switch (ctx->Stencil.ZFailFunc[0]) + { + case GL_KEEP: + stencilctl |= SC_szfailop_keep; + break; + case GL_ZERO: + stencilctl |= SC_szfailop_zero; + break; + case GL_REPLACE: + stencilctl |= SC_szfailop_replace; + break; + case GL_INCR: + stencilctl |= SC_szfailop_incrsat; + break; + case GL_DECR: + stencilctl |= SC_szfailop_decrsat; + break; + case GL_INCR_WRAP: + stencilctl |= SC_szfailop_incr; + break; + case GL_DECR_WRAP: + stencilctl |= SC_szfailop_decr; + break; + case GL_INVERT: + stencilctl |= SC_szfailop_invert; + break; + default: + break; + } + + switch (ctx->Stencil.ZPassFunc[0]) + { + case GL_KEEP: + stencilctl |= SC_szpassop_keep; + break; + case GL_ZERO: + stencilctl |= SC_szpassop_zero; + break; + case GL_REPLACE: + stencilctl |= SC_szpassop_replace; + break; + case GL_INCR: + stencilctl |= SC_szpassop_incrsat; + break; + case GL_DECR: + stencilctl |= SC_szpassop_decrsat; + break; + case GL_INCR_WRAP: + stencilctl |= SC_szpassop_incr; + break; + case GL_DECR_WRAP: + stencilctl |= SC_szpassop_decr; + break; + case GL_INVERT: + stencilctl |= SC_szpassop_invert; + break; + default: + break; + } + + MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT ); + mmesa->hw.stencilctl &= (SC_sfailop_MASK & SC_szfailop_MASK + & SC_szpassop_MASK); + mmesa->hw.stencilctl |= stencilctl; +} + + +/* ============================================================= + * Window position and viewport transformation + */ + +void mgaCalcViewport( GLcontext *ctx ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + const GLfloat *v = ctx->Viewport._WindowMap.m; + GLfloat *m = mmesa->hw_viewport; + + /* See also mga_translate_vertex. + */ + m[MAT_SX] = v[MAT_SX]; + m[MAT_TX] = v[MAT_TX] + mmesa->drawX + SUBPIXEL_X; + m[MAT_SY] = - v[MAT_SY]; + m[MAT_TY] = - v[MAT_TY] + mmesa->driDrawable->h + mmesa->drawY + SUBPIXEL_Y; + m[MAT_SZ] = v[MAT_SZ] * mmesa->depth_scale; + m[MAT_TZ] = v[MAT_TZ] * mmesa->depth_scale; + + mmesa->SetupNewInputs = ~0; +} + +static void mgaViewport( GLcontext *ctx, + GLint x, GLint y, + GLsizei width, GLsizei height ) +{ + mgaCalcViewport( ctx ); +} + +static void mgaDepthRange( GLcontext *ctx, + GLclampd nearval, GLclampd farval ) +{ + mgaCalcViewport( ctx ); +} + + +/* ============================================================= + * Miscellaneous + */ + +static void mgaDDClearColor(GLcontext *ctx, + const GLfloat color[4] ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + GLubyte c[4]; + CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]); + CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]); + CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]); + CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]); + + mmesa->ClearColor = mgaPackColor( mmesa->mgaScreen->cpp, + c[0], c[1], c[2], c[3]); +} + + +/* Fallback to swrast for select and feedback. + */ +static void mgaRenderMode( GLcontext *ctx, GLenum mode ) +{ + FALLBACK( ctx, MGA_FALLBACK_RENDERMODE, (mode != GL_RENDER) ); +} + + +static void mgaDDLogicOp( GLcontext *ctx, GLenum opcode ) +{ + mgaContextPtr mmesa = MGA_CONTEXT( ctx ); + + MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT ); + mmesa->hw.rop = mgarop_NoBLK[ opcode & 0x0f ]; +} + + +static void mga_set_cliprects(mgaContextPtr mmesa) +{ + __DRIdrawablePrivate *driDrawable = mmesa->driDrawable; + + if ((mmesa->draw_buffer != MGA_FRONT) + || (driDrawable->numBackClipRects == 0)) { + if (driDrawable->numClipRects == 0) { + static drm_clip_rect_t zeroareacliprect = {0,0,0,0}; + mmesa->numClipRects = 1; + mmesa->pClipRects = &zeroareacliprect; + } else { + mmesa->numClipRects = driDrawable->numClipRects; + mmesa->pClipRects = driDrawable->pClipRects; + } + mmesa->drawX = driDrawable->x; + mmesa->drawY = driDrawable->y; + } else { + mmesa->numClipRects = driDrawable->numBackClipRects; + mmesa->pClipRects = driDrawable->pBackClipRects; + mmesa->drawX = driDrawable->backX; + mmesa->drawY = driDrawable->backY; + } + + mmesa->setup.dstorg = mmesa->drawOffset; + mmesa->dirty |= MGA_UPLOAD_CONTEXT | MGA_UPLOAD_CLIPRECTS; +} + + +void mgaUpdateRects( mgaContextPtr mmesa, GLuint buffers ) +{ + __DRIdrawablePrivate *const driDrawable = mmesa->driDrawable; + __DRIdrawablePrivate *const driReadable = mmesa->driReadable; + drm_mga_sarea_t *sarea = mmesa->sarea; + + + mmesa->dirty_cliprects = 0; + + driUpdateFramebufferSize(mmesa->glCtx, driDrawable); + if (driDrawable != driReadable) { + driUpdateFramebufferSize(mmesa->glCtx, driReadable); + } + + mga_set_cliprects(mmesa); + + sarea->req_drawable = driDrawable->draw; + sarea->req_draw_buffer = mmesa->draw_buffer; + + mgaUpdateClipping( mmesa->glCtx ); + mgaCalcViewport( mmesa->glCtx ); +} + + +static void mgaDDDrawBuffer(GLcontext *ctx, GLenum mode ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + + FLUSH_BATCH( mmesa ); + + /* + * _DrawDestMask is easier to cope with than <mode>. + */ + switch ( ctx->DrawBuffer->_ColorDrawBufferMask[0] ) { + case BUFFER_BIT_FRONT_LEFT: + mmesa->setup.dstorg = mmesa->mgaScreen->frontOffset; + mmesa->draw_buffer = MGA_FRONT; + break; + case BUFFER_BIT_BACK_LEFT: + mmesa->setup.dstorg = mmesa->mgaScreen->backOffset; + mmesa->draw_buffer = MGA_BACK; + break; + default: + /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */ + FALLBACK( ctx, MGA_FALLBACK_DRAW_BUFFER, GL_TRUE ); + return; + } + + mmesa->dirty |= MGA_UPLOAD_CONTEXT; + mga_set_cliprects(mmesa); + FALLBACK(ctx, MGA_FALLBACK_DRAW_BUFFER, GL_FALSE); +} + + +static void mgaDDReadBuffer(GLcontext *ctx, GLenum mode ) +{ + /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */ +} + + +/* ============================================================= + * State enable/disable + */ + + +static void mgaDDEnable(GLcontext *ctx, GLenum cap, GLboolean state) +{ + mgaContextPtr mmesa = MGA_CONTEXT( ctx ); + + switch(cap) { + case GL_DITHER: + MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT ); + if (!ctx->Color.DitherFlag) + mmesa->setup.maccess |= MA_nodither_enable; + else + mmesa->setup.maccess &= ~MA_nodither_enable; + break; + case GL_LIGHTING: + case GL_COLOR_SUM_EXT: + FLUSH_BATCH( mmesa ); + updateSpecularLighting( ctx ); + break; + case GL_ALPHA_TEST: + MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT ); + mmesa->hw.alpha_func_enable = (state) ? ~0 : 0; + break; + case GL_DEPTH_TEST: + MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT ); + FALLBACK (ctx, MGA_FALLBACK_DEPTH, + ctx->Depth.Func == GL_NEVER && ctx->Depth.Test); + break; + + case GL_SCISSOR_TEST: + FLUSH_BATCH( mmesa ); + mmesa->scissor = state; + mgaUpdateClipping( ctx ); + break; + + case GL_FOG: + MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT ); + if (ctx->Fog.Enabled) + mmesa->setup.maccess |= MA_fogen_enable; + else + mmesa->setup.maccess &= ~MA_fogen_enable; + break; + case GL_CULL_FACE: + mgaDDCullFaceFrontFace( ctx, 0 ); + break; + case GL_TEXTURE_1D: + case GL_TEXTURE_2D: + case GL_TEXTURE_3D: + break; + case GL_POLYGON_STIPPLE: + if (mmesa->haveHwStipple && mmesa->raster_primitive == GL_TRIANGLES) { + MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT ); + mmesa->setup.dwgctl &= ~(0xf<<20); + if (state) + mmesa->setup.dwgctl |= mmesa->poly_stipple; + } + break; + + case GL_BLEND: + case GL_COLOR_LOGIC_OP: + updateBlendLogicOp( ctx ); + break; + + case GL_STENCIL_TEST: + MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT ); + if (mmesa->hw_stencil) { + mmesa->hw.stencil_enable = ( state ) ? ~0 : 0; + } + else { + FALLBACK( ctx, MGA_FALLBACK_STENCIL, state ); + } + default: + break; + } +} + + +/* ============================================================= + */ + +static void mgaDDPrintDirty( const char *msg, GLuint state ) +{ + fprintf(stderr, "%s (0x%03x): %s%s%s%s%s%s%s\n", + msg, + (unsigned int) state, + (state & MGA_WAIT_AGE) ? "wait-age " : "", + (state & MGA_UPLOAD_TEX0IMAGE) ? "upload-tex0-img " : "", + (state & MGA_UPLOAD_TEX1IMAGE) ? "upload-tex1-img " : "", + (state & MGA_UPLOAD_CONTEXT) ? "upload-ctx " : "", + (state & MGA_UPLOAD_TEX0) ? "upload-tex0 " : "", + (state & MGA_UPLOAD_TEX1) ? "upload-tex1 " : "", + (state & MGA_UPLOAD_PIPE) ? "upload-pipe " : "" + ); +} + +/* Push the state into the sarea and/or texture memory. + */ +void mgaEmitHwStateLocked( mgaContextPtr mmesa ) +{ + drm_mga_sarea_t *sarea = mmesa->sarea; + GLcontext * ctx = mmesa->glCtx; + + if (MGA_DEBUG & DEBUG_VERBOSE_MSG) + mgaDDPrintDirty( __FUNCTION__, mmesa->dirty ); + + if (mmesa->dirty & MGA_UPLOAD_CONTEXT) { + mmesa->setup.wflag = _CULL_DISABLE; + if (mmesa->raster_primitive == GL_TRIANGLES) { + if ((ctx->Texture.Unit[0]._ReallyEnabled == TEXTURE_2D_BIT && + ctx->Texture.Unit[1]._ReallyEnabled == TEXTURE_2D_BIT)) { + mmesa->setup.wflag = mmesa->hw.cull_dualtex; + } + else { + mmesa->setup.wflag = mmesa->hw.cull; + } + } + + mmesa->setup.stencil = mmesa->hw.stencil + & mmesa->hw.stencil_enable; + mmesa->setup.stencilctl = mmesa->hw.stencilctl + & mmesa->hw.stencil_enable; + + /* If depth testing is not enabled, then use the no Z-compare / no + * Z-write mode. Otherwise, use whatever is set in hw.zmode. + */ + mmesa->setup.dwgctl &= (DC_zmode_MASK & DC_atype_MASK); + mmesa->setup.dwgctl |= (ctx->Depth.Test) + ? mmesa->hw.zmode : (DC_zmode_nozcmp | DC_atype_i); + + mmesa->setup.dwgctl &= DC_bop_MASK; + mmesa->setup.dwgctl |= RGBA_LOGICOP_ENABLED(ctx) + ? mmesa->hw.rop : mgarop_NoBLK[ GL_COPY & 0x0f ]; + + mmesa->setup.alphactrl &= AC_src_MASK & AC_dst_MASK & AC_atmode_MASK + & AC_atref_MASK & AC_alphasel_MASK; + mmesa->setup.alphactrl |= + (mmesa->hw.alpha_func & mmesa->hw.alpha_func_enable) | + (mmesa->hw.blend_func & mmesa->hw.blend_func_enable) | + ((AC_src_one | AC_dst_zero) & ~mmesa->hw.blend_func_enable) | + mmesa->hw.alpha_sel; + + memcpy( &sarea->context_state, &mmesa->setup, sizeof(mmesa->setup)); + } + + if ((mmesa->dirty & MGA_UPLOAD_TEX0) && mmesa->CurrentTexObj[0]) { + memcpy(&sarea->tex_state[0], + &mmesa->CurrentTexObj[0]->setup, + sizeof(sarea->tex_state[0])); + } + + if ((mmesa->dirty & MGA_UPLOAD_TEX1) && mmesa->CurrentTexObj[1]) { + memcpy(&sarea->tex_state[1], + &mmesa->CurrentTexObj[1]->setup, + sizeof(sarea->tex_state[1])); + } + + if (mmesa->dirty & (MGA_UPLOAD_TEX0 | MGA_UPLOAD_TEX1)) { + sarea->tex_state[0].texctl2 &= ~TMC_specen_enable; + sarea->tex_state[1].texctl2 &= ~TMC_specen_enable; + sarea->tex_state[0].texctl2 |= mmesa->hw.specen; + sarea->tex_state[1].texctl2 |= mmesa->hw.specen; + } + + if (mmesa->dirty & MGA_UPLOAD_PIPE) { +/* mmesa->sarea->wacceptseq = mmesa->hw_primitive; */ + mmesa->sarea->warp_pipe = mmesa->vertex_format; + mmesa->sarea->vertsize = mmesa->vertex_size; + } + + mmesa->sarea->dirty |= mmesa->dirty; + mmesa->dirty &= MGA_UPLOAD_CLIPRECTS; +} + +/* ============================================================= + */ + + +static void mgaDDValidateState( GLcontext *ctx ) +{ + mgaContextPtr mmesa = MGA_CONTEXT( ctx ); + + FLUSH_BATCH( mmesa ); + + if (mmesa->NewGLState & _NEW_TEXTURE) { + mgaUpdateTextureState(ctx); + } + + if (!mmesa->Fallback) { + if (mmesa->NewGLState & _MGA_NEW_RASTERSETUP) { + mgaChooseVertexState( ctx ); + } + + if (mmesa->NewGLState & _MGA_NEW_RENDERSTATE) { + mgaChooseRenderState( ctx ); + } + } + + mmesa->NewGLState = 0; +} + + +static void mgaDDInvalidateState( GLcontext *ctx, GLuint new_state ) +{ + _swrast_InvalidateState( ctx, new_state ); + _swsetup_InvalidateState( ctx, new_state ); + _vbo_InvalidateState( ctx, new_state ); + _tnl_InvalidateState( ctx, new_state ); + MGA_CONTEXT(ctx)->NewGLState |= new_state; +} + + +static void mgaRunPipeline( GLcontext *ctx ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + + if (mmesa->NewGLState) { + mgaDDValidateState( ctx ); + } + + if (mmesa->dirty) { + mgaEmitHwStateLocked( mmesa ); + } + + _tnl_run_pipeline( ctx ); +} + + +void mgaInitState( mgaContextPtr mmesa ) +{ + mgaScreenPrivate *mgaScreen = mmesa->mgaScreen; + GLcontext *ctx = mmesa->glCtx; + + if (ctx->Visual.doubleBufferMode) { + /* use back buffer by default */ + mmesa->draw_buffer = MGA_BACK; + mmesa->drawOffset = mmesa->mgaScreen->backOffset; + mmesa->readOffset = mmesa->mgaScreen->backOffset; + mmesa->setup.dstorg = mgaScreen->backOffset; + } else { + /* use front buffer by default */ + mmesa->draw_buffer = MGA_FRONT; + mmesa->drawOffset = mmesa->mgaScreen->frontOffset; + mmesa->readOffset = mmesa->mgaScreen->frontOffset; + mmesa->setup.dstorg = mgaScreen->frontOffset; + } + + mmesa->setup.maccess = (MA_memreset_disable | + MA_fogen_disable | + MA_tlutload_disable | + MA_nodither_disable | + MA_dit555_disable); + if (driQueryOptioni (&mmesa->optionCache, "color_reduction") != + DRI_CONF_COLOR_REDUCTION_DITHER) + mmesa->setup.maccess |= MA_nodither_enable; + + switch (mmesa->mgaScreen->cpp) { + case 2: + mmesa->setup.maccess |= MA_pwidth_16; + break; + case 4: + mmesa->setup.maccess |= MA_pwidth_32; + break; + default: + fprintf( stderr, "Error: unknown cpp %d, exiting...\n", + mmesa->mgaScreen->cpp ); + exit( 1 ); + } + + switch (mmesa->glCtx->Visual.depthBits) { + case 16: + mmesa->setup.maccess |= MA_zwidth_16; + break; + case 24: + mmesa->setup.maccess |= MA_zwidth_24; + break; + case 32: + mmesa->setup.maccess |= MA_zwidth_32; + break; + } + + mmesa->hw.blend_func = AC_src_one | AC_dst_zero; + mmesa->hw.blend_func_enable = 0; + mmesa->hw.alpha_func = AC_atmode_noacmp | MGA_FIELD( AC_atref, 0x00 ); + mmesa->hw.alpha_func_enable = 0; + mmesa->hw.rop = mgarop_NoBLK[ GL_COPY & 0x0f ]; + mmesa->hw.zmode = DC_zmode_zlt | DC_atype_zi; + mmesa->hw.stencil = MGA_FIELD( S_sref, 0x00) | MGA_FIELD( S_smsk, 0xff ) | + MGA_FIELD( S_swtmsk, 0xff ); + mmesa->hw.stencilctl = SC_smode_salways | SC_sfailop_keep + | SC_szfailop_keep | SC_szpassop_keep; + mmesa->hw.stencil_enable = 0; + mmesa->hw.cull = _CULL_DISABLE; + mmesa->hw.cull_dualtex = _CULL_DISABLE; + mmesa->hw.specen = 0; + mmesa->hw.alpha_sel = AC_alphasel_diffused; + + mmesa->setup.dwgctl = (DC_opcod_trap | + DC_linear_xy | + DC_solid_disable | + DC_arzero_disable | + DC_sgnzero_disable | + DC_shftzero_enable | + MGA_FIELD( DC_bop, 0xC ) | + MGA_FIELD( DC_trans, 0x0 ) | + DC_bltmod_bmonolef | + DC_pattern_disable | + DC_transc_disable | + DC_clipdis_disable); + + mmesa->setup.plnwt = ~0; + mmesa->setup.alphactrl = (AC_amode_alpha_channel | + AC_astipple_disable | + AC_aten_disable); + + mmesa->setup.fogcolor = PACK_COLOR_888((GLubyte)(ctx->Fog.Color[0]*255.0F), + (GLubyte)(ctx->Fog.Color[1]*255.0F), + (GLubyte)(ctx->Fog.Color[2]*255.0F)); + + mmesa->setup.wflag = 0; + mmesa->setup.tdualstage0 = 0; + mmesa->setup.tdualstage1 = 0; + mmesa->setup.fcol = 0; + mmesa->dirty |= MGA_UPLOAD_CONTEXT; + + mmesa->envcolor[0] = 0; + mmesa->envcolor[1] = 0; +} + + +void mgaDDInitStateFuncs( GLcontext *ctx ) +{ + ctx->Driver.UpdateState = mgaDDInvalidateState; + ctx->Driver.Enable = mgaDDEnable; + ctx->Driver.LightModelfv = mgaDDLightModelfv; + ctx->Driver.AlphaFunc = mgaDDAlphaFunc; + ctx->Driver.BlendEquationSeparate = mgaDDBlendEquationSeparate; + ctx->Driver.BlendFuncSeparate = mgaDDBlendFuncSeparate; + ctx->Driver.DepthFunc = mgaDDDepthFunc; + ctx->Driver.DepthMask = mgaDDDepthMask; + ctx->Driver.Fogfv = mgaDDFogfv; + ctx->Driver.Scissor = mgaDDScissor; + ctx->Driver.CullFace = mgaDDCullFaceFrontFace; + ctx->Driver.FrontFace = mgaDDCullFaceFrontFace; + ctx->Driver.ColorMask = mgaDDColorMask; + + ctx->Driver.DrawBuffer = mgaDDDrawBuffer; + ctx->Driver.ReadBuffer = mgaDDReadBuffer; + ctx->Driver.ClearColor = mgaDDClearColor; + ctx->Driver.ClearDepth = mgaDDClearDepth; + ctx->Driver.LogicOpcode = mgaDDLogicOp; + + ctx->Driver.PolygonStipple = mgaDDPolygonStipple; + + ctx->Driver.StencilFuncSeparate = mgaDDStencilFuncSeparate; + ctx->Driver.StencilMaskSeparate = mgaDDStencilMaskSeparate; + ctx->Driver.StencilOpSeparate = mgaDDStencilOpSeparate; + + ctx->Driver.DepthRange = mgaDepthRange; + ctx->Driver.Viewport = mgaViewport; + ctx->Driver.RenderMode = mgaRenderMode; + + ctx->Driver.ClearIndex = 0; + ctx->Driver.IndexMask = 0; + + TNL_CONTEXT(ctx)->Driver.RunPipeline = mgaRunPipeline; +} diff --git a/src/mgastate.h b/src/mgastate.h new file mode 100644 index 0000000..afbe0aa --- /dev/null +++ b/src/mgastate.h @@ -0,0 +1,39 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgastate.h,v 1.5 2002/10/30 12:51:36 alanh Exp $ */ +/* + * Copyright 2000-2001 VA Linux Systems, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#ifndef _MGA_STATE_H +#define _MGA_STATE_H + +extern void mgaInitState( mgaContextPtr mmesa ); +extern void mgaDDInitStateFuncs(GLcontext *ctx); +extern void mgaUpdateClipping(const GLcontext *ctx); +extern void mgaUpdateCull( GLcontext *ctx ); +extern void mgaCalcViewport( GLcontext *ctx ); +extern void mgaUpdateRects( mgaContextPtr mmesa, GLuint buffers ); + +#endif diff --git a/src/mgatex.c b/src/mgatex.c new file mode 100644 index 0000000..a7d7431 --- /dev/null +++ b/src/mgatex.c @@ -0,0 +1,541 @@ +/* + * Copyright 2000-2001 VA Linux Systems, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ +/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgatex.c,v 1.14 2002/10/30 12:51:36 alanh Exp $ */ + +#include "glheader.h" +#include "mm.h" +#include "mgacontext.h" +#include "mgatex.h" +#include "mgaregs.h" +#include "mgatris.h" +#include "mgaioctl.h" + +#include "colormac.h" +#include "context.h" +#include "enums.h" +#include "simple_list.h" +#include "imports.h" +#include "macros.h" +#include "texformat.h" +#include "texstore.h" +#include "teximage.h" +#include "texobj.h" + +#include "swrast/swrast.h" + +#include "xmlpool.h" + +/** + * Set the texture wrap modes. + * Currently \c GL_REPEAT, \c GL_CLAMP and \c GL_CLAMP_TO_EDGE are supported. + * + * \param t Texture object whose wrap modes are to be set + * \param swrap Wrap mode for the \a s texture coordinate + * \param twrap Wrap mode for the \a t texture coordinate + */ + +static void +mgaSetTexWrapping( mgaTextureObjectPtr t, GLenum swrap, GLenum twrap ) +{ + GLboolean is_clamp = GL_FALSE; + GLboolean is_clamp_to_edge = GL_FALSE; + + t->setup.texctl &= (TMC_clampu_MASK & TMC_clampv_MASK); + t->setup.texctl2 &= (TMC_borderen_MASK); + + switch( swrap ) { + case GL_REPEAT: + break; + case GL_CLAMP: + t->setup.texctl |= TMC_clampu_enable; + is_clamp = GL_TRUE; + break; + case GL_CLAMP_TO_EDGE: + t->setup.texctl |= TMC_clampu_enable; + is_clamp_to_edge = GL_TRUE; + break; + default: + _mesa_problem(NULL, "bad S wrap mode in %s", __FUNCTION__); + } + + switch( twrap ) { + case GL_REPEAT: + break; + case GL_CLAMP: + t->setup.texctl |= TMC_clampv_enable; + is_clamp = GL_TRUE; + break; + case GL_CLAMP_TO_EDGE: + t->setup.texctl |= TMC_clampv_enable; + is_clamp_to_edge = GL_TRUE; + break; + default: + _mesa_problem(NULL, "bad T wrap mode in %s", __FUNCTION__); + } + + if ( is_clamp ) { + t->setup.texctl2 |= TMC_borderen_enable; + } + + t->border_fallback = (is_clamp && is_clamp_to_edge); +} + + +/** + * Set the texture magnification and minification modes. + * + * \param t Texture whose filter modes are to be set + * \param minf Texture minification mode + * \param magf Texture magnification mode + */ + +static void +mgaSetTexFilter( mgaTextureObjectPtr t, GLenum minf, GLenum magf ) +{ + GLuint val = 0; + + switch (minf) { + case GL_NEAREST: val = TF_minfilter_nrst; break; + case GL_LINEAR: val = TF_minfilter_bilin; break; + case GL_NEAREST_MIPMAP_NEAREST: val = TF_minfilter_mm1s; break; + case GL_LINEAR_MIPMAP_NEAREST: val = TF_minfilter_mm4s; break; + case GL_NEAREST_MIPMAP_LINEAR: val = TF_minfilter_mm2s; break; + case GL_LINEAR_MIPMAP_LINEAR: val = TF_minfilter_mm8s; break; + default: val = TF_minfilter_nrst; break; + } + + switch (magf) { + case GL_NEAREST: val |= TF_magfilter_nrst; break; + case GL_LINEAR: val |= TF_magfilter_bilin; break; + default: val |= TF_magfilter_nrst; break; + } + + /* See OpenGL 1.2 specification */ + if (magf == GL_LINEAR && (minf == GL_NEAREST_MIPMAP_NEAREST || + minf == GL_NEAREST_MIPMAP_LINEAR)) { + val |= MGA_FIELD( TF_fthres, 0x20 ); /* c = 0.5 */ + } else { + val |= MGA_FIELD( TF_fthres, 0x10 ); /* c = 0 */ + } + + + /* Mask off the bits for the fields we are setting. Remember, the MGA mask + * defines have 0s for the bits in the named fields. This is the opposite + * of most of the other drivers. + */ + + t->setup.texfilter &= (TF_minfilter_MASK & + TF_magfilter_MASK & + TF_fthres_MASK); + t->setup.texfilter |= val; +} + +static void mgaSetTexBorderColor(mgaTextureObjectPtr t, GLubyte color[4]) +{ + t->setup.texbordercol = PACK_COLOR_8888(color[3], color[0], + color[1], color[2] ); +} + + +static const struct gl_texture_format * +mgaChooseTextureFormat( GLcontext *ctx, GLint internalFormat, + GLenum format, GLenum type ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + const GLboolean do32bpt = + ( mmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_32 ); + const GLboolean force16bpt = + ( mmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FORCE_16 ); + (void) format; + + switch ( internalFormat ) { + case 4: + case GL_RGBA: + case GL_COMPRESSED_RGBA: + switch ( type ) { + case GL_UNSIGNED_INT_10_10_10_2: + case GL_UNSIGNED_INT_2_10_10_10_REV: + return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb1555; + case GL_UNSIGNED_SHORT_4_4_4_4: + case GL_UNSIGNED_SHORT_4_4_4_4_REV: + return &_mesa_texformat_argb4444; + case GL_UNSIGNED_SHORT_5_5_5_1: + case GL_UNSIGNED_SHORT_1_5_5_5_REV: + return &_mesa_texformat_argb1555; + default: + return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444; + } + + case 3: + case GL_RGB: + case GL_COMPRESSED_RGB: + switch ( type ) { + case GL_UNSIGNED_SHORT_4_4_4_4: + case GL_UNSIGNED_SHORT_4_4_4_4_REV: + return &_mesa_texformat_argb4444; + case GL_UNSIGNED_SHORT_5_5_5_1: + case GL_UNSIGNED_SHORT_1_5_5_5_REV: + return &_mesa_texformat_argb1555; + case GL_UNSIGNED_SHORT_5_6_5: + case GL_UNSIGNED_SHORT_5_6_5_REV: + return &_mesa_texformat_rgb565; + default: + return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565; + } + + case GL_RGBA8: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: + return !force16bpt ? + &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444; + + case GL_RGBA4: + case GL_RGBA2: + return &_mesa_texformat_argb4444; + + case GL_RGB5_A1: + return &_mesa_texformat_argb1555; + + case GL_RGB8: + case GL_RGB10: + case GL_RGB12: + case GL_RGB16: + return !force16bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565; + + case GL_RGB5: + case GL_RGB4: + case GL_R3_G3_B2: + return &_mesa_texformat_rgb565; + + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA8: + case GL_ALPHA12: + case GL_ALPHA16: + case GL_COMPRESSED_ALPHA: + /* FIXME: This will report incorrect component sizes... */ + return MGA_IS_G400(mmesa) ? &_mesa_texformat_al88 : &_mesa_texformat_argb4444; + + case 1: + case GL_LUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE8: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + case GL_COMPRESSED_LUMINANCE: + /* FIXME: This will report incorrect component sizes... */ + return MGA_IS_G400(mmesa) ? &_mesa_texformat_al88 : &_mesa_texformat_rgb565; + + case 2: + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE4_ALPHA4: + case GL_LUMINANCE6_ALPHA2: + case GL_LUMINANCE8_ALPHA8: + case GL_LUMINANCE12_ALPHA4: + case GL_LUMINANCE12_ALPHA12: + case GL_LUMINANCE16_ALPHA16: + case GL_COMPRESSED_LUMINANCE_ALPHA: + /* FIXME: This will report incorrect component sizes... */ + return MGA_IS_G400(mmesa) ? &_mesa_texformat_al88 : &_mesa_texformat_argb4444; + + case GL_INTENSITY: + case GL_INTENSITY4: + case GL_INTENSITY8: + case GL_INTENSITY12: + case GL_INTENSITY16: + case GL_COMPRESSED_INTENSITY: + /* FIXME: This will report incorrect component sizes... */ + return MGA_IS_G400(mmesa) ? &_mesa_texformat_i8 : &_mesa_texformat_argb4444; + + case GL_YCBCR_MESA: + if (MGA_IS_G400(mmesa) && + (type == GL_UNSIGNED_SHORT_8_8_APPLE || + type == GL_UNSIGNED_BYTE)) + return &_mesa_texformat_ycbcr; + else + return &_mesa_texformat_ycbcr_rev; + + case GL_COLOR_INDEX: + case GL_COLOR_INDEX1_EXT: + case GL_COLOR_INDEX2_EXT: + case GL_COLOR_INDEX4_EXT: + case GL_COLOR_INDEX8_EXT: + case GL_COLOR_INDEX12_EXT: + case GL_COLOR_INDEX16_EXT: + return &_mesa_texformat_ci8; + + default: + _mesa_problem( ctx, "unexpected texture format in %s", __FUNCTION__ ); + return NULL; + } + + return NULL; /* never get here */ +} + + + + +/** + * Allocate space for and load the mesa images into the texture memory block. + * This will happen before drawing with a new texture, or drawing with a + * texture after it was swapped out or teximaged again. + */ + +static mgaTextureObjectPtr +mgaAllocTexObj( struct gl_texture_object *tObj ) +{ + mgaTextureObjectPtr t; + + + t = CALLOC( sizeof( *t ) ); + tObj->DriverData = t; + if ( t != NULL ) { + /* Initialize non-image-dependent parts of the state: + */ + t->base.tObj = tObj; + + t->setup.texctl = TMC_takey_1 | TMC_tamask_0; + t->setup.texctl2 = TMC_ckstransdis_enable; + t->setup.texfilter = TF_filteralpha_enable | TF_uvoffset_OGL; + + t->border_fallback = GL_FALSE; + t->texenv_fallback = GL_FALSE; + + make_empty_list( & t->base ); + + mgaSetTexWrapping( t, tObj->WrapS, tObj->WrapT ); + mgaSetTexFilter( t, tObj->MinFilter, tObj->MagFilter ); + mgaSetTexBorderColor( t, tObj->_BorderChan ); + } + + return( t ); +} + + +static void mgaTexEnv( GLcontext *ctx, GLenum target, + GLenum pname, const GLfloat *param ) +{ + GLuint unit = ctx->Texture.CurrentUnit; + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + + switch( pname ) { + case GL_TEXTURE_ENV_COLOR: { + GLubyte c[4]; + + UNCLAMPED_FLOAT_TO_RGBA_CHAN( c, texUnit->EnvColor ); + mmesa->envcolor[unit] = PACK_COLOR_8888( c[3], c[0], c[1], c[2] ); + break; + } + } +} + + +static void mgaTexImage2D( GLcontext *ctx, GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint height, GLint border, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage ) +{ + driTextureObject * t = (driTextureObject *) texObj->DriverData; + + if ( t != NULL ) { + driSwapOutTextureObject( t ); + } + else { + t = (driTextureObject *) mgaAllocTexObj( texObj ); + if ( t == NULL ) { + _mesa_error( ctx, GL_OUT_OF_MEMORY, "glTexImage2D" ); + return; + } + } + + _mesa_store_teximage2d( ctx, target, level, internalFormat, + width, height, border, format, type, + pixels, packing, texObj, texImage ); + level -= t->firstLevel; + if (level >= 0) + t->dirty_images[0] |= (1UL << level); +} + +static void mgaTexSubImage2D( GLcontext *ctx, + GLenum target, + GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage ) +{ + driTextureObject * t = (driTextureObject *) texObj->DriverData; + + assert( t ); /* this _should_ be true */ + if ( t != NULL ) { + driSwapOutTextureObject( t ); + } + else { + t = (driTextureObject *) mgaAllocTexObj( texObj ); + if ( t == NULL ) { + _mesa_error( ctx, GL_OUT_OF_MEMORY, "glTexImage2D" ); + return; + } + } + + _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width, + height, format, type, pixels, packing, texObj, + texImage); + level -= t->firstLevel; + if (level >= 0) + t->dirty_images[0] |= (1UL << level); +} + + +/** + * Changes variables and flags for a state update, which will happen at the + * next UpdateTextureState + */ + +static void +mgaTexParameter( GLcontext *ctx, GLenum target, + struct gl_texture_object *tObj, + GLenum pname, const GLfloat *params ) +{ + mgaContextPtr mmesa = MGA_CONTEXT( ctx ); + mgaTextureObjectPtr t = (mgaTextureObjectPtr) tObj->DriverData; + + /* If we don't have a hardware texture, it will be automatically + * created with current state before it is used, so we don't have + * to do anything now + */ + if ( (t == NULL) || + (target != GL_TEXTURE_2D && + target != GL_TEXTURE_RECTANGLE_NV) ) { + return; + } + + switch (pname) { + case GL_TEXTURE_MIN_FILTER: + driSwapOutTextureObject( (driTextureObject *) t ); + /* FALLTHROUGH */ + case GL_TEXTURE_MAG_FILTER: + FLUSH_BATCH(mmesa); + mgaSetTexFilter( t, tObj->MinFilter, tObj->MagFilter ); + break; + + case GL_TEXTURE_WRAP_S: + case GL_TEXTURE_WRAP_T: + FLUSH_BATCH(mmesa); + mgaSetTexWrapping(t,tObj->WrapS,tObj->WrapT); + break; + + case GL_TEXTURE_BORDER_COLOR: + FLUSH_BATCH(mmesa); + mgaSetTexBorderColor(t, tObj->_BorderChan); + break; + + case GL_TEXTURE_BASE_LEVEL: + case GL_TEXTURE_MAX_LEVEL: + case GL_TEXTURE_MIN_LOD: + case GL_TEXTURE_MAX_LOD: + /* This isn't the most efficient solution but there doesn't appear to + * be a nice alternative. Since there's no LOD clamping, + * we just have to rely on loading the right subset of mipmap levels + * to simulate a clamped LOD. + */ + driSwapOutTextureObject( (driTextureObject *) t ); + break; + + default: + return; + } +} + + +static void +mgaBindTexture( GLcontext *ctx, GLenum target, + struct gl_texture_object *tObj ) +{ + assert( (target != GL_TEXTURE_2D && target != GL_TEXTURE_RECTANGLE_NV) || + (tObj->DriverData != NULL) ); +} + + +static void +mgaDeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj ) +{ + mgaContextPtr mmesa = MGA_CONTEXT( ctx ); + driTextureObject * t = (driTextureObject *) tObj->DriverData; + + if ( t ) { + if ( mmesa ) { + FLUSH_BATCH( mmesa ); + } + + driDestroyTextureObject( t ); + } + + /* Free mipmap images and the texture object itself */ + _mesa_delete_texture_object(ctx, tObj); +} + + +/** + * Allocate a new texture object. + * Called via ctx->Driver.NewTextureObject. + * Note: this function will be called during context creation to + * allocate the default texture objects. + * Note: we could use containment here to 'derive' the driver-specific + * texture object from the core mesa gl_texture_object. Not done at this time. + */ +static struct gl_texture_object * +mgaNewTextureObject( GLcontext *ctx, GLuint name, GLenum target ) +{ + struct gl_texture_object *obj; + obj = _mesa_new_texture_object(ctx, name, target); + mgaAllocTexObj( obj ); + return obj; +} + + +void +mgaInitTextureFuncs( struct dd_function_table *functions ) +{ + functions->ChooseTextureFormat = mgaChooseTextureFormat; + functions->TexImage2D = mgaTexImage2D; + functions->TexSubImage2D = mgaTexSubImage2D; + functions->BindTexture = mgaBindTexture; + functions->NewTextureObject = mgaNewTextureObject; + functions->DeleteTexture = mgaDeleteTexture; + functions->IsTextureResident = driIsTextureResident; + functions->TexEnv = mgaTexEnv; + functions->TexParameter = mgaTexParameter; +} diff --git a/src/mgatex.h b/src/mgatex.h new file mode 100644 index 0000000..fb7ffcf --- /dev/null +++ b/src/mgatex.h @@ -0,0 +1,51 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgatex.h,v 1.7 2002/10/30 12:51:36 alanh Exp $ */ +/* + * Copyright 2000-2001 VA Linux Systems, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#ifndef MGATEX_INC +#define MGATEX_INC + +#include "mgacontext.h" + +typedef struct mga_texture_object_s *mgaTextureObjectPtr; + + +/* Called before a primitive is rendered to make sure the texture + * state is properly setup. Texture residence is checked later + * when we grab the lock. + */ +void mgaUpdateTextureState( GLcontext *ctx ); + +int mgaUploadTexImages( mgaContextPtr mmesa, mgaTextureObjectPtr t ); + +void mgaDestroyTexObj( mgaContextPtr mmesa, mgaTextureObjectPtr t ); + +void mgaInitTextureFuncs( struct dd_function_table *functions ); + +GLboolean mgaUpdateTextureEnvCombine( GLcontext *ctx, int unit ); + +#endif diff --git a/src/mgatexmem.c b/src/mgatexmem.c new file mode 100644 index 0000000..1874333 --- /dev/null +++ b/src/mgatexmem.c @@ -0,0 +1,278 @@ +/* + * Copyright 2000-2001 VA Linux Systems, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ +/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgatexmem.c,v 1.7 2002/10/30 12:51:36 alanh Exp $ */ + +#include "glheader.h" + +#include "mm.h" +#include "mgacontext.h" +#include "mgatex.h" +#include "mgaregs.h" +#include "mgaioctl.h" +#include "mga_xmesa.h" + +#include "imports.h" +#include "simple_list.h" + +/** + * Destroy any device-dependent state associated with the texture. This may + * include NULLing out hardware state that points to the texture. + */ +void +mgaDestroyTexObj( mgaContextPtr mmesa, mgaTextureObjectPtr t ) +{ + unsigned i; + + + /* See if it was the driver's current object. + */ + + if ( mmesa != NULL ) + { + if ( t->age > mmesa->dirtyAge ) + mmesa->dirtyAge = t->age; + + for ( i = 0 ; i < mmesa->glCtx->Const.MaxTextureUnits ; i++ ) + { + if ( t == mmesa->CurrentTexObj[ i ] ) { + mmesa->CurrentTexObj[ i ] = NULL; + } + } + } +} + + +/** + * Upload a texture image from system memory to either on-card or AGP + * memory. Uploads to on-card memory are performed using an ILOAD operation. + * This is used for both initial loading of the entire image, and texSubImage + * updates. + * + * Performed with the hardware lock held. + * + * Even though this function is named "upload subimage," the entire image + * is uploaded. + * + * \param mmesa Driver context. + * \param t Texture to be uploaded. + * \param hwlevel Mipmap level of the texture to be uploaded. + * + * \bug As mentioned above, this fuction actually copies the entier mipmap + * level. There should be a version of this function that performs + * sub-rectangle uploads. This will perform quite a bit better if only + * a small portion of a larger texture has been updated. Care would + * need to be take with such an implementation once glCopyTexImage has + * been hardware accelerated. + */ +static void mgaUploadSubImage( mgaContextPtr mmesa, + mgaTextureObjectPtr t, GLint hwlevel ) +{ + struct gl_texture_image * texImage; + unsigned offset; + unsigned texelBytes; + unsigned length; + const int level = hwlevel + t->base.firstLevel; + + + if ( (hwlevel < 0) + || (hwlevel >= (MGA_IS_G200(mmesa) + ? G200_TEX_MAXLEVELS : G400_TEX_MAXLEVELS)) ) { + fprintf( stderr, "[%s:%d] level = %d\n", __FILE__, __LINE__, level ); + return; + } + + texImage = t->base.tObj->Image[0][level]; + if ( texImage == NULL ) { + fprintf( stderr, "[%s:%d] Image[%d] = NULL\n", __FILE__, __LINE__, + level ); + return; + } + + + if (texImage->Data == NULL) { + fprintf(stderr, "null texture image data tObj %p level %d\n", + (void *) t->base.tObj, level); + return; + } + + + /* find the proper destination offset for this level */ + if ( MGA_IS_G200(mmesa) ) { + offset = (t->base.memBlock->ofs + t->offsets[hwlevel]); + } + else { + unsigned i; + + offset = t->base.memBlock->ofs; + for ( i = 0 ; i < hwlevel ; i++ ) { + offset += (t->offsets[1] >> (i * 2)); + } + } + + + /* Copy the texture from system memory to a memory space that can be + * directly used by the hardware for texturing. + */ + + texelBytes = texImage->TexFormat->TexelBytes; + length = texImage->Width * texImage->Height * texelBytes; + if ( t->base.heap->heapId == MGA_CARD_HEAP ) { + unsigned tex_offset = 0; + unsigned to_copy; + + + /* We may not be able to upload the entire texture in one batch due to + * register limits or dma buffer limits. Split the copy up into maximum + * sized chunks. + */ + + offset += mmesa->mgaScreen->textureOffset[ t->base.heap->heapId ]; + while ( length != 0 ) { + mgaGetILoadBufferLocked( mmesa ); + + /* The kernel ILOAD ioctl requires that the lenght be an even multiple + * of MGA_ILOAD_ALIGN. + */ + length = ((length) + MGA_ILOAD_MASK) & ~MGA_ILOAD_MASK; + + to_copy = MIN2( length, MGA_BUFFER_SIZE ); + (void) memcpy( mmesa->iload_buffer->address, + (GLubyte *) texImage->Data + tex_offset, to_copy ); + + if ( MGA_DEBUG & DEBUG_VERBOSE_TEXTURE ) + fprintf(stderr, "[%s:%d] address/size = 0x%08lx/%d\n", + __FILE__, __LINE__, + (long) (offset + tex_offset), + to_copy ); + + mgaFireILoadLocked( mmesa, offset + tex_offset, to_copy ); + tex_offset += to_copy; + length -= to_copy; + } + } else { + /* FIXME: the sync for direct copy reduces speed.. */ + /* This works, is slower for uploads to card space and needs + * additional synchronization with the dma stream. + */ + + UPDATE_LOCK(mmesa, DRM_LOCK_FLUSH | DRM_LOCK_QUIESCENT); + + memcpy( mmesa->mgaScreen->texVirtual[t->base.heap->heapId] + offset, + texImage->Data, length ); + + if ( MGA_DEBUG & DEBUG_VERBOSE_TEXTURE ) + fprintf(stderr, "[%s:%d] address/size = 0x%08lx/%d\n", + __FILE__, __LINE__, + (long) (mmesa->mgaScreen->texVirtual[t->base.heap->heapId] + + offset), + length); + } +} + + +/** + * Upload the texture images associated with texture \a t. This might + * require the allocation of texture memory. + * + * \param mmesa Context pointer + * \param t Texture to be uploaded + */ + +int mgaUploadTexImages( mgaContextPtr mmesa, mgaTextureObjectPtr t ) +{ + int i; + int ofs; + + + if ( (t == NULL) || (t->base.totalSize == 0) ) + return 0; + + LOCK_HARDWARE( mmesa ); + + if (t->base.memBlock == NULL ) { + int heap; + + heap = driAllocateTexture( mmesa->texture_heaps, mmesa->nr_heaps, + (driTextureObject *) t ); + if ( heap == -1 ) { + UNLOCK_HARDWARE( mmesa ); + return -1; + } + + ofs = mmesa->mgaScreen->textureOffset[ heap ] + + t->base.memBlock->ofs; + + if ( MGA_IS_G200(mmesa) ) { + t->setup.texorg = ofs; + t->setup.texorg1 = ofs + t->offsets[1]; + t->setup.texorg2 = ofs + t->offsets[2]; + t->setup.texorg3 = ofs + t->offsets[3]; + t->setup.texorg4 = ofs + t->offsets[4]; + } + else { + t->setup.texorg = ofs | TO_texorgoffsetsel; + t->setup.texorg1 = t->offsets[1]; + t->setup.texorg2 = 0; + t->setup.texorg3 = 0; + t->setup.texorg4 = 0; + } + + mmesa->dirty |= MGA_UPLOAD_CONTEXT; + } + + /* Let the world know we've used this memory recently. + */ + driUpdateTextureLRU( (driTextureObject *) t ); + + if (MGA_DEBUG&DEBUG_VERBOSE_TEXTURE) + fprintf(stderr, "[%s:%d] dispatch age: %d age freed memory: %d\n", + __FILE__, __LINE__, + GET_DISPATCH_AGE(mmesa), mmesa->dirtyAge); + + if (mmesa->dirtyAge >= GET_DISPATCH_AGE(mmesa)) + mgaWaitAgeLocked( mmesa, mmesa->dirtyAge ); + + if (t->base.dirty_images[0]) { + const int numLevels = t->base.lastLevel - t->base.firstLevel + 1; + + if (MGA_DEBUG&DEBUG_VERBOSE_TEXTURE) + fprintf(stderr, "[%s:%d] dirty_images[0] = 0x%04x\n", + __FILE__, __LINE__, t->base.dirty_images[0] ); + + for (i = 0 ; i < numLevels ; i++) { + if ( (t->base.dirty_images[0] & (1U << i)) != 0 ) { + mgaUploadSubImage( mmesa, t, i ); + } + } + t->base.dirty_images[0] = 0; + } + + + UNLOCK_HARDWARE( mmesa ); + + return 0; +} diff --git a/src/mgatris.c b/src/mgatris.c new file mode 100644 index 0000000..2b7ea05 --- /dev/null +++ b/src/mgatris.c @@ -0,0 +1,912 @@ +/* + * Copyright 2000-2001 VA Linux Systems, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ +/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgatris.c,v 1.10 2002/10/30 12:51:36 alanh Exp $ */ + +#include "mtypes.h" +#include "macros.h" +#include "colormac.h" +#include "swrast/swrast.h" +#include "swrast_setup/swrast_setup.h" +#include "tnl/t_context.h" +#include "tnl/t_pipeline.h" + +#include "mm.h" +#include "mgacontext.h" +#include "mgaioctl.h" +#include "mgatris.h" +#include "mgavb.h" +#include "mgastate.h" + + +static void mgaRenderPrimitive( GLcontext *ctx, GLenum prim ); + +/*********************************************************************** + * Functions to draw basic primitives * + ***********************************************************************/ + + +#if defined (USE_X86_ASM) +#define EMIT_VERT( j, vb, vertex_size, v ) \ +do { int __tmp; \ + __asm__ __volatile__( "rep ; movsl" \ + : "=%c" (j), "=D" (vb), "=S" (__tmp) \ + : "0" (vertex_size), \ + "D" ((long)vb), \ + "S" ((long)v)); \ +} while (0) +#else +#define EMIT_VERT( j, vb, vertex_size, v ) \ +do { \ + for ( j = 0 ; j < vertex_size ; j++ ) \ + vb[j] = (v)->ui[j]; \ + vb += vertex_size; \ +} while (0) +#endif + +static void __inline__ mga_draw_triangle( mgaContextPtr mmesa, + mgaVertexPtr v0, + mgaVertexPtr v1, + mgaVertexPtr v2 ) +{ + GLuint vertex_size = mmesa->vertex_size; + GLuint *vb = mgaAllocDmaLow( mmesa, 3 * 4 * vertex_size ); + int j; + + EMIT_VERT( j, vb, vertex_size, v0 ); + EMIT_VERT( j, vb, vertex_size, v1 ); + EMIT_VERT( j, vb, vertex_size, v2 ); +} + + +static void __inline__ mga_draw_quad( mgaContextPtr mmesa, + mgaVertexPtr v0, + mgaVertexPtr v1, + mgaVertexPtr v2, + mgaVertexPtr v3 ) +{ + GLuint vertex_size = mmesa->vertex_size; + GLuint *vb = mgaAllocDmaLow( mmesa, 6 * 4 * vertex_size ); + int j; + + EMIT_VERT( j, vb, vertex_size, v0 ); + EMIT_VERT( j, vb, vertex_size, v1 ); + EMIT_VERT( j, vb, vertex_size, v3 ); + EMIT_VERT( j, vb, vertex_size, v1 ); + EMIT_VERT( j, vb, vertex_size, v2 ); + EMIT_VERT( j, vb, vertex_size, v3 ); +} + + +static __inline__ void mga_draw_point( mgaContextPtr mmesa, + mgaVertexPtr tmp ) +{ + GLfloat sz = mmesa->glCtx->Point._Size * .5; + int vertex_size = mmesa->vertex_size; + GLuint *vb = mgaAllocDmaLow( mmesa, 6 * 4 * vertex_size ); + int j; + +#if 0 + v0->v.x += PNT_X_OFFSET - TRI_X_OFFSET; + v0->v.y += PNT_Y_OFFSET - TRI_Y_OFFSET; +#endif + + /* Draw a point as two triangles. + */ + *(float *)&vb[0] = tmp->v.x - sz; + *(float *)&vb[1] = tmp->v.y - sz; + for (j = 2 ; j < vertex_size ; j++) + vb[j] = tmp->ui[j]; + vb += vertex_size; + + *(float *)&vb[0] = tmp->v.x + sz; + *(float *)&vb[1] = tmp->v.y - sz; + for (j = 2 ; j < vertex_size ; j++) + vb[j] = tmp->ui[j]; + vb += vertex_size; + + *(float *)&vb[0] = tmp->v.x + sz; + *(float *)&vb[1] = tmp->v.y + sz; + for (j = 2 ; j < vertex_size ; j++) + vb[j] = tmp->ui[j]; + vb += vertex_size; + + *(float *)&vb[0] = tmp->v.x + sz; + *(float *)&vb[1] = tmp->v.y + sz; + for (j = 2 ; j < vertex_size ; j++) + vb[j] = tmp->ui[j]; + vb += vertex_size; + + *(float *)&vb[0] = tmp->v.x - sz; + *(float *)&vb[1] = tmp->v.y + sz; + for (j = 2 ; j < vertex_size ; j++) + vb[j] = tmp->ui[j]; + vb += vertex_size; + + *(float *)&vb[0] = tmp->v.x - sz; + *(float *)&vb[1] = tmp->v.y - sz; + for (j = 2 ; j < vertex_size ; j++) + vb[j] = tmp->ui[j]; + +#if 0 + v0->v.x -= PNT_X_OFFSET - TRI_X_OFFSET; + v0->v.y -= PNT_Y_OFFSET - TRI_Y_OFFSET; +#endif +} + + +static __inline__ void mga_draw_line( mgaContextPtr mmesa, + mgaVertexPtr v0, + mgaVertexPtr v1 ) +{ + GLuint vertex_size = mmesa->vertex_size; + GLuint *vb = mgaAllocDmaLow( mmesa, 6 * 4 * vertex_size ); + GLfloat dx, dy, ix, iy; + GLfloat width = mmesa->glCtx->Line._Width; + GLint j; + +#if 0 + v0->v.x += LINE_X_OFFSET - TRI_X_OFFSET; + v0->v.y += LINE_Y_OFFSET - TRI_Y_OFFSET; + v1->v.x += LINE_X_OFFSET - TRI_X_OFFSET; + v1->v.y += LINE_Y_OFFSET - TRI_Y_OFFSET; +#endif + + dx = v0->v.x - v1->v.x; + dy = v0->v.y - v1->v.y; + + ix = width * .5; iy = 0; + if (dx * dx > dy * dy) { + iy = ix; ix = 0; + } + + *(float *)&vb[0] = v0->v.x - ix; + *(float *)&vb[1] = v0->v.y - iy; + for (j = 2 ; j < vertex_size ; j++) + vb[j] = v0->ui[j]; + vb += vertex_size; + + *(float *)&vb[0] = v1->v.x + ix; + *(float *)&vb[1] = v1->v.y + iy; + for (j = 2 ; j < vertex_size ; j++) + vb[j] = v1->ui[j]; + vb += vertex_size; + + *(float *)&vb[0] = v0->v.x + ix; + *(float *)&vb[1] = v0->v.y + iy; + for (j = 2 ; j < vertex_size ; j++) + vb[j] = v0->ui[j]; + vb += vertex_size; + + *(float *)&vb[0] = v0->v.x - ix; + *(float *)&vb[1] = v0->v.y - iy; + for (j = 2 ; j < vertex_size ; j++) + vb[j] = v0->ui[j]; + vb += vertex_size; + + *(float *)&vb[0] = v1->v.x - ix; + *(float *)&vb[1] = v1->v.y - iy; + for (j = 2 ; j < vertex_size ; j++) + vb[j] = v1->ui[j]; + vb += vertex_size; + + *(float *)&vb[0] = v1->v.x + ix; + *(float *)&vb[1] = v1->v.y + iy; + for (j = 2 ; j < vertex_size ; j++) + vb[j] = v1->ui[j]; + vb += vertex_size; + +#if 0 + v0->v.x -= LINE_X_OFFSET - TRI_X_OFFSET; + v0->v.y -= LINE_Y_OFFSET - TRI_Y_OFFSET; + v1->v.x -= LINE_X_OFFSET - TRI_X_OFFSET; + v1->v.y -= LINE_Y_OFFSET - TRI_Y_OFFSET; +#endif +} + +/*********************************************************************** + * Macros for t_dd_tritmp.h to draw basic primitives * + ***********************************************************************/ + +#define TRI( a, b, c ) \ +do { \ + if (DO_FALLBACK) \ + mmesa->draw_tri( mmesa, a, b, c ); \ + else \ + mga_draw_triangle( mmesa, a, b, c ); \ +} while (0) + +#define QUAD( a, b, c, d ) \ +do { \ + if (DO_FALLBACK) { \ + mmesa->draw_tri( mmesa, a, b, d ); \ + mmesa->draw_tri( mmesa, b, c, d ); \ + } else { \ + mga_draw_quad( mmesa, a, b, c, d ); \ + } \ +} while (0) + +#define LINE( v0, v1 ) \ +do { \ + if (DO_FALLBACK) \ + mmesa->draw_line( mmesa, v0, v1 ); \ + else { \ + mga_draw_line( mmesa, v0, v1 ); \ + } \ +} while (0) + +#define POINT( v0 ) \ +do { \ + if (DO_FALLBACK) \ + mmesa->draw_point( mmesa, v0 ); \ + else { \ + mga_draw_point( mmesa, v0 ); \ + } \ +} while (0) + + +/*********************************************************************** + * Fallback to swrast for basic primitives * + ***********************************************************************/ + +/* This code is hit only when a mix of accelerated and unaccelerated + * primitives are being drawn, and only for the unaccelerated + * primitives. + */ + +static void +mga_fallback_tri( mgaContextPtr mmesa, + mgaVertex *v0, + mgaVertex *v1, + mgaVertex *v2 ) +{ + GLcontext *ctx = mmesa->glCtx; + SWvertex v[3]; + mga_translate_vertex( ctx, v0, &v[0] ); + mga_translate_vertex( ctx, v1, &v[1] ); + mga_translate_vertex( ctx, v2, &v[2] ); + _swrast_Triangle( ctx, &v[0], &v[1], &v[2] ); +} + + +static void +mga_fallback_line( mgaContextPtr mmesa, + mgaVertex *v0, + mgaVertex *v1 ) +{ + GLcontext *ctx = mmesa->glCtx; + SWvertex v[2]; + mga_translate_vertex( ctx, v0, &v[0] ); + mga_translate_vertex( ctx, v1, &v[1] ); + _swrast_Line( ctx, &v[0], &v[1] ); +} + + +static void +mga_fallback_point( mgaContextPtr mmesa, + mgaVertex *v0 ) +{ + GLcontext *ctx = mmesa->glCtx; + SWvertex v[1]; + mga_translate_vertex( ctx, v0, &v[0] ); + _swrast_Point( ctx, &v[0] ); +} + +/*********************************************************************** + * Build render functions from dd templates * + ***********************************************************************/ + + +#define MGA_UNFILLED_BIT 0x1 +#define MGA_OFFSET_BIT 0x2 +#define MGA_TWOSIDE_BIT 0x4 +#define MGA_FLAT_BIT 0x8 /* mga can't flatshade? */ +#define MGA_FALLBACK_BIT 0x10 +#define MGA_MAX_TRIFUNC 0x20 + +static struct { + tnl_points_func points; + tnl_line_func line; + tnl_triangle_func triangle; + tnl_quad_func quad; +} rast_tab[MGA_MAX_TRIFUNC]; + +#define DO_FALLBACK (IND & MGA_FALLBACK_BIT) +#define DO_OFFSET (IND & MGA_OFFSET_BIT) +#define DO_UNFILLED (IND & MGA_UNFILLED_BIT) +#define DO_TWOSIDE (IND & MGA_TWOSIDE_BIT) +#define DO_FLAT (IND & MGA_FLAT_BIT) +#define DO_TRI 1 +#define DO_QUAD 1 +#define DO_LINE 1 +#define DO_POINTS 1 +#define DO_FULL_QUAD 1 + +#define HAVE_RGBA 1 +#define HAVE_BACK_COLORS 0 +#define HAVE_SPEC 1 +#define HAVE_HW_FLATSHADE 0 +#define VERTEX mgaVertex +#define TAB rast_tab + + +#define DEPTH_SCALE mmesa->depth_scale +#define UNFILLED_TRI unfilled_tri +#define UNFILLED_QUAD unfilled_quad +#define VERT_X(_v) _v->v.x +#define VERT_Y(_v) _v->v.y +#define VERT_Z(_v) _v->v.z +#define AREA_IS_CCW( a ) (a > 0) +#define GET_VERTEX(e) (mmesa->verts + (e * mmesa->vertex_size * sizeof(int))) + +#define VERT_SET_RGBA( v, c ) \ +do { \ + mga_color_t *color = (mga_color_t *)&((v)->ui[4]); \ + UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \ + UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \ + UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \ + UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]); \ +} while (0) + +#define VERT_COPY_RGBA( v0, v1 ) v0->ui[4] = v1->ui[4] + +#define VERT_SET_SPEC( v0, c ) \ +do { \ + UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.red, (c)[0]); \ + UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.green, (c)[1]); \ + UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.blue, (c)[2]); \ +} while (0) + +#define VERT_COPY_SPEC( v0, v1 ) \ +do { \ + v0->v.specular.red = v1->v.specular.red; \ + v0->v.specular.green = v1->v.specular.green; \ + v0->v.specular.blue = v1->v.specular.blue; \ +} while (0) + +#define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[4] +#define VERT_RESTORE_RGBA( idx ) v[idx]->ui[4] = color[idx] +#define VERT_SAVE_SPEC( idx ) spec[idx] = v[idx]->ui[5] +#define VERT_RESTORE_SPEC( idx ) v[idx]->ui[5] = spec[idx] + +#define LOCAL_VARS(n) \ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); \ + GLuint color[n], spec[n]; \ + (void) color; (void) spec; + + + +/*********************************************************************** + * Functions to draw basic unfilled primitives * + ***********************************************************************/ + +#define RASTERIZE(x) if (mmesa->raster_primitive != x) \ + mgaRasterPrimitive( ctx, x, MGA_WA_TRIANGLES ) +#define RENDER_PRIMITIVE mmesa->render_primitive +#define IND MGA_FALLBACK_BIT +#define TAG(x) x +#include "tnl_dd/t_dd_unfilled.h" +#undef IND + +/*********************************************************************** + * Functions to draw GL primitives * + ***********************************************************************/ + +#define IND (0) +#define TAG(x) x +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_OFFSET_BIT) +#define TAG(x) x##_offset +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_TWOSIDE_BIT) +#define TAG(x) x##_twoside +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_TWOSIDE_BIT|MGA_OFFSET_BIT) +#define TAG(x) x##_twoside_offset +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_UNFILLED_BIT) +#define TAG(x) x##_unfilled +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_OFFSET_BIT|MGA_UNFILLED_BIT) +#define TAG(x) x##_offset_unfilled +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_TWOSIDE_BIT|MGA_UNFILLED_BIT) +#define TAG(x) x##_twoside_unfilled +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_TWOSIDE_BIT|MGA_OFFSET_BIT|MGA_UNFILLED_BIT) +#define TAG(x) x##_twoside_offset_unfilled +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_FALLBACK_BIT) +#define TAG(x) x##_fallback +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_OFFSET_BIT|MGA_FALLBACK_BIT) +#define TAG(x) x##_offset_fallback +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_TWOSIDE_BIT|MGA_FALLBACK_BIT) +#define TAG(x) x##_twoside_fallback +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_TWOSIDE_BIT|MGA_OFFSET_BIT|MGA_FALLBACK_BIT) +#define TAG(x) x##_twoside_offset_fallback +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_UNFILLED_BIT|MGA_FALLBACK_BIT) +#define TAG(x) x##_unfilled_fallback +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_OFFSET_BIT|MGA_UNFILLED_BIT|MGA_FALLBACK_BIT) +#define TAG(x) x##_offset_unfilled_fallback +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_TWOSIDE_BIT|MGA_UNFILLED_BIT|MGA_FALLBACK_BIT) +#define TAG(x) x##_twoside_unfilled_fallback +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_TWOSIDE_BIT|MGA_OFFSET_BIT|MGA_UNFILLED_BIT| \ + MGA_FALLBACK_BIT) +#define TAG(x) x##_twoside_offset_unfilled_fallback +#include "tnl_dd/t_dd_tritmp.h" + + +/* Mga doesn't support provoking-vertex flat-shading? + */ +#define IND (MGA_FLAT_BIT) +#define TAG(x) x##_flat +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_OFFSET_BIT|MGA_FLAT_BIT) +#define TAG(x) x##_offset_flat +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_TWOSIDE_BIT|MGA_FLAT_BIT) +#define TAG(x) x##_twoside_flat +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_TWOSIDE_BIT|MGA_OFFSET_BIT|MGA_FLAT_BIT) +#define TAG(x) x##_twoside_offset_flat +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_UNFILLED_BIT|MGA_FLAT_BIT) +#define TAG(x) x##_unfilled_flat +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_OFFSET_BIT|MGA_UNFILLED_BIT|MGA_FLAT_BIT) +#define TAG(x) x##_offset_unfilled_flat +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_TWOSIDE_BIT|MGA_UNFILLED_BIT|MGA_FLAT_BIT) +#define TAG(x) x##_twoside_unfilled_flat +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_TWOSIDE_BIT|MGA_OFFSET_BIT|MGA_UNFILLED_BIT|MGA_FLAT_BIT) +#define TAG(x) x##_twoside_offset_unfilled_flat +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_FALLBACK_BIT|MGA_FLAT_BIT) +#define TAG(x) x##_fallback_flat +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_OFFSET_BIT|MGA_FALLBACK_BIT|MGA_FLAT_BIT) +#define TAG(x) x##_offset_fallback_flat +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_TWOSIDE_BIT|MGA_FALLBACK_BIT|MGA_FLAT_BIT) +#define TAG(x) x##_twoside_fallback_flat +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_TWOSIDE_BIT|MGA_OFFSET_BIT|MGA_FALLBACK_BIT|MGA_FLAT_BIT) +#define TAG(x) x##_twoside_offset_fallback_flat +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_UNFILLED_BIT|MGA_FALLBACK_BIT|MGA_FLAT_BIT) +#define TAG(x) x##_unfilled_fallback_flat +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_OFFSET_BIT|MGA_UNFILLED_BIT|MGA_FALLBACK_BIT|MGA_FLAT_BIT) +#define TAG(x) x##_offset_unfilled_fallback_flat +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_TWOSIDE_BIT|MGA_UNFILLED_BIT|MGA_FALLBACK_BIT|MGA_FLAT_BIT) +#define TAG(x) x##_twoside_unfilled_fallback_flat +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_TWOSIDE_BIT|MGA_OFFSET_BIT|MGA_UNFILLED_BIT| \ + MGA_FALLBACK_BIT|MGA_FLAT_BIT) +#define TAG(x) x##_twoside_offset_unfilled_fallback_flat +#include "tnl_dd/t_dd_tritmp.h" + + +static void init_rast_tab( void ) +{ + init(); + init_offset(); + init_twoside(); + init_twoside_offset(); + init_unfilled(); + init_offset_unfilled(); + init_twoside_unfilled(); + init_twoside_offset_unfilled(); + init_fallback(); + init_offset_fallback(); + init_twoside_fallback(); + init_twoside_offset_fallback(); + init_unfilled_fallback(); + init_offset_unfilled_fallback(); + init_twoside_unfilled_fallback(); + init_twoside_offset_unfilled_fallback(); + + init_flat(); + init_offset_flat(); + init_twoside_flat(); + init_twoside_offset_flat(); + init_unfilled_flat(); + init_offset_unfilled_flat(); + init_twoside_unfilled_flat(); + init_twoside_offset_unfilled_flat(); + init_fallback_flat(); + init_offset_fallback_flat(); + init_twoside_fallback_flat(); + init_twoside_offset_fallback_flat(); + init_unfilled_fallback_flat(); + init_offset_unfilled_fallback_flat(); + init_twoside_unfilled_fallback_flat(); + init_twoside_offset_unfilled_fallback_flat(); +} + +/**********************************************************************/ +/* Render whole begin/end objects */ +/**********************************************************************/ + + +#define VERT(x) (mgaVertex *)(vertptr + ((x)*vertex_size*sizeof(int))) +#define RENDER_POINTS( start, count ) \ + for ( ; start < count ; start++) \ + mga_draw_point( mmesa, VERT(ELT(start)) ); +#define RENDER_LINE( v0, v1 ) \ + mga_draw_line( mmesa, VERT(v0), VERT(v1) ) +#define RENDER_TRI( v0, v1, v2 ) \ + mga_draw_triangle( mmesa, VERT(v0), VERT(v1), VERT(v2) ) +#define RENDER_QUAD( v0, v1, v2, v3 ) \ + mga_draw_quad( mmesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) ) +#define INIT(x) mgaRenderPrimitive( ctx, x ) +#undef LOCAL_VARS +#define LOCAL_VARS \ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); \ + GLubyte *vertptr = (GLubyte *)mmesa->verts; \ + const GLuint vertex_size = mmesa->vertex_size; \ + const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \ + (void) elt; +#define RESET_STIPPLE +#define RESET_OCCLUSION +#define PRESERVE_VB_DEFS +#define ELT(x) x +#define TAG(x) mga_##x##_verts +#include "tnl/t_vb_rendertmp.h" +#undef ELT +#undef TAG +#define TAG(x) mga_##x##_elts +#define ELT(x) elt[x] +#include "tnl/t_vb_rendertmp.h" + + +/**********************************************************************/ +/* Render clipped primitives */ +/**********************************************************************/ + + + +static void mgaRenderClippedPoly( GLcontext *ctx, const GLuint *elts, GLuint n ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &tnl->vb; + GLuint prim = mmesa->render_primitive; + + /* Render the new vertices as an unclipped polygon. + */ + { + GLuint *tmp = VB->Elts; + VB->Elts = (GLuint *)elts; + tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, PRIM_BEGIN|PRIM_END ); + VB->Elts = tmp; + } + + /* Restore the render primitive + */ + if (prim != GL_POLYGON) + tnl->Driver.Render.PrimitiveNotify( ctx, prim ); +} + +static void mgaRenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + tnl->Driver.Render.Line( ctx, ii, jj ); +} + +static void mgaFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts, + GLuint n ) +{ + mgaContextPtr mmesa = MGA_CONTEXT( ctx ); + GLuint vertex_size = mmesa->vertex_size; + GLuint *vb = mgaAllocDmaLow( mmesa, (n-2) * 3 * 4 * vertex_size ); + GLubyte *vertptr = (GLubyte *)mmesa->verts; + const GLuint *start = (const GLuint *)VERT(elts[0]); + int i,j; + + for (i = 2 ; i < n ; i++) { + EMIT_VERT( j, vb, vertex_size, (mgaVertexPtr) VERT(elts[i-1]) ); + EMIT_VERT( j, vb, vertex_size, (mgaVertexPtr) VERT(elts[i]) ); + EMIT_VERT( j, vb, vertex_size, (mgaVertexPtr) start ); + } +} + +/**********************************************************************/ +/* Choose render functions */ +/**********************************************************************/ + + +#define POINT_FALLBACK (DD_POINT_SMOOTH) +#define LINE_FALLBACK (DD_LINE_SMOOTH | DD_LINE_STIPPLE) +#define TRI_FALLBACK (DD_TRI_SMOOTH | DD_TRI_UNFILLED) +#define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK) +#define ANY_RASTER_FLAGS (DD_FLATSHADE|DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET| \ + DD_TRI_UNFILLED) + +void mgaChooseRenderState(GLcontext *ctx) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + GLuint flags = ctx->_TriangleCaps; + GLuint index = 0; + + if (flags & (ANY_FALLBACK_FLAGS|ANY_RASTER_FLAGS|DD_TRI_STIPPLE)) { + if (flags & ANY_RASTER_FLAGS) { + if (flags & DD_TRI_LIGHT_TWOSIDE) index |= MGA_TWOSIDE_BIT; + if (flags & DD_TRI_OFFSET) index |= MGA_OFFSET_BIT; + if (flags & DD_TRI_UNFILLED) index |= MGA_UNFILLED_BIT; + if (flags & DD_FLATSHADE) index |= MGA_FLAT_BIT; + } + + mmesa->draw_point = mga_draw_point; + mmesa->draw_line = mga_draw_line; + mmesa->draw_tri = mga_draw_triangle; + + /* Hook in fallbacks for specific primitives. + */ + if (flags & ANY_FALLBACK_FLAGS) + { + if (flags & POINT_FALLBACK) + mmesa->draw_point = mga_fallback_point; + + if (flags & LINE_FALLBACK) + mmesa->draw_line = mga_fallback_line; + + if (flags & TRI_FALLBACK) + mmesa->draw_tri = mga_fallback_tri; + + index |= MGA_FALLBACK_BIT; + } + + if ((flags & DD_TRI_STIPPLE) && !mmesa->haveHwStipple) { + mmesa->draw_tri = mga_fallback_tri; + index |= MGA_FALLBACK_BIT; + } + } + + if (mmesa->RenderIndex != index) { + mmesa->RenderIndex = index; + + tnl->Driver.Render.Points = rast_tab[index].points; + tnl->Driver.Render.Line = rast_tab[index].line; + tnl->Driver.Render.Triangle = rast_tab[index].triangle; + tnl->Driver.Render.Quad = rast_tab[index].quad; + + if (index == 0) { + tnl->Driver.Render.PrimTabVerts = mga_render_tab_verts; + tnl->Driver.Render.PrimTabElts = mga_render_tab_elts; + tnl->Driver.Render.ClippedLine = line; /* from tritmp.h */ + tnl->Driver.Render.ClippedPolygon = mgaFastRenderClippedPoly; + } else { + tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts; + tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts; + tnl->Driver.Render.ClippedLine = mgaRenderClippedLine; + tnl->Driver.Render.ClippedPolygon = mgaRenderClippedPoly; + } + } +} + +/**********************************************************************/ +/* Runtime render state and callbacks */ +/**********************************************************************/ + + +static GLenum reduced_prim[GL_POLYGON+1] = { + GL_POINTS, + GL_LINES, + GL_LINES, + GL_LINES, + GL_TRIANGLES, + GL_TRIANGLES, + GL_TRIANGLES, + GL_TRIANGLES, + GL_TRIANGLES, + GL_TRIANGLES +}; + + + +/* Always called between RenderStart and RenderFinish --> We already + * hold the lock. + */ +void mgaRasterPrimitive( GLcontext *ctx, GLenum prim, GLuint hwprim ) +{ + mgaContextPtr mmesa = MGA_CONTEXT( ctx ); + + FLUSH_BATCH( mmesa ); + + /* Update culling */ + if (mmesa->raster_primitive != prim) + mmesa->dirty |= MGA_UPLOAD_CONTEXT; + + mmesa->raster_primitive = prim; +/* mmesa->hw_primitive = hwprim; */ + mmesa->hw_primitive = MGA_WA_TRIANGLES; /* disable mgarender.c for now */ + + if (ctx->Polygon.StippleFlag && mmesa->haveHwStipple) + { + mmesa->dirty |= MGA_UPLOAD_CONTEXT; + mmesa->setup.dwgctl &= ~(0xf<<20); + if (mmesa->raster_primitive == GL_TRIANGLES) + mmesa->setup.dwgctl |= mmesa->poly_stipple; + } +} + + + +/* Determine the rasterized primitive when not drawing unfilled + * polygons. + * + * Used only for the default render stage which always decomposes + * primitives to trianges/lines/points. For the accelerated stage, + * which renders strips as strips, the equivalent calculations are + * performed in mgarender.c. + */ +static void mgaRenderPrimitive( GLcontext *ctx, GLenum prim ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + GLuint rprim = reduced_prim[prim]; + + mmesa->render_primitive = prim; + + if (rprim == GL_TRIANGLES && (ctx->_TriangleCaps & DD_TRI_UNFILLED)) + return; + + if (mmesa->raster_primitive != rprim) { + mgaRasterPrimitive( ctx, rprim, MGA_WA_TRIANGLES ); + } +} + +static void mgaRenderFinish( GLcontext *ctx ) +{ + if (MGA_CONTEXT(ctx)->RenderIndex & MGA_FALLBACK_BIT) + _swrast_flush( ctx ); +} + + + +/**********************************************************************/ +/* Manage total rasterization fallbacks */ +/**********************************************************************/ + +static const char * const fallbackStrings[] = { + "Texture mode", + "glDrawBuffer(GL_FRONT_AND_BACK)", + "read buffer", + "glBlendFunc(GL_SRC_ALPHA_SATURATE, GL_ZERO)", + "glRenderMode(selection or feedback)", + "No hardware stencil", + "glDepthFunc( GL_NEVER )", + "Mixing GL_CLAMP_TO_EDGE and GL_CLAMP", + "rasterization fallback option" +}; + +static const char *getFallbackString(GLuint bit) +{ + int i = 0; + while (bit > 1) { + i++; + bit >>= 1; + } + return fallbackStrings[i]; +} + + +void mgaFallback( GLcontext *ctx, GLuint bit, GLboolean mode ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + GLuint oldfallback = mmesa->Fallback; + + if (mode) { + mmesa->Fallback |= bit; + if (oldfallback == 0) { + FLUSH_BATCH(mmesa); + _swsetup_Wakeup( ctx ); + mmesa->RenderIndex = ~0; + if (MGA_DEBUG & DEBUG_VERBOSE_FALLBACK) { + fprintf(stderr, "MGA begin rasterization fallback: 0x%x %s\n", + bit, getFallbackString(bit)); + } + } + } + else { + mmesa->Fallback &= ~bit; + if (oldfallback == bit) { + _swrast_flush( ctx ); + tnl->Driver.Render.Start = mgaCheckTexSizes; + tnl->Driver.Render.PrimitiveNotify = mgaRenderPrimitive; + tnl->Driver.Render.Finish = mgaRenderFinish; + tnl->Driver.Render.BuildVertices = mgaBuildVertices; + mmesa->NewGLState |= (_MGA_NEW_RENDERSTATE | + _MGA_NEW_RASTERSETUP); + if (MGA_DEBUG & DEBUG_VERBOSE_FALLBACK) { + fprintf(stderr, "MGA end rasterization fallback: 0x%x %s\n", + bit, getFallbackString(bit)); + } + } + } +} + + +void mgaDDInitTriFuncs( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + static int firsttime = 1; + if (firsttime) { + init_rast_tab(); + firsttime = 0; + } + + mmesa->RenderIndex = ~0; + + tnl->Driver.Render.Start = mgaCheckTexSizes; + tnl->Driver.Render.Finish = mgaRenderFinish; + tnl->Driver.Render.PrimitiveNotify = mgaRenderPrimitive; + tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple; + tnl->Driver.Render.BuildVertices = mgaBuildVertices; + tnl->Driver.Render.Multipass = NULL; +} diff --git a/src/mgatris.h b/src/mgatris.h new file mode 100644 index 0000000..f3ece3a --- /dev/null +++ b/src/mgatris.h @@ -0,0 +1,52 @@ +/* + * Copyright 2000-2001 VA Linux Systems, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ +/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgatris.h,v 1.10 2002/10/30 12:51:36 alanh Exp $ */ + +#ifndef MGATRIS_INC +#define MGATRIS_INC + +#include "mtypes.h" + +extern void mgaDDInitTriFuncs( GLcontext *ctx ); +extern void mgaChooseRenderState( GLcontext *ctx ); +extern void mgaRasterPrimitive( GLcontext *ctx, GLenum prim, GLuint hwprim ); + +extern void mgaFallback( GLcontext *ctx, GLuint bit, GLboolean mode ); +#define FALLBACK( ctx, bit, mode ) mgaFallback( ctx, bit, mode ) + +#define _MGA_NEW_RENDERSTATE (_DD_NEW_POINT_SMOOTH | \ + _DD_NEW_LINE_SMOOTH | \ + _DD_NEW_LINE_STIPPLE | \ + _DD_NEW_TRI_SMOOTH | \ + _DD_NEW_FLATSHADE | \ + _DD_NEW_TRI_LIGHT_TWOSIDE | \ + _DD_NEW_TRI_OFFSET | \ + _DD_NEW_TRI_UNFILLED | \ + _DD_NEW_TRI_STIPPLE | \ + _NEW_POLYGONSTIPPLE) + +#endif diff --git a/src/mgavb.c b/src/mgavb.c new file mode 100644 index 0000000..902d8bd --- /dev/null +++ b/src/mgavb.c @@ -0,0 +1,480 @@ +/* + * Copyright 2000-2001 VA Linux Systems, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ +/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgavb.c,v 1.15 2003/03/26 20:43:49 tsi Exp $ */ + +#include <stdlib.h> +#include "mgacontext.h" +#include "mgavb.h" +#include "mgatris.h" +#include "mgaioctl.h" +#include "mga_xmesa.h" + +#include "glheader.h" +#include "mtypes.h" +#include "imports.h" +#include "macros.h" +#include "colormac.h" + +#include "tnl/t_context.h" +#include "swrast_setup/swrast_setup.h" +#include "swrast/swrast.h" + + +#define MGA_TEX1_BIT 0x1 +#define MGA_TEX0_BIT 0x2 +#define MGA_RGBA_BIT 0x4 +#define MGA_SPEC_BIT 0x8 +#define MGA_FOG_BIT 0x10 +#define MGA_XYZW_BIT 0x20 +#define MGA_PTEX_BIT 0x40 +#define MGA_MAX_SETUP 0x80 + +static struct { + void (*emit)( GLcontext *, GLuint, GLuint, void *, GLuint ); + tnl_interp_func interp; + tnl_copy_pv_func copy_pv; + GLboolean (*check_tex_sizes)( GLcontext *ctx ); + GLuint vertex_size; + GLuint vertex_format; +} setup_tab[MGA_MAX_SETUP]; + + +#define TINY_VERTEX_FORMAT 0 +#define NOTEX_VERTEX_FORMAT 0 +#define TEX0_VERTEX_FORMAT (MGA_A|MGA_S|MGA_F) +#define TEX1_VERTEX_FORMAT (MGA_A|MGA_S|MGA_F|MGA_T2) +#define PROJ_TEX1_VERTEX_FORMAT 0 +#define TEX2_VERTEX_FORMAT 0 +#define TEX3_VERTEX_FORMAT 0 +#define PROJ_TEX3_VERTEX_FORMAT 0 + +#define DO_XYZW (IND & MGA_XYZW_BIT) +#define DO_RGBA (IND & MGA_RGBA_BIT) +#define DO_SPEC (IND & MGA_SPEC_BIT) +#define DO_FOG (IND & MGA_FOG_BIT) +#define DO_TEX0 (IND & MGA_TEX0_BIT) +#define DO_TEX1 (IND & MGA_TEX1_BIT) +#define DO_TEX2 0 +#define DO_TEX3 0 +#define DO_PTEX (IND & MGA_PTEX_BIT) + + +#define VERTEX mgaVertex +#define VERTEX_COLOR mga_color_t +#define LOCALVARS mgaContextPtr mmesa = MGA_CONTEXT(ctx); +#define GET_VIEWPORT_MAT() mmesa->hw_viewport +#define GET_TEXSOURCE(n) mmesa->tmu_source[n] +#define GET_VERTEX_FORMAT() mmesa->vertex_format +#define GET_VERTEX_STORE() mmesa->verts +#define GET_VERTEX_SIZE() mmesa->vertex_size * sizeof(GLuint) + +#define HAVE_HW_VIEWPORT 0 +#define HAVE_HW_DIVIDE 0 +#define HAVE_RGBA_COLOR 0 +#define HAVE_TINY_VERTICES 0 +#define HAVE_NOTEX_VERTICES 0 +#define HAVE_TEX0_VERTICES 1 +#define HAVE_TEX1_VERTICES 1 +#define HAVE_TEX2_VERTICES 0 +#define HAVE_TEX3_VERTICES 0 +#define HAVE_PTEX_VERTICES 0 + +#define UNVIEWPORT_VARS \ + const GLfloat dx = - mmesa->drawX - SUBPIXEL_X; \ + const GLfloat dy = (mmesa->driDrawable->h + \ + mmesa->drawY + SUBPIXEL_Y); \ + const GLfloat sz = 1.0 / mmesa->depth_scale + +#define UNVIEWPORT_X(x) x + dx; +#define UNVIEWPORT_Y(y) - y + dy; +#define UNVIEWPORT_Z(z) z * sz; + +#define PTEX_FALLBACK() FALLBACK(ctx, MGA_FALLBACK_TEXTURE, 1) + +#define INTERP_VERTEX setup_tab[mmesa->SetupIndex].interp +#define COPY_PV_VERTEX setup_tab[mmesa->SetupIndex].copy_pv + + +/*********************************************************************** + * Generate pv-copying and translation functions * + ***********************************************************************/ + +#define TAG(x) mga_##x +#include "tnl_dd/t_dd_vb.c" + +/*********************************************************************** + * Generate vertex emit and interp functions * + ***********************************************************************/ + + +#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT) +#define TAG(x) x##_wg +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_SPEC_BIT) +#define TAG(x) x##_wgs +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_TEX0_BIT) +#define TAG(x) x##_wgt0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_TEX0_BIT|MGA_TEX1_BIT) +#define TAG(x) x##_wgt0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_TEX0_BIT|MGA_PTEX_BIT) +#define TAG(x) x##_wgpt0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_SPEC_BIT|MGA_TEX0_BIT) +#define TAG(x) x##_wgst0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_SPEC_BIT|MGA_TEX0_BIT|MGA_TEX1_BIT) +#define TAG(x) x##_wgst0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_SPEC_BIT|MGA_TEX0_BIT|MGA_PTEX_BIT) +#define TAG(x) x##_wgspt0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_FOG_BIT) +#define TAG(x) x##_wgf +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_FOG_BIT|MGA_SPEC_BIT) +#define TAG(x) x##_wgfs +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_FOG_BIT|MGA_TEX0_BIT) +#define TAG(x) x##_wgft0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_FOG_BIT|MGA_TEX0_BIT|MGA_TEX1_BIT) +#define TAG(x) x##_wgft0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_FOG_BIT|MGA_TEX0_BIT|MGA_PTEX_BIT) +#define TAG(x) x##_wgfpt0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_FOG_BIT|MGA_SPEC_BIT|MGA_TEX0_BIT) +#define TAG(x) x##_wgfst0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_FOG_BIT|MGA_SPEC_BIT|MGA_TEX0_BIT|MGA_TEX1_BIT) +#define TAG(x) x##_wgfst0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_FOG_BIT|MGA_SPEC_BIT|MGA_TEX0_BIT|MGA_PTEX_BIT) +#define TAG(x) x##_wgfspt0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_TEX0_BIT) +#define TAG(x) x##_t0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_TEX0_BIT|MGA_TEX1_BIT) +#define TAG(x) x##_t0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_FOG_BIT) +#define TAG(x) x##_f +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_FOG_BIT|MGA_TEX0_BIT) +#define TAG(x) x##_ft0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_FOG_BIT|MGA_TEX0_BIT|MGA_TEX1_BIT) +#define TAG(x) x##_ft0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_RGBA_BIT) +#define TAG(x) x##_g +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_RGBA_BIT|MGA_SPEC_BIT) +#define TAG(x) x##_gs +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_RGBA_BIT|MGA_TEX0_BIT) +#define TAG(x) x##_gt0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_RGBA_BIT|MGA_TEX0_BIT|MGA_TEX1_BIT) +#define TAG(x) x##_gt0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_RGBA_BIT|MGA_SPEC_BIT|MGA_TEX0_BIT) +#define TAG(x) x##_gst0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_RGBA_BIT|MGA_SPEC_BIT|MGA_TEX0_BIT|MGA_TEX1_BIT) +#define TAG(x) x##_gst0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_RGBA_BIT|MGA_FOG_BIT) +#define TAG(x) x##_gf +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_RGBA_BIT|MGA_FOG_BIT|MGA_SPEC_BIT) +#define TAG(x) x##_gfs +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_RGBA_BIT|MGA_FOG_BIT|MGA_TEX0_BIT) +#define TAG(x) x##_gft0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_RGBA_BIT|MGA_FOG_BIT|MGA_TEX0_BIT|MGA_TEX1_BIT) +#define TAG(x) x##_gft0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_RGBA_BIT|MGA_FOG_BIT|MGA_SPEC_BIT|MGA_TEX0_BIT) +#define TAG(x) x##_gfst0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_RGBA_BIT|MGA_FOG_BIT|MGA_SPEC_BIT|MGA_TEX0_BIT|MGA_TEX1_BIT) +#define TAG(x) x##_gfst0t1 +#include "tnl_dd/t_dd_vbtmp.h" + + +static void init_setup_tab( void ) +{ + init_wg(); + init_wgs(); + init_wgt0(); + init_wgt0t1(); + init_wgpt0(); + init_wgst0(); + init_wgst0t1(); + init_wgspt0(); + init_wgf(); + init_wgfs(); + init_wgft0(); + init_wgft0t1(); + init_wgfpt0(); + init_wgfst0(); + init_wgfst0t1(); + init_wgfspt0(); + init_t0(); + init_t0t1(); + init_f(); + init_ft0(); + init_ft0t1(); + init_g(); + init_gs(); + init_gt0(); + init_gt0t1(); + init_gst0(); + init_gst0t1(); + init_gf(); + init_gfs(); + init_gft0(); + init_gft0t1(); + init_gfst0(); + init_gfst0t1(); +} + + + + +void mgaPrintSetupFlags(char *msg, GLuint flags ) +{ + fprintf(stderr, "%s: %d %s%s%s%s%s%s\n", + msg, + (int)flags, + (flags & MGA_XYZW_BIT) ? " xyzw," : "", + (flags & MGA_RGBA_BIT) ? " rgba," : "", + (flags & MGA_SPEC_BIT) ? " spec," : "", + (flags & MGA_FOG_BIT) ? " fog," : "", + (flags & MGA_TEX0_BIT) ? " tex-0," : "", + (flags & MGA_TEX1_BIT) ? " tex-1," : ""); +} + + +void mgaCheckTexSizes( GLcontext *ctx ) +{ + mgaContextPtr mmesa = MGA_CONTEXT( ctx ); + TNLcontext *tnl = TNL_CONTEXT(ctx); + + /*fprintf(stderr, "%s\n", __FUNCTION__);*/ + + if (!setup_tab[mmesa->SetupIndex].check_tex_sizes(ctx)) { + mmesa->SetupIndex |= MGA_PTEX_BIT; + mmesa->SetupNewInputs = ~0; + + if (!mmesa->Fallback && + !(ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) { + tnl->Driver.Render.Interp = setup_tab[mmesa->SetupIndex].interp; + tnl->Driver.Render.CopyPV = setup_tab[mmesa->SetupIndex].copy_pv; + } + if (mmesa->Fallback) { + tnl->Driver.Render.Start(ctx); + } + } +} + + +void mgaBuildVertices( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint newinputs ) +{ + mgaContextPtr mmesa = MGA_CONTEXT( ctx ); + GLuint stride = mmesa->vertex_size * sizeof(int); + GLubyte *v = ((GLubyte *)mmesa->verts + (start * stride)); + + newinputs |= mmesa->SetupNewInputs; + mmesa->SetupNewInputs = 0; + + if (!newinputs) + return; + + if (newinputs & VERT_BIT_POS) { + setup_tab[mmesa->SetupIndex].emit( ctx, start, count, v, stride ); + } else { + GLuint ind = 0; + + if (newinputs & VERT_BIT_COLOR0) + ind |= MGA_RGBA_BIT; + + if (newinputs & VERT_BIT_COLOR1) + ind |= MGA_SPEC_BIT; + + if (newinputs & VERT_BIT_TEX0) + ind |= MGA_TEX0_BIT; + + if (newinputs & VERT_BIT_TEX1) + ind |= MGA_TEX0_BIT|MGA_TEX1_BIT; + + if (newinputs & VERT_BIT_FOG) + ind |= MGA_FOG_BIT; + + if (mmesa->SetupIndex & MGA_PTEX_BIT) + ind = ~0; + + ind &= mmesa->SetupIndex; + + if (ind) { + setup_tab[ind].emit( ctx, start, count, v, stride ); + } + } +} + + +void mgaChooseVertexState( GLcontext *ctx ) +{ + mgaContextPtr mmesa = MGA_CONTEXT( ctx ); + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLuint ind = MGA_XYZW_BIT|MGA_RGBA_BIT; + + if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) + ind |= MGA_SPEC_BIT; + + if (ctx->Fog.Enabled) + ind |= MGA_FOG_BIT; + + if (ctx->Texture._EnabledUnits & 0x2) { + /* unit 1 enabled */ + if (ctx->Texture._EnabledUnits & 0x1) { + /* unit 0 enabled */ + ind |= MGA_TEX1_BIT|MGA_TEX0_BIT; + } + else { + ind |= MGA_TEX0_BIT; + } + } + else if (ctx->Texture._EnabledUnits & 0x1) { + /* unit 0 enabled */ + ind |= MGA_TEX0_BIT; + } + + mmesa->SetupIndex = ind; + + if (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED)) { + tnl->Driver.Render.Interp = mga_interp_extras; + tnl->Driver.Render.CopyPV = mga_copy_pv_extras; + } else { + tnl->Driver.Render.Interp = setup_tab[ind].interp; + tnl->Driver.Render.CopyPV = setup_tab[ind].copy_pv; + } + + if (setup_tab[ind].vertex_format != mmesa->vertex_format) { + FLUSH_BATCH(mmesa); + mmesa->dirty |= MGA_UPLOAD_PIPE; + mmesa->vertex_format = setup_tab[ind].vertex_format; + mmesa->vertex_size = setup_tab[ind].vertex_size; + } +} + + + +void *mga_emit_contiguous_verts( GLcontext *ctx, + GLuint start, + GLuint count, + void *dest) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + GLuint stride = mmesa->vertex_size * 4; + setup_tab[mmesa->SetupIndex].emit( ctx, start, count, dest, stride ); + return (void *)((char *)dest + stride * (count - start)); +} + + + +void mgaInitVB( GLcontext *ctx ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + GLuint size = TNL_CONTEXT(ctx)->vb.Size; + + mmesa->verts = (GLubyte *)ALIGN_MALLOC(size * sizeof(mgaVertex), 32); + + { + static int firsttime = 1; + if (firsttime) { + init_setup_tab(); + firsttime = 0; + } + } + + mmesa->dirty |= MGA_UPLOAD_PIPE; + mmesa->vertex_format = setup_tab[0].vertex_format; + mmesa->vertex_size = setup_tab[0].vertex_size; +} + + +void mgaFreeVB( GLcontext *ctx ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + if (mmesa->verts) { + ALIGN_FREE(mmesa->verts); + mmesa->verts = 0; + } +} + diff --git a/src/mgavb.h b/src/mgavb.h new file mode 100644 index 0000000..5f6454a --- /dev/null +++ b/src/mgavb.h @@ -0,0 +1,66 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgavb.h,v 1.8 2002/10/30 12:51:36 alanh Exp $ */ +/* + * Copyright 2000-2001 VA Linux Systems, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#ifndef MGAVB_INC +#define MGAVB_INC + +#include "mtypes.h" +#include "mgacontext.h" +#include "swrast/swrast.h" + +#define _MGA_NEW_RASTERSETUP (_NEW_TEXTURE | \ + _DD_NEW_SEPARATE_SPECULAR | \ + _DD_NEW_TRI_UNFILLED | \ + _DD_NEW_TRI_LIGHT_TWOSIDE | \ + _NEW_FOG) + + +extern void mgaChooseVertexState( GLcontext *ctx ); +extern void mgaCheckTexSizes( GLcontext *ctx ); +extern void mgaBuildVertices( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint newinputs ); + +extern void mgaPrintSetupFlags(char *msg, GLuint flags ); + +extern void mgaInitVB( GLcontext *ctx ); +extern void mgaFreeVB( GLcontext *ctx ); + +extern void *mga_emit_contiguous_verts( GLcontext *ctx, + GLuint start, + GLuint count, + void *dest ); + +extern void mga_translate_vertex(GLcontext *ctx, + const mgaVertex *src, + SWvertex *dst); + +extern void mga_print_vertex( GLcontext *ctx, const mgaVertex *v ); + +#endif diff --git a/src/server/mga.h b/src/server/mga.h new file mode 100644 index 0000000..830d48d --- /dev/null +++ b/src/server/mga.h @@ -0,0 +1,115 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/mga/mga.h,v 1.85 2002/12/16 16:19:17 dawes Exp $ */ +/* + * MGA Millennium (MGA2064W) functions + * + * Copyright 1996 The XFree86 Project, Inc. + * + * Authors + * Dirk Hohndel + * hohndel@XFree86.Org + * David Dawes + * dawes@XFree86.Org + */ + +#ifndef MGA_H +#define MGA_H + + +#include "xf86drm.h" +#include "linux/types.h" + + +#define PCI_CHIP_MGA2085 0x0518 +#define PCI_CHIP_MGA2064 0x0519 +#define PCI_CHIP_MGA1064 0x051A +#define PCI_CHIP_MGA2164 0x051B +#define PCI_CHIP_MGA2164_AGP 0x051F +#define PCI_CHIP_MGAG200_PCI 0x0520 +#define PCI_CHIP_MGAG200 0x0521 +#define PCI_CHIP_MGAG400 0x0525 +#define PCI_CHIP_MGAG550 0x2527 +#define PCI_CHIP_MGAG100_PCI 0x1000 +#define PCI_CHIP_MGAG100 0x1001 + + +# define MMIO_IN8(base, offset) \ + *(volatile unsigned char *)(((unsigned char*)(base)) + (offset)) +# define MMIO_IN16(base, offset) \ + *(volatile unsigned short *)(void *)(((unsigned char*)(base)) + (offset)) +# define MMIO_IN32(base, offset) \ + *(volatile unsigned int *)(void *)(((unsigned char*)(base)) + (offset)) +# define MMIO_OUT8(base, offset, val) \ + *(volatile unsigned char *)(((unsigned char*)(base)) + (offset)) = (val) +# define MMIO_OUT16(base, offset, val) \ + *(volatile unsigned short *)(void *)(((unsigned char*)(base)) + (offset)) = (val) +# define MMIO_OUT32(base, offset, val) \ + *(volatile unsigned int *)(void *)(((unsigned char*)(base)) + (offset)) = (val) + +#define INREG8(addr) MMIO_IN8(pMga->IOBase, addr) +#define INREG16(addr) MMIO_IN16(pMga->IOBase, addr) +#define INREG(addr) MMIO_IN32(pMga->IOBase, addr) +#define OUTREG8(addr, val) MMIO_OUT8(pMga->IOBase, addr, val) +#define OUTREG16(addr, val) MMIO_OUT16(pMga->IOBase, addr, val) +#define OUTREG(addr, val) MMIO_OUT32(pMga->IOBase, addr, val) + +#define MGAIOMAPSIZE 0x00004000 + + +typedef struct { + int Chipset; /**< \brief Chipset number */ + + int irq; /**< \brief IRQ number */ + + + int frontOffset; /**< \brief Front color buffer offset */ + int frontPitch; /**< \brief Front color buffer pitch */ + int backOffset; /**< \brief Back color buffer offset */ + int backPitch; /**< \brief Back color buffer pitch */ + int depthOffset; /**< \brief Depth buffer offset */ + int depthPitch; /**< \brief Depth buffer pitch */ + int textureOffset; /**< \brief Texture area offset */ + int textureSize; /**< \brief Texture area size */ + int logTextureGranularity; + + /** + * \name AGP + */ + /*@{*/ + drmSize agpSize; /**< \brief AGP map size */ + int agpMode; /**< \brief AGP mode */ + /*@}*/ + + drmRegion agp; + + /* PCI mappings */ + drmRegion registers; + drmRegion status; + + /* AGP mappings */ + drmRegion warp; + drmRegion primary; + drmRegion buffers; + drmRegion agpTextures; + + drmBufMapPtr drmBuffers; + + unsigned long IOAddress; + unsigned char *IOBase; + int HasSDRAM; + + __u32 reg_ien; +} MGARec, *MGAPtr; + + + +#define MGA_FRONT 0x1 +#define MGA_BACK 0x2 +#define MGA_DEPTH 0x4 + +#define MGA_AGP_1X_MODE 0x01 +#define MGA_AGP_2X_MODE 0x02 +#define MGA_AGP_4X_MODE 0x04 +#define MGA_AGP_MODE_MASK 0x07 + + +#endif diff --git a/src/server/mga_bios.h b/src/server/mga_bios.h new file mode 100644 index 0000000..8fbf619 --- /dev/null +++ b/src/server/mga_bios.h @@ -0,0 +1,143 @@ +/* $XConsortium: mga_bios.h /main/2 1996/10/28 04:48:23 kaleb $ */ +#ifndef MGA_BIOS_H +#define MGA_BIOS_H + +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/mga/mga_bios.h,v 1.3 1998/07/25 16:55:51 dawes Exp $ */ + +/* + * MGABiosInfo - This struct describes the video BIOS info block. + * + * DESCRIPTION + * Do not mess with this, unless you know what you are doing. + * The data lengths and types are critical. + * + * HISTORY + * October 7, 1996 - [aem] Andrew E. Mileski + * This struct was shamelessly stolen from the MGA DDK. + * It has been reformatted, and the data types changed. + */ +typedef struct { + /* Length of this structure in bytes */ + __u16 StructLen; + + /* + * Unique number identifying the product type + * 0 : MGA-S1P20 (2MB base with 175MHz Ramdac) + * 1 : MGA-S1P21 (2MB base with 220MHz Ramdac) + * 2 : Reserved + * 3 : Reserved + * 4 : MGA-S1P40 (4MB base with 175MHz Ramdac) + * 5 : MGA-S1P41 (4MB base with 220MHz Ramdac) + */ + __u16 ProductID; + + /* Serial number of the board */ + __u8 SerNo[ 10 ]; + + /* + * Manufacturing date of the board (at product test) + * Format: yyyy yyym mmmd dddd + */ + __u16 ManufDate; + + /* Identification of manufacturing site */ + __u16 ManufId; + + /* + * Number and revision level of the PCB + * Format: nnnn nnnn nnnr rrrr + * n = PCB number ex:576 (from 0->2047) + * r = PCB revision (from 0->31) + */ + __u16 PCBInfo; + + /* Identification of any PMBs */ + __u16 PMBInfo; + + /* + * Bit 0-7 : Ramdac speed (0=175MHz, 1=220MHz) + * Bit 8-15 : Ramdac type (0=TVP3026, 1=TVP3027) + */ + __u16 RamdacType; + + /* Maximum PCLK of the ramdac */ + __u16 PclkMax; + + /* Maximum LDCLK supported by the WRAM memory */ + __u16 LclkMax; + + /* Maximum MCLK of base board */ + __u16 ClkBase; + + /* Maximum MCLK of 4Mb board */ + __u16 Clk4MB; + + /* Maximum MCLK of 8Mb board */ + __u16 Clk8MB; + + /* Maximum MCLK of board with multimedia module */ + __u16 ClkMod; + + /* Diagnostic test pass frequency */ + __u16 TestClk; + + /* Default VGA mode1 pixel frequency */ + __u16 VGAFreq1; + + /* Default VGA mode2 pixel frequency */ + __u16 VGAFreq2; + + /* Date of last BIOS programming/update */ + __u16 ProgramDate; + + /* Number of times BIOS has been programmed */ + __u16 ProgramCnt; + + /* Support for up to 32 hardware/software options */ + __u32 Options; + + /* Support for up to 32 hardware/software features */ + __u32 FeatFlag; + + /* Definition of VGA mode MCLK */ + __u16 VGAClk; + + /* Indicate the revision level of this header struct */ + __u16 StructRev; + + __u16 Reserved[ 3 ]; +} MGABiosInfo; + +/* from the PINS structure, refer pins info from MGA */ +typedef struct tagParamMGA { + __u16 PinID; /* 0 */ + __u8 StructLen; /* 2 */ + __u8 Rsvd1; /* 3 */ + __u16 StructRev; /* 4 */ + __u16 ProgramDate; /* 6 */ + __u16 ProgramCnt; /* 8 */ + __u16 ProductID; /* 10 */ + __u8 SerNo[16]; /* 12 */ + __u8 PLInfo[6]; /* 28 */ + __u16 PCBInfo; /* 34 */ + __u32 FeatFlag; /* 36 */ + __u8 RamdacType; /* 40 */ + __u8 RamdacSpeed; /* 41 */ + __u8 PclkMax; /* 42 */ + __u8 ClkGE; /* 43 */ + __u8 ClkMem; /* 44 */ + __u8 Clk4MB; /* 45 */ + __u8 Clk8MB; /* 46 */ + __u8 ClkMod; /* 47 */ + __u8 TestClk; /* 48 */ + __u8 VGAFreq1; /* 49 */ + __u8 VGAFreq2; /* 50 */ + __u8 MCTLWTST; /* 51 */ + __u8 VidCtrl; /* 52 */ + __u8 Clk12MB; /* 53 */ + __u8 Clk16MB; /* 54 */ + __u8 Reserved[8]; /* 55-62 */ + __u8 PinCheck; /* 63 */ +} MGABios2Info; + +#endif diff --git a/src/server/mga_dri.c b/src/server/mga_dri.c new file mode 100644 index 0000000..258ace8 --- /dev/null +++ b/src/server/mga_dri.c @@ -0,0 +1,1089 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/mga/mga_dri.c,v 1.28 2003/02/08 21:26:58 dawes Exp $ */ + +/* + * Copyright 2000 VA Linux Systems Inc., Fremont, California. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES + * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * Gareth Hughes <gareth@valinux.com> + */ + +#include <errno.h> +#include <unistd.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <inttypes.h> + +#include "driver.h" +#include "drm.h" +#include "memops.h" + +#include "mga_reg.h" +#include "mga.h" +#include "mga_macros.h" +#include "mga_dri.h" + + +/* Quiescence, locking + */ +#define MGA_TIMEOUT 2048 + +static void MGAWaitForIdleDMA( struct DRIDriverContextRec *ctx, MGAPtr pMga ) +{ + drm_lock_t lock; + int ret; + int i = 0; + + memset( &lock, 0, sizeof(lock) ); + + for (;;) { + do { + /* first ask for quiescent and flush */ + lock.flags = DRM_LOCK_QUIESCENT | DRM_LOCK_FLUSH; + do { + ret = drmCommandWrite( ctx->drmFD, DRM_MGA_FLUSH, + &lock, sizeof( lock ) ); + } while ( ret == -EBUSY && i++ < DRM_MGA_IDLE_RETRY ); + + /* if it's still busy just try quiescent */ + if ( ret == -EBUSY ) { + lock.flags = DRM_LOCK_QUIESCENT; + do { + ret = drmCommandWrite( ctx->drmFD, DRM_MGA_FLUSH, + &lock, sizeof( lock ) ); + } while ( ret == -EBUSY && i++ < DRM_MGA_IDLE_RETRY ); + } + } while ( ( ret == -EBUSY ) && ( i++ < MGA_TIMEOUT ) ); + + if ( ret == 0 ) + return; + + fprintf( stderr, + "[dri] Idle timed out, resetting engine...\n" ); + + drmCommandNone( ctx->drmFD, DRM_MGA_RESET ); + } +} + +static unsigned int mylog2( unsigned int n ) +{ + unsigned int log2 = 1; + while ( n > 1 ) n >>= 1, log2++; + return log2; +} + +static int MGADRIAgpInit(struct DRIDriverContextRec *ctx, MGAPtr pMga) +{ + unsigned long mode; + unsigned int vendor, device; + int ret, count, i; + + if(pMga->agpSize < 12)pMga->agpSize = 12; + if(pMga->agpSize > 64)pMga->agpSize = 64; /* cap */ + + /* FIXME: Make these configurable... + */ + pMga->agp.size = pMga->agpSize * 1024 * 1024; + + pMga->warp.offset = 0; + pMga->warp.size = MGA_WARP_UCODE_SIZE; + + pMga->primary.offset = (pMga->warp.offset + + pMga->warp.size); + pMga->primary.size = 1024 * 1024; + + pMga->buffers.offset = (pMga->primary.offset + + pMga->primary.size); + pMga->buffers.size = MGA_NUM_BUFFERS * MGA_BUFFER_SIZE; + + + pMga->agpTextures.offset = (pMga->buffers.offset + + pMga->buffers.size); + + pMga->agpTextures.size = pMga->agp.size - + pMga->agpTextures.offset; + + if ( drmAgpAcquire( ctx->drmFD ) < 0 ) { + fprintf( stderr, "[agp] AGP not available\n" ); + return 0; + } + + mode = drmAgpGetMode( ctx->drmFD ); /* Default mode */ + vendor = drmAgpVendorId( ctx->drmFD ); + device = drmAgpDeviceId( ctx->drmFD ); + + mode &= ~MGA_AGP_MODE_MASK; + switch ( pMga->agpMode ) { + case 4: + mode |= MGA_AGP_4X_MODE; + case 2: + mode |= MGA_AGP_2X_MODE; + case 1: + default: + mode |= MGA_AGP_1X_MODE; + } + +#if 0 + fprintf( stderr, + "[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n", + mode, vendor, device, + ctx->pciVendor, + ctx->pciChipType ); +#endif + + if ( drmAgpEnable( ctx->drmFD, mode ) < 0 ) { + fprintf( stderr, "[agp] AGP not enabled\n" ); + drmAgpRelease( ctx->drmFD ); + return 0; + } + + if ( pMga->Chipset == PCI_CHIP_MGAG200 ) { + switch ( pMga->agpMode ) { + case 2: + fprintf( stderr, + "[drm] Enabling AGP 2x PLL encoding\n" ); + OUTREG( MGAREG_AGP_PLL, MGA_AGP2XPLL_ENABLE ); + break; + + case 1: + default: + fprintf( stderr, + "[drm] Disabling AGP 2x PLL encoding\n" ); + OUTREG( MGAREG_AGP_PLL, MGA_AGP2XPLL_DISABLE ); + pMga->agpMode = 1; + break; + } + } + + ret = drmAgpAlloc( ctx->drmFD, pMga->agp.size, + 0, NULL, &pMga->agp.handle ); + if ( ret < 0 ) { + fprintf( stderr, "[agp] Out of memory (%d)\n", ret ); + drmAgpRelease( ctx->drmFD ); + return 0; + } + fprintf( stderr, + "[agp] %d kB allocated with handle 0x%08x\n", + pMga->agp.size/1024, (unsigned int)pMga->agp.handle ); + + if ( drmAgpBind( ctx->drmFD, pMga->agp.handle, 0 ) < 0 ) { + fprintf( stderr, "[agp] Could not bind memory\n" ); + drmAgpFree( ctx->drmFD, pMga->agp.handle ); + drmAgpRelease( ctx->drmFD ); + return 0; + } + + /* WARP microcode space + */ + if ( drmAddMap( ctx->drmFD, + pMga->warp.offset, + pMga->warp.size, + DRM_AGP, DRM_READ_ONLY, + &pMga->warp.handle ) < 0 ) { + fprintf( stderr, + "[agp] Could not add WARP microcode mapping\n" ); + return 0; + } + fprintf( stderr, + "[agp] WARP microcode handle = 0x%08x\n", + pMga->warp.handle ); + + if ( drmMap( ctx->drmFD, + pMga->warp.handle, + pMga->warp.size, + &pMga->warp.map ) < 0 ) { + fprintf( stderr, + "[agp] Could not map WARP microcode\n" ); + return 0; + } + fprintf( stderr, + "[agp] WARP microcode mapped at 0x%08lx\n", + (unsigned long)pMga->warp.map ); + + /* Primary DMA space + */ + if ( drmAddMap( ctx->drmFD, + pMga->primary.offset, + pMga->primary.size, + DRM_AGP, DRM_READ_ONLY, + &pMga->primary.handle ) < 0 ) { + fprintf( stderr, + "[agp] Could not add primary DMA mapping\n" ); + return 0; + } + fprintf( stderr, + "[agp] Primary DMA handle = 0x%08x\n", + pMga->primary.handle ); + + if ( drmMap( ctx->drmFD, + pMga->primary.handle, + pMga->primary.size, + &pMga->primary.map ) < 0 ) { + fprintf( stderr, + "[agp] Could not map primary DMA\n" ); + return 0; + } + fprintf( stderr, + "[agp] Primary DMA mapped at 0x%08lx\n", + (unsigned long)pMga->primary.map ); + + /* DMA buffers + */ + if ( drmAddMap( ctx->drmFD, + pMga->buffers.offset, + pMga->buffers.size, + DRM_AGP, 0, + &pMga->buffers.handle ) < 0 ) { + fprintf( stderr, + "[agp] Could not add DMA buffers mapping\n" ); + return 0; + } + fprintf( stderr, + "[agp] DMA buffers handle = 0x%08x\n", + pMga->buffers.handle ); + + if ( drmMap( ctx->drmFD, + pMga->buffers.handle, + pMga->buffers.size, + &pMga->buffers.map ) < 0 ) { + fprintf( stderr, + "[agp] Could not map DMA buffers\n" ); + return 0; + } + fprintf( stderr, + "[agp] DMA buffers mapped at 0x%08lx\n", + (unsigned long)pMga->buffers.map ); + + count = drmAddBufs( ctx->drmFD, + MGA_NUM_BUFFERS, MGA_BUFFER_SIZE, + DRM_AGP_BUFFER, pMga->buffers.offset ); + if ( count <= 0 ) { + fprintf( stderr, + "[drm] failure adding %d %d byte DMA buffers\n", + MGA_NUM_BUFFERS, MGA_BUFFER_SIZE ); + return 0; + } + fprintf( stderr, + "[drm] Added %d %d byte DMA buffers\n", + count, MGA_BUFFER_SIZE ); + + i = mylog2(pMga->agpTextures.size / MGA_NR_TEX_REGIONS); + if(i < MGA_LOG_MIN_TEX_REGION_SIZE) + i = MGA_LOG_MIN_TEX_REGION_SIZE; + pMga->agpTextures.size = (pMga->agpTextures.size >> i) << i; + + if ( drmAddMap( ctx->drmFD, + pMga->agpTextures.offset, + pMga->agpTextures.size, + DRM_AGP, 0, + &pMga->agpTextures.handle ) < 0 ) { + fprintf( stderr, + "[agp] Could not add agpTexture mapping\n" ); + return 0; + } +/* should i map it ? */ + fprintf( stderr, + "[agp] agpTexture handle = 0x%08x\n", + pMga->agpTextures.handle ); + fprintf( stderr, + "[agp] agpTexture size: %d kb\n", pMga->agpTextures.size/1024 ); + + return 1; +} + +static int MGADRIMapInit( struct DRIDriverContextRec *ctx, MGAPtr pMga ) +{ + pMga->registers.size = MGAIOMAPSIZE; + + if ( drmAddMap( ctx->drmFD, + (drm_handle_t)pMga->IOAddress, + pMga->registers.size, + DRM_REGISTERS, DRM_READ_ONLY, + &pMga->registers.handle ) < 0 ) { + fprintf( stderr, + "[drm] Could not add MMIO registers mapping\n" ); + return 0; + } + fprintf( stderr, + "[drm] Registers handle = 0x%08lx\n", + pMga->registers.handle ); + + pMga->status.size = SAREA_MAX; + + if ( drmAddMap( ctx->drmFD, 0, pMga->status.size, + DRM_SHM, DRM_READ_ONLY | DRM_LOCKED | DRM_KERNEL, + &pMga->status.handle ) < 0 ) { + fprintf( stderr, + "[drm] Could not add status page mapping\n" ); + return 0; + } + fprintf( stderr, + "[drm] Status handle = 0x%08x\n", + pMga->status.handle ); + + if ( drmMap( ctx->drmFD, + pMga->status.handle, + pMga->status.size, + &pMga->status.map ) < 0 ) { + fprintf( stderr, + "[agp] Could not map status page\n" ); + return 0; + } + fprintf( stderr, + "[agp] Status page mapped at 0x%08lx\n", + (unsigned long)pMga->status.map ); + + return 1; +} + +static int MGADRIKernelInit( struct DRIDriverContextRec *ctx, MGAPtr pMga ) +{ + drm_mga_init_t init; + int ret; + + memset( &init, 0, sizeof(init) ); + + init.func = MGA_INIT_DMA; + init.sarea_priv_offset = sizeof(drm_sarea_t); + + switch ( pMga->Chipset ) { + case PCI_CHIP_MGAG550: + case PCI_CHIP_MGAG400: + init.chipset = MGA_CARD_TYPE_G400; + break; + case PCI_CHIP_MGAG200: + case PCI_CHIP_MGAG200_PCI: + init.chipset = MGA_CARD_TYPE_G200; + break; + default: + return 0; + } + + init.sgram = 0; /* FIXME !pMga->HasSDRAM; */ + + + switch (ctx->bpp) + { + case 16: + init.maccess = MGA_MACCESS_PW16; + break; + case 32: + init.maccess = MGA_MACCESS_PW32; + break; + default: + fprintf( stderr, "[mga] invalid bpp (%d)\n", ctx->bpp ); + return 0; + } + + + init.fb_cpp = ctx->bpp / 8; + init.front_offset = pMga->frontOffset; + init.front_pitch = pMga->frontPitch / init.fb_cpp; + init.back_offset = pMga->backOffset; + init.back_pitch = pMga->backPitch / init.fb_cpp; + + init.depth_cpp = ctx->bpp / 8; + init.depth_offset = pMga->depthOffset; + init.depth_pitch = pMga->depthPitch / init.depth_cpp; + + init.texture_offset[0] = pMga->textureOffset; + init.texture_size[0] = pMga->textureSize; + + init.fb_offset = ctx->shared.hFrameBuffer; + init.mmio_offset = pMga->registers.handle; + init.status_offset = pMga->status.handle; + + init.warp_offset = pMga->warp.handle; + init.primary_offset = pMga->primary.handle; + init.buffers_offset = pMga->buffers.handle; + + init.texture_offset[1] = pMga->agpTextures.handle; + init.texture_size[1] = pMga->agpTextures.size; + + ret = drmCommandWrite( ctx->drmFD, DRM_MGA_INIT, &init, sizeof(init)); + if ( ret < 0 ) { + fprintf( stderr, + "[drm] Failed to initialize DMA! (%d)\n", ret ); + return 0; + } + + return 1; +} + +static void MGADRIIrqInit(struct DRIDriverContextRec *ctx, MGAPtr pMga) +{ + if (!pMga->irq) + { + pMga->irq = drmGetInterruptFromBusID(ctx->drmFD, + ctx->pciBus, + ctx->pciDevice, + ctx->pciFunc); + + fprintf(stderr, "[drm] got IRQ %d\n", pMga->irq); + + if((drmCtlInstHandler(ctx->drmFD, pMga->irq)) != 0) + { + fprintf(stderr, + "[drm] failure adding irq handler, " + "there is a device already using that irq\n" + "[drm] falling back to irq-free operation\n"); + pMga->irq = 0; + } + else + { + pMga->reg_ien = INREG( MGAREG_IEN ); + } + } + + if (pMga->irq) + fprintf(stderr, + "[drm] dma control initialized, using IRQ %d\n", + pMga->irq); +} + +static int MGADRIBuffersInit( struct DRIDriverContextRec *ctx, MGAPtr pMga ) +{ + pMga->drmBuffers = drmMapBufs( ctx->drmFD ); + if ( !pMga->drmBuffers ) + { + fprintf( stderr, + "[drm] Failed to map DMA buffers list\n" ); + return 0; + } + + fprintf( stderr, + "[drm] Mapped %d DMA buffers\n", + pMga->drmBuffers->count ); + + return 1; +} + +static int MGAMemoryInit( struct DRIDriverContextRec *ctx, MGAPtr pMga ) +{ + int width_bytes = ctx->shared.virtualWidth * ctx->cpp; + int bufferSize = ((ctx->shared.virtualHeight * width_bytes + + MGA_BUFFER_ALIGN) + & ~MGA_BUFFER_ALIGN); + int depthSize = ((((ctx->shared.virtualHeight+15) & ~15) * width_bytes + + MGA_BUFFER_ALIGN) + & ~MGA_BUFFER_ALIGN); + int l; + + pMga->frontOffset = 0; + pMga->frontPitch = ctx->shared.virtualWidth * ctx->cpp; + + fprintf(stderr, + "Using %d MB AGP aperture\n", pMga->agpSize); + fprintf(stderr, + "Using %d MB for vertex/indirect buffers\n", pMga->buffers.size>>20); + fprintf(stderr, + "Using %d MB for AGP textures\n", pMga->agpTextures.size>>20); + + /* Front, back and depth buffers - everything else texture?? + */ + pMga->textureSize = ctx->shared.fbSize - 2 * bufferSize - depthSize; + + if (pMga->textureSize < 0) + return 0; + + l = mylog2( pMga->textureSize / MGA_NR_TEX_REGIONS ); + if ( l < MGA_LOG_MIN_TEX_REGION_SIZE ) + l = MGA_LOG_MIN_TEX_REGION_SIZE; + + /* Round the texture size up to the nearest whole number of + * texture regions. Again, be greedy about this, don't + * round down. + */ + pMga->logTextureGranularity = l; + pMga->textureSize = (pMga->textureSize >> l) << l; + + /* Set a minimum usable local texture heap size. This will fit + * two 256x256x32bpp textures. + */ + if (pMga->textureSize < 512 * 1024) { + pMga->textureOffset = 0; + pMga->textureSize = 0; + } + + /* Reserve space for textures */ + pMga->textureOffset = ((ctx->shared.fbSize - pMga->textureSize + + MGA_BUFFER_ALIGN) & + ~MGA_BUFFER_ALIGN); + + /* Reserve space for the shared depth + * buffer. + */ + pMga->depthOffset = ((pMga->textureOffset - depthSize + + MGA_BUFFER_ALIGN) & + ~MGA_BUFFER_ALIGN); + pMga->depthPitch = ctx->shared.virtualWidth * ctx->cpp; + + pMga->backOffset = ((pMga->depthOffset - bufferSize + + MGA_BUFFER_ALIGN) & + ~MGA_BUFFER_ALIGN); + pMga->backPitch = ctx->shared.virtualWidth * ctx->cpp; + + + fprintf(stderr, + "Will use back buffer at offset 0x%x\n", + pMga->backOffset); + fprintf(stderr, + "Will use depth buffer at offset 0x%x\n", + pMga->depthOffset); + fprintf(stderr, + "Will use %d kb for textures at offset 0x%x\n", + pMga->textureSize/1024, pMga->textureOffset); + + return 1; +} + +static int MGACheckDRMVersion( struct DRIDriverContextRec *ctx, MGAPtr pMga ) +{ + drmVersionPtr version; + + /* Check the MGA DRM version */ + version = drmGetVersion(ctx->drmFD); + if ( version ) { + if ( version->version_major != 3 || + version->version_minor < 0 ) { + /* incompatible drm version */ + fprintf( stderr, + "[dri] MGADRIScreenInit failed because of a version mismatch.\n" + "[dri] mga.o kernel module version is %d.%d.%d but version 3.0.x is needed.\n" + "[dri] Disabling DRI.\n", + version->version_major, + version->version_minor, + version->version_patchlevel ); + drmFreeVersion( version ); + return 0; + } + drmFreeVersion( version ); + } + + return 1; +} + +static void print_client_msg( MGADRIPtr pMGADRI ) +{ + fprintf( stderr, "chipset: %d\n", pMGADRI->chipset ); + + fprintf( stderr, "width: %d\n", pMGADRI->width ); + fprintf( stderr, "height: %d\n", pMGADRI->height ); + fprintf( stderr, "mem: %d\n", pMGADRI->mem ); + fprintf( stderr, "cpp: %d\n", pMGADRI->cpp ); + + fprintf( stderr, "agpMode: %d\n", pMGADRI->agpMode ); + + fprintf( stderr, "frontOffset: %d\n", pMGADRI->frontOffset ); + fprintf( stderr, "frontPitch: %d\n", pMGADRI->frontPitch ); + + fprintf( stderr, "backOffset: %d\n", pMGADRI->backOffset ); + fprintf( stderr, "backPitch: %d\n", pMGADRI->backPitch ); + + fprintf( stderr, "depthOffset: %d\n", pMGADRI->depthOffset ); + fprintf( stderr, "depthPitch: %d\n", pMGADRI->depthPitch ); + + fprintf( stderr, "textureOffset: %d\n", pMGADRI->textureOffset ); + fprintf( stderr, "textureSize: %d\n", pMGADRI->textureSize ); + + fprintf( stderr, "logTextureGranularity: %d\n", pMGADRI->logTextureGranularity ); + fprintf( stderr, "logAgpTextureGranularity: %d\n", pMGADRI->logAgpTextureGranularity ); + + fprintf( stderr, "agpTextureHandle: %u\n", (unsigned int)pMGADRI->agpTextureOffset ); + fprintf( stderr, "agpTextureSize: %u\n", (unsigned int)pMGADRI->agpTextureSize ); + +#if 0 + pMGADRI->registers.handle = pMga->registers.handle; + pMGADRI->registers.size = pMga->registers.size; + pMGADRI->status.handle = pMga->status.handle; + pMGADRI->status.size = pMga->status.size; + pMGADRI->primary.handle = pMga->primary.handle; + pMGADRI->primary.size = pMga->primary.size; + pMGADRI->buffers.handle = pMga->buffers.handle; + pMGADRI->buffers.size = pMga->buffers.size; + pMGADRI->sarea_priv_offset = sizeof(drm_sarea_t); +#endif +} + +static int MGAScreenInit( struct DRIDriverContextRec *ctx, MGAPtr pMga ) +{ + int i; + int err; + MGADRIPtr pMGADRI; + + usleep(100); + /*assert(!ctx->IsClient);*/ + + { + int width_bytes = (ctx->shared.virtualWidth * ctx->cpp); + int maxy = ctx->shared.fbSize / width_bytes; + + + if (maxy <= ctx->shared.virtualHeight * 3) { + fprintf(stderr, + "Static buffer allocation failed -- " + "need at least %d kB video memory (have %d kB)\n", + (ctx->shared.virtualWidth * ctx->shared.virtualHeight * + ctx->cpp * 3 + 1023) / 1024, + ctx->shared.fbSize / 1024); + return 0; + } + } + + switch(pMga->Chipset) { + case PCI_CHIP_MGAG550: + case PCI_CHIP_MGAG400: + case PCI_CHIP_MGAG200: +#if 0 + case PCI_CHIP_MGAG200_PCI: +#endif + break; + default: + fprintf(stderr, "[drm] Direct rendering only supported with G200/G400/G550 AGP\n"); + return 0; + } + + fprintf( stderr, + "[drm] bpp: %d depth: %d\n", + ctx->bpp, ctx->bpp /* FIXME: depth */ ); + + if ( (ctx->bpp / 8) != 2 && + (ctx->bpp / 8) != 4 ) { + fprintf( stderr, + "[dri] Direct rendering only supported in 16 and 32 bpp modes\n" ); + return 0; + } + + ctx->shared.SAREASize = SAREA_MAX; + + + /* Note that drmOpen will try to load the kernel module, if needed. */ + ctx->drmFD = drmOpen("mga", NULL ); + if (ctx->drmFD < 0) { + fprintf(stderr, "[drm] drmOpen failed\n"); + return 0; + } + + if ((err = drmSetBusid(ctx->drmFD, ctx->pciBusID)) < 0) { + fprintf(stderr, "[drm] drmSetBusid failed (%d, %s), %s\n", + ctx->drmFD, ctx->pciBusID, strerror(-err)); + return 0; + } + + + if (drmAddMap( ctx->drmFD, + 0, + ctx->shared.SAREASize, + DRM_SHM, + DRM_CONTAINS_LOCK, + &ctx->shared.hSAREA) < 0) + { + fprintf(stderr, "[drm] drmAddMap failed\n"); + return 0; + } + fprintf(stderr, "[drm] added %d byte SAREA at 0x%08lx\n", + ctx->shared.SAREASize, ctx->shared.hSAREA); + + if (drmMap( ctx->drmFD, + ctx->shared.hSAREA, + ctx->shared.SAREASize, + (drmAddressPtr)(&ctx->pSAREA)) < 0) + { + fprintf(stderr, "[drm] drmMap failed\n"); + return 0; + } + memset(ctx->pSAREA, 0, ctx->shared.SAREASize); + fprintf(stderr, "[drm] mapped SAREA 0x%08lx to %p, size %d\n", + ctx->shared.hSAREA, ctx->pSAREA, ctx->shared.SAREASize); + + /* Need to AddMap the framebuffer and mmio regions here: + */ + if (drmAddMap( ctx->drmFD, + (drm_handle_t)ctx->FBStart, + ctx->FBSize, + DRM_FRAME_BUFFER, + 0, + &ctx->shared.hFrameBuffer) < 0) + { + fprintf(stderr, "[drm] drmAddMap framebuffer failed\n"); + return 0; + } + fprintf(stderr, "[drm] framebuffer handle = 0x%08lx\n", + ctx->shared.hFrameBuffer); + + +#if 0 /* will be done in MGADRIMapInit */ + if (drmAddMap(ctx->drmFD, + ctx->FixedInfo.mmio_start, + ctx->FixedInfo.mmio_len, + DRM_REGISTERS, + DRM_READ_ONLY, + &pMga->registers.handle) < 0) { + fprintf(stderr, "[drm] drmAddMap mmio failed\n"); + return 0; + } + fprintf(stderr, + "[drm] register handle = 0x%08lx\n", pMga->registers.handle); +#endif + + + /* Check the mga DRM version */ + if (!MGACheckDRMVersion(ctx, pMga)) { + return 0; + } + + if ( !MGADRIAgpInit( ctx, pMga ) ) { + return 0; + } + + if ( !MGADRIMapInit( ctx, pMga ) ) { + return 0; + } + + /* Memory manager setup */ + if (!MGAMemoryInit(ctx, pMga)) { + return 0; + } + + + /* Create a 'server' context so we can grab the lock for + * initialization ioctls. + */ + if ((err = drmCreateContext(ctx->drmFD, &ctx->serverContext)) != 0) { + fprintf(stderr, "%s: drmCreateContext failed %d\n", __FUNCTION__, err); + return 0; + } + + DRM_LOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext, 0); + + /* Initialize the kernel data structures */ + if (!MGADRIKernelInit(ctx, pMga)) { + fprintf(stderr, "MGADRIKernelInit failed\n"); + DRM_UNLOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext); + return 0; + } + + /* Initialize the vertex buffers list */ + if (!MGADRIBuffersInit(ctx, pMga)) { + fprintf(stderr, "MGADRIBuffersInit failed\n"); + DRM_UNLOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext); + return 0; + } + + /* Initialize IRQ */ + MGADRIIrqInit(ctx, pMga); + + + /* Initialize the SAREA private data structure */ + { + drm_mga_sarea_t *pSAREAPriv; + pSAREAPriv = (drm_mga_sarea_t *)(((char*)ctx->pSAREA) + + sizeof(drm_sarea_t)); + memset(pSAREAPriv, 0, sizeof(*pSAREAPriv)); + } + + /* Quick hack to clear the front & back buffers. Could also use + * the clear ioctl to do this, but would need to setup hw state + * first. + */ + drimemsetio((char *)ctx->FBAddress + pMga->frontOffset, + 0, + pMga->frontPitch * ctx->shared.virtualHeight ); + + drimemsetio((char *)ctx->FBAddress + pMga->backOffset, + 0, + pMga->backPitch * ctx->shared.virtualHeight ); + + /* Can release the lock now */ +/* DRM_UNLOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext);*/ + + /* This is the struct passed to radeon_dri.so for its initialization */ + ctx->driverClientMsg = malloc(sizeof(MGADRIRec)); + ctx->driverClientMsgSize = sizeof(MGADRIRec); + + pMGADRI = (MGADRIPtr)ctx->driverClientMsg; + + + switch(pMga->Chipset) { + case PCI_CHIP_MGAG550: + case PCI_CHIP_MGAG400: + pMGADRI->chipset = MGA_CARD_TYPE_G400; + break; + case PCI_CHIP_MGAG200: + case PCI_CHIP_MGAG200_PCI: + pMGADRI->chipset = MGA_CARD_TYPE_G200; + break; + default: + return 0; + } + pMGADRI->width = ctx->shared.virtualWidth; + pMGADRI->height = ctx->shared.virtualHeight; + pMGADRI->mem = ctx->shared.fbSize; + pMGADRI->cpp = ctx->bpp / 8; + + pMGADRI->agpMode = pMga->agpMode; + + pMGADRI->frontOffset = pMga->frontOffset; + pMGADRI->frontPitch = pMga->frontPitch; + pMGADRI->backOffset = pMga->backOffset; + pMGADRI->backPitch = pMga->backPitch; + pMGADRI->depthOffset = pMga->depthOffset; + pMGADRI->depthPitch = pMga->depthPitch; + pMGADRI->textureOffset = pMga->textureOffset; + pMGADRI->textureSize = pMga->textureSize; + pMGADRI->logTextureGranularity = pMga->logTextureGranularity; + + i = mylog2( pMga->agpTextures.size / MGA_NR_TEX_REGIONS ); + if ( i < MGA_LOG_MIN_TEX_REGION_SIZE ) + i = MGA_LOG_MIN_TEX_REGION_SIZE; + + pMGADRI->logAgpTextureGranularity = i; + pMGADRI->agpTextureOffset = (unsigned int)pMga->agpTextures.handle; + pMGADRI->agpTextureSize = (unsigned int)pMga->agpTextures.size; + + pMGADRI->registers.handle = pMga->registers.handle; + pMGADRI->registers.size = pMga->registers.size; + pMGADRI->status.handle = pMga->status.handle; + pMGADRI->status.size = pMga->status.size; + pMGADRI->primary.handle = pMga->primary.handle; + pMGADRI->primary.size = pMga->primary.size; + pMGADRI->buffers.handle = pMga->buffers.handle; + pMGADRI->buffers.size = pMga->buffers.size; + pMGADRI->sarea_priv_offset = sizeof(drm_sarea_t); + + print_client_msg( pMGADRI ); + + return 1; +} + + +/** + * \brief Validate the fbdev mode. + * + * \param ctx display handle. + * + * \return one on success, or zero on failure. + * + * Saves some registers and returns 1. + * + * \sa mgaValidateMode(). + */ +static int mgaValidateMode( const DRIDriverContext *ctx ) +{ + return 1; +} + + +/** + * \brief Examine mode returned by fbdev. + * + * \param ctx display handle. + * + * \return one on success, or zero on failure. + * + * Restores registers that fbdev has clobbered and returns 1. + * + * \sa mgaValidateMode(). + */ +static int mgaPostValidateMode( const DRIDriverContext *ctx ) +{ + return 1; +} + + +/** + * \brief Initialize the framebuffer device mode + * + * \param ctx display handle. + * + * \return one on success, or zero on failure. + * + * Fills in \p info with some default values and some information from \p ctx + * and then calls MGAScreenInit() for the screen initialization. + * + * Before exiting clears the framebuffer memomry accessing it directly. + */ +static int mgaInitFBDev( struct DRIDriverContextRec *ctx ) +{ + MGAPtr pMga = calloc(1, sizeof(*pMga)); + + { + int dummy = ctx->shared.virtualWidth; + + switch (ctx->bpp / 8) { + case 1: dummy = (ctx->shared.virtualWidth + 127) & ~127; break; + case 2: dummy = (ctx->shared.virtualWidth + 31) & ~31; break; + case 3: + case 4: dummy = (ctx->shared.virtualWidth + 15) & ~15; break; + } + + ctx->shared.virtualWidth = dummy; + } + + ctx->driverPrivate = (void *)pMga; + + pMga->agpMode = MGA_DEFAULT_AGP_MODE; + pMga->agpSize = MGA_DEFAULT_AGP_SIZE; + + pMga->Chipset = ctx->chipset; + + pMga->IOAddress = ctx->MMIOStart; + pMga->IOBase = ctx->MMIOAddress; + + pMga->frontPitch = ctx->shared.virtualWidth * ctx->cpp; + + if (!MGAScreenInit( ctx, pMga )) + return 0; + + return 1; +} + + +/** + * \brief The screen is being closed, so clean up any state and free any + * resources used by the DRI. + * + * \param ctx display handle. + * + * Unmaps the SAREA, closes the DRM device file descriptor and frees the driver + * private data. + */ +static void mgaHaltFBDev( struct DRIDriverContextRec *ctx ) +{ + drmUnmap( ctx->pSAREA, ctx->shared.SAREASize ); + drmClose(ctx->drmFD); + + if (ctx->driverPrivate) { + free(ctx->driverPrivate); + ctx->driverPrivate = NULL; + } +} + + +static int mgaEngineShutdown( const DRIDriverContext *ctx ) +{ + fprintf(stderr, "%s() is not yet implemented!\n", __FUNCTION__); + + return 1; +} + +static int mgaEngineRestore( const DRIDriverContext *ctx ) +{ + fprintf(stderr, "%s() is not yet implemented!\n", __FUNCTION__); + + return 1; +} + +/** + * \brief Exported driver interface for Mini GLX. + * + * \sa DRIDriverRec. + */ +struct DRIDriverRec __driDriver = { + mgaValidateMode, + mgaPostValidateMode, + mgaInitFBDev, + mgaHaltFBDev, + mgaEngineShutdown, + mgaEngineRestore, + 0 +}; + + + + +#if 0 +void MGADRICloseScreen( ScreenPtr pScreen ) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + MGAPtr pMga = MGAPTR(pScrn); + MGADRIServerPrivatePtr pMga = pMga->DRIServerInfo; + drmMGAInit init; + + if ( pMga->drmBuffers ) { + drmUnmapBufs( pMga->drmBuffers ); + pMga->drmBuffers = NULL; + } + + if (pMga->irq) { + drmCtlUninstHandler(ctx->drmFD); + pMga->irq = 0; + } + + /* Cleanup DMA */ + memset( &init, 0, sizeof(drmMGAInit) ); + init.func = MGA_CLEANUP_DMA; + drmCommandWrite( ctx->drmFD, DRM_MGA_INIT, &init, sizeof(drmMGAInit) ); + + if ( pMga->status.map ) { + drmUnmap( pMga->status.map, pMga->status.size ); + pMga->status.map = NULL; + } + if ( pMga->buffers.map ) { + drmUnmap( pMga->buffers.map, pMga->buffers.size ); + pMga->buffers.map = NULL; + } + if ( pMga->primary.map ) { + drmUnmap( pMga->primary.map, pMga->primary.size ); + pMga->primary.map = NULL; + } + if ( pMga->warp.map ) { + drmUnmap( pMga->warp.map, pMga->warp.size ); + pMga->warp.map = NULL; + } + + if ( pMga->agpTextures.map ) { + drmUnmap( pMga->agpTextures.map, pMga->agpTextures.size ); + pMga->agpTextures.map = NULL; + } + + if ( pMga->agp.handle ) { + drmAgpUnbind( ctx->drmFD, pMga->agp.handle ); + drmAgpFree( ctx->drmFD, pMga->agp.handle ); + pMga->agp.handle = 0; + drmAgpRelease( ctx->drmFD ); + } + + DRICloseScreen( pScreen ); + + if ( pMga->pDRIInfo ) { + if ( pMga->pDRIpMga->devPrivate ) { + xfree( pMga->pDRIpMga->devPrivate ); + pMga->pDRIpMga->devPrivate = 0; + } + DRIDestroyInfoRec( pMga->pDRIInfo ); + pMga->pDRIInfo = 0; + } + if ( pMga->DRIServerInfo ) { + xfree( pMga->DRIServerInfo ); + pMga->DRIServerInfo = 0; + } + if ( pMga->pVisualConfigs ) { + xfree( pMga->pVisualConfigs ); + } + if ( pMga->pVisualConfigsPriv ) { + xfree( pMga->pVisualConfigsPriv ); + } +} +#endif diff --git a/src/server/mga_dri.h b/src/server/mga_dri.h new file mode 100644 index 0000000..03b8414 --- /dev/null +++ b/src/server/mga_dri.h @@ -0,0 +1,113 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/mga/mga_dri.h,v 1.8 2002/11/29 11:06:42 eich Exp $ */ + +/* + * Copyright 2000 VA Linux Systems Inc., Fremont, California. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES + * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * Gareth Hughes <gareth@valinux.com> + */ + +#ifndef __MGA_DRI_H__ +#define __MGA_DRI_H__ + +#include "xf86drm.h" +#include "drm.h" +#include "mga_drm.h" + +#define MGA_DEFAULT_AGP_SIZE 64 +#define MGA_DEFAULT_AGP_MODE 4 +#define MGA_MAX_AGP_MODE 4 + +/* Buffer are aligned on 4096 byte boundaries. + */ +#define MGA_BUFFER_ALIGN 0x00000fff + +#ifdef __GNUC__ +# define DEPRECATED __attribute__ ((deprecated)) +#else +# define DEPRECATED +#endif + +#if 1 +typedef struct _mgaDrmRegion { + drm_handle_t handle; + unsigned int offset; + drmSize size; +} mgaDrmRegion, *mgaDrmRegionPtr; +#else +#define mgaDrmRegion drmRegion +#endif + +typedef struct { + int chipset; + int width DEPRECATED; + int height DEPRECATED; + int mem DEPRECATED; + int cpp; + + int agpMode; + + unsigned int frontOffset; + unsigned int frontPitch; + + unsigned int backOffset; + unsigned int backPitch; + + unsigned int depthOffset; + unsigned int depthPitch; + + unsigned int textureOffset; + unsigned int textureSize; + int logTextureGranularity DEPRECATED; + + /* Allow calculation of setup dma addresses. + */ + unsigned int agpBufferOffset DEPRECATED; + + unsigned int agpTextureOffset; + unsigned int agpTextureSize; + int logAgpTextureGranularity DEPRECATED; + + unsigned int mAccess DEPRECATED; + + /** + * \name DRM memory regions. + * + * \todo + * Several of these fields are no longer used (and will never be used + * again) on the client-side. None of them, except \c registers, are used + * on the server-side. At some point when it is safe to do so (probably + * for the X.org 6.9 / 7.0 release), these fields should be removed. + */ + /*@{*/ + mgaDrmRegion registers; /**< MMIO registers. */ + mgaDrmRegion status DEPRECATED; /**< No longer used on the client-side. */ + mgaDrmRegion primary; /**< Primary DMA region. */ + mgaDrmRegion buffers DEPRECATED; /**< No longer used on the client-side. */ + /*@}*/ + + unsigned int sarea_priv_offset; +} MGADRIRec, *MGADRIPtr; + +#endif diff --git a/src/server/mga_macros.h b/src/server/mga_macros.h new file mode 100644 index 0000000..d985081 --- /dev/null +++ b/src/server/mga_macros.h @@ -0,0 +1,118 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/mga/mga_macros.h,v 1.22 2002/02/20 17:17:50 dawes Exp $ */ + +#ifndef _MGA_MACROS_H_ +#define _MGA_MACROS_H_ + +#ifndef PSZ +#define PSZ 8 +#endif + +#if PSZ == 8 +#define REPLICATE(r) r &= 0xFF; r |= r << 8; r |= r << 16 +#elif PSZ == 16 +#define REPLICATE(r) r &= 0xFFFF; r |= r << 16 +#elif PSZ == 24 +#define REPLICATE(r) r &= 0xFFFFFF; r |= r << 24 +#else +#define REPLICATE(r) /* */ +#endif + +#define RGBEQUAL(c) (!((((c) >> 8) ^ (c)) & 0xffff)) + +#ifdef XF86DRI +#define MGA_SYNC_XTAG 0x275f4200 + +#define MGABUSYWAIT() do { \ +OUTREG(MGAREG_DWGSYNC, MGA_SYNC_XTAG); \ +while(INREG(MGAREG_DWGSYNC) != MGA_SYNC_XTAG) ; \ +}while(0); + +#endif + +#define MGAISBUSY() (INREG8(MGAREG_Status + 2) & 0x01) + +#define WAITFIFO(cnt) \ + if(!pMga->UsePCIRetry) {\ + register int n = cnt; \ + if(n > pMga->FifoSize) n = pMga->FifoSize; \ + while(pMga->fifoCount < (n))\ + pMga->fifoCount = INREG8(MGAREG_FIFOSTATUS);\ + pMga->fifoCount -= n;\ + } + +#define XYADDRESS(x,y) \ + ((y) * pMga->CurrentLayout.displayWidth + (x) + pMga->YDstOrg) + +#define MAKEDMAINDEX(index) ((((index) >> 2) & 0x7f) | (((index) >> 6) & 0x80)) + +#define DMAINDICES(one,two,three,four) \ + ( MAKEDMAINDEX(one) | \ + (MAKEDMAINDEX(two) << 8) | \ + (MAKEDMAINDEX(three) << 16) | \ + (MAKEDMAINDEX(four) << 24) ) + +#if PSZ == 24 +#define SET_PLANEMASK(p) /**/ +#else +#define SET_PLANEMASK(p) \ + if(!(pMga->AccelFlags & MGA_NO_PLANEMASK) && ((p) != pMga->PlaneMask)) { \ + pMga->PlaneMask = (p); \ + REPLICATE((p)); \ + OUTREG(MGAREG_PLNWT,(p)); \ + } +#endif + +#define SET_FOREGROUND(c) \ + if((c) != pMga->FgColor) { \ + pMga->FgColor = (c); \ + REPLICATE((c)); \ + OUTREG(MGAREG_FCOL,(c)); \ + } + +#define SET_BACKGROUND(c) \ + if((c) != pMga->BgColor) { \ + pMga->BgColor = (c); \ + REPLICATE((c)); \ + OUTREG(MGAREG_BCOL,(c)); \ + } + +#define DISABLE_CLIP() { \ + pMga->AccelFlags &= ~CLIPPER_ON; \ + WAITFIFO(1); \ + OUTREG(MGAREG_CXBNDRY, 0xFFFF0000); } + +#ifdef XF86DRI +#define CHECK_DMA_QUIESCENT(pMGA, pScrn) { \ + if (!pMGA->haveQuiescense) { \ + pMGA->GetQuiescence( pScrn ); \ + } \ +} +#else +#define CHECK_DMA_QUIESCENT(pMGA, pScrn) +#endif + +#ifdef USEMGAHAL +#define HAL_CHIPSETS ((pMga->Chipset == PCI_CHIP_MGAG200_PCI) || \ + (pMga->Chipset == PCI_CHIP_MGAG200) || \ + (pMga->Chipset == PCI_CHIP_MGAG400) || \ + (pMga->Chipset == PCI_CHIP_MGAG550)) + +#define MGA_HAL(x) { \ + MGAPtr pMga = MGAPTR(pScrn); \ + if (pMga->HALLoaded && HAL_CHIPSETS) { x; } \ +} +#define MGA_NOT_HAL(x) { \ + MGAPtr pMga = MGAPTR(pScrn); \ + if (!pMga->HALLoaded || !HAL_CHIPSETS) { x; } \ +} +#else +#define MGA_NOT_HAL(x) { x; } +#endif + +#define MGAISGx50(x) ( (((x)->Chipset == PCI_CHIP_MGAG400) && ((x)->ChipRev >= 0x80)) || \ + ((x)->Chipset == PCI_CHIP_MGAG550) ) + +#define MGA_DH_NEEDS_HAL(x) (((x)->Chipset == PCI_CHIP_MGAG400) && \ + ((x)->ChipRev < 0x80)) + +#endif /* _MGA_MACROS_H_ */ diff --git a/src/server/mga_reg.h b/src/server/mga_reg.h new file mode 100644 index 0000000..b8e3499 --- /dev/null +++ b/src/server/mga_reg.h @@ -0,0 +1,484 @@ +/* $XConsortium: mgareg.h /main/2 1996/10/25 10:33:21 kaleb $ */ + + + +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/mga/mga_reg.h,v 1.18 2001/09/26 12:59:18 alanh Exp $ */ + + + +/* + * MGA Millennium (MGA2064W) functions + * MGA Mystique (MGA1064SG) functions + * + * Copyright 1996 The XFree86 Project, Inc. + * + * Authors + * Dirk Hohndel + * hohndel@XFree86.Org + * David Dawes + * dawes@XFree86.Org + * Contributors: + * Guy DESBIEF, Aix-en-provence, France + * g.desbief@aix.pacwan.net + * MGA1064SG Mystique register file + */ + + +#ifndef _MGA_REG_H_ +#define _MGA_REG_H_ + +#define MGAREG_DWGCTL 0x1c00 +#define MGAREG_MACCESS 0x1c04 +#define MGA_MACCESS_PW16 0x00000001 +#define MGA_MACCESS_PW32 0x00000002 +/* the following is a mystique only register */ +#define MGAREG_MCTLWTST 0x1c08 +#define MGAREG_ZORG 0x1c0c + +#define MGAREG_PAT0 0x1c10 +#define MGAREG_PAT1 0x1c14 +#define MGAREG_PLNWT 0x1c1c + +#define MGAREG_BCOL 0x1c20 +#define MGAREG_FCOL 0x1c24 + +#define MGAREG_SRC0 0x1c30 +#define MGAREG_SRC1 0x1c34 +#define MGAREG_SRC2 0x1c38 +#define MGAREG_SRC3 0x1c3c + +#define MGAREG_XYSTRT 0x1c40 +#define MGAREG_XYEND 0x1c44 + +#define MGAREG_SHIFT 0x1c50 +/* the following is a mystique only register */ +#define MGAREG_DMAPAD 0x1c54 +#define MGAREG_SGN 0x1c58 +#define MGAREG_LEN 0x1c5c + +#define MGAREG_AR0 0x1c60 +#define MGAREG_AR1 0x1c64 +#define MGAREG_AR2 0x1c68 +#define MGAREG_AR3 0x1c6c +#define MGAREG_AR4 0x1c70 +#define MGAREG_AR5 0x1c74 +#define MGAREG_AR6 0x1c78 + +#define MGAREG_CXBNDRY 0x1c80 +#define MGAREG_FXBNDRY 0x1c84 +#define MGAREG_YDSTLEN 0x1c88 +#define MGAREG_PITCH 0x1c8c + +#define MGAREG_YDST 0x1c90 +#define MGAREG_YDSTORG 0x1c94 +#define MGAREG_YTOP 0x1c98 +#define MGAREG_YBOT 0x1c9c + +#define MGAREG_CXLEFT 0x1ca0 +#define MGAREG_CXRIGHT 0x1ca4 +#define MGAREG_FXLEFT 0x1ca8 +#define MGAREG_FXRIGHT 0x1cac + +#define MGAREG_XDST 0x1cb0 + +#define MGAREG_DR0 0x1cc0 +#define MGAREG_DR1 0x1cc4 +#define MGAREG_DR2 0x1cc8 +#define MGAREG_DR3 0x1ccc + +#define MGAREG_DR4 0x1cd0 +#define MGAREG_DR5 0x1cd4 +#define MGAREG_DR6 0x1cd8 +#define MGAREG_DR7 0x1cdc + +#define MGAREG_DR8 0x1ce0 +#define MGAREG_DR9 0x1ce4 +#define MGAREG_DR10 0x1ce8 +#define MGAREG_DR11 0x1cec + +#define MGAREG_DR12 0x1cf0 +#define MGAREG_DR13 0x1cf4 +#define MGAREG_DR14 0x1cf8 +#define MGAREG_DR15 0x1cfc + +#define MGAREG_SRCORG 0x2cb4 +#define MGAREG_DSTORG 0x2cb8 + +/* add or or this to one of the previous "power registers" to start + the drawing engine */ + +#define MGAREG_EXEC 0x0100 + +#define MGAREG_FIFOSTATUS 0x1e10 +#define MGAREG_Status 0x1e14 +#define MGAREG_ICLEAR 0x1e18 +#define MGAREG_IEN 0x1e1c + +#define MGAREG_VCOUNT 0x1e20 + +#define MGAREG_Reset 0x1e40 + +#define MGAREG_OPMODE 0x1e54 + +/* Warp Registers */ +#define MGAREG_WIADDR 0x1dc0 +#define MGAREG_WIADDR2 0x1dd8 +#define MGAREG_WGETMSB 0x1dc8 +#define MGAREG_WVRTXSZ 0x1dcc +#define MGAREG_WACCEPTSEQ 0x1dd4 +#define MGAREG_WMISC 0x1e70 + +/* OPMODE register additives */ + +#define MGAOPM_DMA_GENERAL (0x00 << 2) +#define MGAOPM_DMA_BLIT (0x01 << 2) +#define MGAOPM_DMA_VECTOR (0x10 << 2) + +/* DWGCTL register additives */ + +/* Lines */ + +#define MGADWG_LINE_OPEN 0x00 +#define MGADWG_AUTOLINE_OPEN 0x01 +#define MGADWG_LINE_CLOSE 0x02 +#define MGADWG_AUTOLINE_CLOSE 0x03 + +/* Trapezoids */ +#define MGADWG_TRAP 0x04 +#define MGADWG_TEXTURE_TRAP 0x05 + +/* BitBlts */ + +#define MGADWG_BITBLT 0x08 +#define MGADWG_FBITBLT 0x0c +#define MGADWG_ILOAD 0x09 +#define MGADWG_ILOAD_SCALE 0x0d +#define MGADWG_ILOAD_FILTER 0x0f +#define MGADWG_ILOAD_HIQH 0x07 +#define MGADWG_ILOAD_HIQHV 0x0e +#define MGADWG_IDUMP 0x0a + +/* atype access to WRAM */ + +#define MGADWG_RPL ( 0x00 << 4 ) +#define MGADWG_RSTR ( 0x01 << 4 ) +#define MGADWG_ZI ( 0x03 << 4 ) +#define MGADWG_BLK ( 0x04 << 4 ) +#define MGADWG_I ( 0x07 << 4 ) + +/* specifies whether bit blits are linear or xy */ +#define MGADWG_LINEAR ( 0x01 << 7 ) + +/* z drawing mode. use MGADWG_NOZCMP for always */ + +#define MGADWG_NOZCMP ( 0x00 << 8 ) +#define MGADWG_ZE ( 0x02 << 8 ) +#define MGADWG_ZNE ( 0x03 << 8 ) +#define MGADWG_ZLT ( 0x04 << 8 ) +#define MGADWG_ZLTE ( 0x05 << 8 ) +#define MGADWG_GT ( 0x06 << 8 ) +#define MGADWG_GTE ( 0x07 << 8 ) + +/* use this to force colour expansion circuitry to do its stuff */ + +#define MGADWG_SOLID ( 0x01 << 11 ) + +/* ar register at zero */ + +#define MGADWG_ARZERO ( 0x01 << 12 ) + +#define MGADWG_SGNZERO ( 0x01 << 13 ) + +#define MGADWG_SHIFTZERO ( 0x01 << 14 ) + +/* See table on 4-43 for bop ALU operations */ + +/* See table on 4-44 for translucidity masks */ + +#define MGADWG_BMONOLEF ( 0x00 << 25 ) +#define MGADWG_BMONOWF ( 0x04 << 25 ) +#define MGADWG_BPLAN ( 0x01 << 25 ) + +/* note that if bfcol is specified and you're doing a bitblt, it causes + a fbitblt to be performed, so check that you obey the fbitblt rules */ + +#define MGADWG_BFCOL ( 0x02 << 25 ) +#define MGADWG_BUYUV ( 0x0e << 25 ) +#define MGADWG_BU32BGR ( 0x03 << 25 ) +#define MGADWG_BU32RGB ( 0x07 << 25 ) +#define MGADWG_BU24BGR ( 0x0b << 25 ) +#define MGADWG_BU24RGB ( 0x0f << 25 ) + +#define MGADWG_PATTERN ( 0x01 << 29 ) +#define MGADWG_TRANSC ( 0x01 << 30 ) +#define MGAREG_MISC_WRITE 0x3c2 +#define MGAREG_MISC_READ 0x3cc +#define MGAREG_MISC_IOADSEL (0x1 << 0) +#define MGAREG_MISC_RAMMAPEN (0x1 << 1) +#define MGAREG_MISC_CLK_SEL_VGA25 (0x0 << 2) +#define MGAREG_MISC_CLK_SEL_VGA28 (0x1 << 2) +#define MGAREG_MISC_CLK_SEL_MGA_PIX (0x2 << 2) +#define MGAREG_MISC_CLK_SEL_MGA_MSK (0x3 << 2) +#define MGAREG_MISC_VIDEO_DIS (0x1 << 4) +#define MGAREG_MISC_HIGH_PG_SEL (0x1 << 5) + +/* MMIO VGA registers */ +#define MGAREG_SEQ_INDEX 0x1fc4 +#define MGAREG_SEQ_DATA 0x1fc5 +#define MGAREG_CRTC_INDEX 0x1fd4 +#define MGAREG_CRTC_DATA 0x1fd5 +#define MGAREG_CRTCEXT_INDEX 0x1fde +#define MGAREG_CRTCEXT_DATA 0x1fdf + + + +/* MGA bits for registers PCI_OPTION_REG */ +#define MGA1064_OPT_SYS_CLK_PCI ( 0x00 << 0 ) +#define MGA1064_OPT_SYS_CLK_PLL ( 0x01 << 0 ) +#define MGA1064_OPT_SYS_CLK_EXT ( 0x02 << 0 ) +#define MGA1064_OPT_SYS_CLK_MSK ( 0x03 << 0 ) + +#define MGA1064_OPT_SYS_CLK_DIS ( 0x01 << 2 ) +#define MGA1064_OPT_G_CLK_DIV_1 ( 0x01 << 3 ) +#define MGA1064_OPT_M_CLK_DIV_1 ( 0x01 << 4 ) + +#define MGA1064_OPT_SYS_PLL_PDN ( 0x01 << 5 ) +#define MGA1064_OPT_VGA_ION ( 0x01 << 8 ) + +/* MGA registers in PCI config space */ +#define PCI_MGA_INDEX 0x44 +#define PCI_MGA_DATA 0x48 +#define PCI_MGA_OPTION2 0x50 +#define PCI_MGA_OPTION3 0x54 + +#define RAMDAC_OFFSET 0x3c00 + +/* TVP3026 direct registers */ + +#define TVP3026_INDEX 0x00 +#define TVP3026_WADR_PAL 0x00 +#define TVP3026_COL_PAL 0x01 +#define TVP3026_PIX_RD_MSK 0x02 +#define TVP3026_RADR_PAL 0x03 +#define TVP3026_CUR_COL_ADDR 0x04 +#define TVP3026_CUR_COL_DATA 0x05 +#define TVP3026_DATA 0x0a +#define TVP3026_CUR_RAM 0x0b +#define TVP3026_CUR_XLOW 0x0c +#define TVP3026_CUR_XHI 0x0d +#define TVP3026_CUR_YLOW 0x0e +#define TVP3026_CUR_YHI 0x0f + +/* TVP3026 indirect registers */ + +#define TVP3026_SILICON_REV 0x01 +#define TVP3026_CURSOR_CTL 0x06 +#define TVP3026_LATCH_CTL 0x0f +#define TVP3026_TRUE_COLOR_CTL 0x18 +#define TVP3026_MUX_CTL 0x19 +#define TVP3026_CLK_SEL 0x1a +#define TVP3026_PAL_PAGE 0x1c +#define TVP3026_GEN_CTL 0x1d +#define TVP3026_MISC_CTL 0x1e +#define TVP3026_GEN_IO_CTL 0x2a +#define TVP3026_GEN_IO_DATA 0x2b +#define TVP3026_PLL_ADDR 0x2c +#define TVP3026_PIX_CLK_DATA 0x2d +#define TVP3026_MEM_CLK_DATA 0x2e +#define TVP3026_LOAD_CLK_DATA 0x2f +#define TVP3026_KEY_RED_LOW 0x32 +#define TVP3026_KEY_RED_HI 0x33 +#define TVP3026_KEY_GREEN_LOW 0x34 +#define TVP3026_KEY_GREEN_HI 0x35 +#define TVP3026_KEY_BLUE_LOW 0x36 +#define TVP3026_KEY_BLUE_HI 0x37 +#define TVP3026_KEY_CTL 0x38 +#define TVP3026_MCLK_CTL 0x39 +#define TVP3026_SENSE_TEST 0x3a +#define TVP3026_TEST_DATA 0x3b +#define TVP3026_CRC_LSB 0x3c +#define TVP3026_CRC_MSB 0x3d +#define TVP3026_CRC_CTL 0x3e +#define TVP3026_ID 0x3f +#define TVP3026_RESET 0xff + + +/* MGA1064 DAC Register file */ +/* MGA1064 direct registers */ + +#define MGA1064_INDEX 0x00 +#define MGA1064_WADR_PAL 0x00 +#define MGA1064_COL_PAL 0x01 +#define MGA1064_PIX_RD_MSK 0x02 +#define MGA1064_RADR_PAL 0x03 +#define MGA1064_DATA 0x0a + +#define MGA1064_CUR_XLOW 0x0c +#define MGA1064_CUR_XHI 0x0d +#define MGA1064_CUR_YLOW 0x0e +#define MGA1064_CUR_YHI 0x0f + +/* MGA1064 indirect registers */ +#define MGA1064_DVI_PIPE_CTL 0x03 +#define MGA1064_CURSOR_BASE_ADR_LOW 0x04 +#define MGA1064_CURSOR_BASE_ADR_HI 0x05 +#define MGA1064_CURSOR_CTL 0x06 +#define MGA1064_CURSOR_COL0_RED 0x08 +#define MGA1064_CURSOR_COL0_GREEN 0x09 +#define MGA1064_CURSOR_COL0_BLUE 0x0a + +#define MGA1064_CURSOR_COL1_RED 0x0c +#define MGA1064_CURSOR_COL1_GREEN 0x0d +#define MGA1064_CURSOR_COL1_BLUE 0x0e + +#define MGA1064_CURSOR_COL2_RED 0x010 +#define MGA1064_CURSOR_COL2_GREEN 0x011 +#define MGA1064_CURSOR_COL2_BLUE 0x012 + +#define MGA1064_VREF_CTL 0x018 + +#define MGA1064_MUL_CTL 0x19 +#define MGA1064_MUL_CTL_8bits 0x0 +#define MGA1064_MUL_CTL_15bits 0x01 +#define MGA1064_MUL_CTL_16bits 0x02 +#define MGA1064_MUL_CTL_24bits 0x03 +#define MGA1064_MUL_CTL_32bits 0x04 +#define MGA1064_MUL_CTL_2G8V16bits 0x05 +#define MGA1064_MUL_CTL_G16V16bits 0x06 +#define MGA1064_MUL_CTL_32_24bits 0x07 + +#define MGAGDAC_XVREFCTRL 0x18 +#define MGA1064_PIX_CLK_CTL 0x1a +#define MGA1064_PIX_CLK_CTL_CLK_DIS ( 0x01 << 2 ) +#define MGA1064_PIX_CLK_CTL_CLK_POW_DOWN ( 0x01 << 3 ) +#define MGA1064_PIX_CLK_CTL_SEL_PCI ( 0x00 << 0 ) +#define MGA1064_PIX_CLK_CTL_SEL_PLL ( 0x01 << 0 ) +#define MGA1064_PIX_CLK_CTL_SEL_EXT ( 0x02 << 0 ) +#define MGA1064_PIX_CLK_CTL_SEL_MSK ( 0x03 << 0 ) + +#define MGA1064_GEN_CTL 0x1d +#define MGA1064_MISC_CTL 0x1e +#define MGA1064_MISC_CTL_DAC_POW_DN ( 0x01 << 0 ) +#define MGA1064_MISC_CTL_VGA ( 0x01 << 1 ) +#define MGA1064_MISC_CTL_DIS_CON ( 0x03 << 1 ) +#define MGA1064_MISC_CTL_MAFC ( 0x02 << 1 ) +#define MGA1064_MISC_CTL_VGA8 ( 0x01 << 3 ) +#define MGA1064_MISC_CTL_DAC_RAM_CS ( 0x01 << 4 ) + +#define MGA1064_GEN_IO_CTL 0x2a +#define MGA1064_GEN_IO_DATA 0x2b +#define MGA1064_SYS_PLL_M 0x2c +#define MGA1064_SYS_PLL_N 0x2d +#define MGA1064_SYS_PLL_P 0x2e +#define MGA1064_SYS_PLL_STAT 0x2f +#define MGA1064_ZOOM_CTL 0x38 +#define MGA1064_SENSE_TST 0x3a + +#define MGA1064_CRC_LSB 0x3c +#define MGA1064_CRC_MSB 0x3d +#define MGA1064_CRC_CTL 0x3e +#define MGA1064_COL_KEY_MSK_LSB 0x40 +#define MGA1064_COL_KEY_MSK_MSB 0x41 +#define MGA1064_COL_KEY_LSB 0x42 +#define MGA1064_COL_KEY_MSB 0x43 +#define MGA1064_PIX_PLLA_M 0x44 +#define MGA1064_PIX_PLLA_N 0x45 +#define MGA1064_PIX_PLLA_P 0x46 +#define MGA1064_PIX_PLLB_M 0x48 +#define MGA1064_PIX_PLLB_N 0x49 +#define MGA1064_PIX_PLLB_P 0x4a +#define MGA1064_PIX_PLLC_M 0x4c +#define MGA1064_PIX_PLLC_N 0x4d +#define MGA1064_PIX_PLLC_P 0x4e + +#define MGA1064_PIX_PLL_STAT 0x4f + +/*Added for G450 dual head*/ +/* Supported PLL*/ +#define __PIXEL_PLL 1 +#define __SYSTEM_PLL 2 +#define __VIDEO_PLL 3 + +#define MGA1064_VID_PLL_P 0x8D +#define MGA1064_VID_PLL_M 0x8E +#define MGA1064_VID_PLL_N 0x8F + +#define MGA1064_DISP_CTL 0x8a +#define MGA1064_SYNC_CTL 0x8b +#define MGA1064_PWR_CTL 0xa0 +#define MGA1064_PAN_CTL 0xa2 + +/* Using crtc2 */ +#define MGAREG2_C2CTL 0x10 +#define MGAREG2_C2HPARAM 0x14 +#define MGAREG2_C2HSYNC 0x18 +#define MGAREG2_C2VPARAM 0x1c +#define MGAREG2_C2VSYNC 0x20 +#define MGAREG2_C2STARTADD0 0x28 + +#define MGAREG2_C2OFFSET 0x40 +#define MGAREG2_C2DATACTL 0x4c + +#define MGAREG_C2CTL 0x3c10 +#define MGAREG_C2HPARAM 0x3c14 +#define MGAREG_C2HSYNC 0x3c18 +#define MGAREG_C2VPARAM 0x3c1c +#define MGAREG_C2VSYNC 0x3c20 +#define MGAREG_C2STARTADD0 0x3c28 + +#define MGAREG_C2OFFSET 0x3c40 +#define MGAREG_C2DATACTL 0x3c4c + +#define MGA1064_DISP_CTL 0x8a +#define MGA1064_SYNC_CTL 0x8b +#define MGA1064_PWR_CTL 0xa0 + +/* video register */ + +#define MGAREG_BESA1C3ORG 0x3d60 +#define MGAREG_BESA1CORG 0x3d10 +#define MGAREG_BESA1ORG 0x3d00 +#define MGAREG_BESCTL 0x3d20 +#define MGAREG_BESGLOBCTL 0x3dc0 +#define MGAREG_BESHCOORD 0x3d28 +#define MGAREG_BESHISCAL 0x3d30 +#define MGAREG_BESHSRCEND 0x3d3c +#define MGAREG_BESHSRCLST 0x3d50 +#define MGAREG_BESHSRCST 0x3d38 +#define MGAREG_BESLUMACTL 0x3d40 +#define MGAREG_BESPITCH 0x3d24 +#define MGAREG_BESV1SRCLST 0x3d54 +#define MGAREG_BESV1WGHT 0x3d48 +#define MGAREG_BESVCOORD 0x3d2c +#define MGAREG_BESVISCAL 0x3d34 + +/* texture engine registers */ + +#define MGAREG_TMR0 0x2c00 +#define MGAREG_TMR1 0x2c04 +#define MGAREG_TMR2 0x2c08 +#define MGAREG_TMR3 0x2c0c +#define MGAREG_TMR4 0x2c10 +#define MGAREG_TMR5 0x2c14 +#define MGAREG_TMR6 0x2c18 +#define MGAREG_TMR7 0x2c1c +#define MGAREG_TMR8 0x2c20 +#define MGAREG_TEXORG 0x2c24 +#define MGAREG_TEXWIDTH 0x2c28 +#define MGAREG_TEXHEIGHT 0x2c2c +#define MGAREG_TEXCTL 0x2c30 +#define MGAREG_TEXCTL2 0x2c3c +#define MGAREG_TEXTRANS 0x2c34 +#define MGAREG_TEXTRANSHIGH 0x2c38 +#define MGAREG_TEXFILTER 0x2c58 +#define MGAREG_ALPHASTART 0x2c70 +#define MGAREG_ALPHAXINC 0x2c74 +#define MGAREG_ALPHAYINC 0x2c78 +#define MGAREG_ALPHACTRL 0x2c7c +#define MGAREG_DWGSYNC 0x2c4c + +#define MGAREG_AGP_PLL 0x1e4c +#define MGA_AGP2XPLL_ENABLE 0x1 +#define MGA_AGP2XPLL_DISABLE 0x0 + +#endif |