Compare commits

...

63 Commits

Author SHA1 Message Date
Keith Whitwell
f221b8df75 Comment out debug 2003-03-24 19:00:16 +00:00
Keith Whitwell
45bd335b1c add glViewport calls 2003-03-24 18:46:57 +00:00
Keith Whitwell
6127672e26 Fix rastpos issue in rotated mode 2003-03-24 18:23:32 +00:00
Keith Whitwell
bb3752a434 Further VT switch prototype hacks 2003-03-24 15:49:13 +00:00
Keith Whitwell
56c896a2b8 Some hacks to make prototype VT switching facilities less prone to lockups. 2003-03-24 15:41:32 +00:00
Keith Whitwell
afc72872be Use new XEvent facilities 2003-03-24 15:40:34 +00:00
Keith Whitwell
e511f40795 Set UNPACK_ROW_LENGTH to properly display bitmap fonts. 2003-03-24 15:39:59 +00:00
Jose Fonseca
a53f53ece3 Avoid the mixing of double-colon rules in the Makefiles. 2003-03-24 10:38:30 +00:00
Jose Fonseca
24812b3eaa Enable the full Mesa documentation. 2003-03-24 00:46:36 +00:00
Jose Fonseca
42e0f2ec95 Make a small reference to the distiction between the full and subset documentation start inital pages. 2003-03-23 23:29:05 +00:00
Jose Fonseca
e4fcab7a35 Final documentation fixes and enhancements. 2003-03-23 23:22:47 +00:00
Jose Fonseca
cd6d79a82c Last bits of documentation. Review still pending. 2003-03-23 14:58:08 +00:00
Jose Fonseca
a428744286 More documentation. 2003-03-23 03:51:34 +00:00
Jose Fonseca
ccc6ef28ca More missing files. 2003-03-23 03:48:43 +00:00
Jose Fonseca
3100749dd0 Tweaks to the doxygen configuration files 2003-03-22 16:51:37 +00:00
Jose Fonseca
980e98d324 More documentation. 2003-03-22 16:49:58 +00:00
Keith Whitwell
2204d5bb46 Don't override ctx->Exec->Viewport as there seem to be dependencies
on this being _mesa_Viewport().
2003-03-22 16:19:58 +00:00
Keith Whitwell
67d3c57c46 Tarball build fixes 2003-03-22 14:36:49 +00:00
Keith Whitwell
9e24ff7a0a Remove non-subset fn calls 2003-03-22 14:35:24 +00:00
Keith Whitwell
e014d794f2 Rotate mode 2003-03-22 12:52:29 +00:00
Keith Whitwell
a9bd5a6860 Bring makefile into line with others 2003-03-22 09:29:19 +00:00
Keith Whitwell
94643c4780 Add clean:: target 2003-03-22 08:48:47 +00:00
Keith Whitwell
993502aebc Subset demos 2003-03-22 08:46:22 +00:00
Keith Whitwell
932e26e8f4 Add RotateMode option 2003-03-22 08:45:57 +00:00
Keith Whitwell
54f4c8d1a3 Rotate mode 2003-03-22 08:44:11 +00:00
Keith Whitwell
277d7a2a85 RotateMode changes 2003-03-22 08:43:26 +00:00
Keith Whitwell
0a98671051 Subset demos, link GLU explicitly 2003-03-22 08:41:06 +00:00
Keith Whitwell
a47745e9fd Link GLU explicitly.
Subsetize some more demos.
2003-03-22 08:40:35 +00:00
Keith Whitwell
69ce6b7db0 A cutdown version of Gareth's GLU implementation to get some more demos
working with the subsetted GL.
2003-03-21 13:02:06 +00:00
Keith Whitwell
5d3ab07110 remove old glprocs.h 2003-03-21 11:38:52 +00:00
Keith Whitwell
1613d48989 Build fixes for full driver.
Cope with new location of generated glapi files.
2003-03-21 11:35:14 +00:00
Keith Whitwell
5a610a1974 do screen clear in locked region 2003-03-21 11:33:24 +00:00
Keith Whitwell
afb339bf75 Don't use non-subset functions 2003-03-21 11:32:55 +00:00
Keith Whitwell
16ca6f8e93 Subsetted spec file 2003-03-21 11:20:22 +00:00
Jose Fonseca
41b5963f8d More documentation. 2003-03-20 19:38:39 +00:00
Jose Fonseca
99199c0ece Add a few missing headers to the doxygen input sources. 2003-03-20 19:37:36 +00:00
Keith Whitwell
368d95a7dc Update raster position early to make sure its always done. 2003-03-20 14:44:49 +00:00
Jose Fonseca
0218da1433 Documentation. 2003-03-20 12:56:57 +00:00
Keith Whitwell
6cb2411250 Distribute initialization, cleanup and state-update tasks to the files
where that data is managed.  Thus, the light attribute state is
initialized in light.c, and update_lighting() moves there too.
2003-03-20 09:19:50 +00:00
Jose Fonseca
0d3a504b94 Documentation. 2003-03-19 15:43:14 +00:00
Jose Fonseca
bde16645ca Seperate the subset documentation from the full implementation. 2003-03-19 14:48:17 +00:00
Keith Whitwell
301f7e4408 subsetting 2003-03-18 08:55:20 +00:00
Keith Whitwell
173441d1a6 Further subsetting 2003-03-17 21:22:49 +00:00
Keith Whitwell
64b3e2fa16 Incremental subsetting 2003-03-17 17:03:46 +00:00
Keith Whitwell
6919c50029 Subsetted versions of enable.c and pixel.c 2003-03-17 16:07:21 +00:00
Keith Whitwell
a8512f7dda Continue with subset_texture.c, get some demos working 2003-03-17 15:18:16 +00:00
Jose Fonseca
70217c70be More documentation. 2003-03-16 00:27:12 +00:00
Keith Whitwell
9d4857a816 Very fragile support for VT switching between multiple running apps.
Not safe to use as there is no exclusion from fbdev hw actions at vt switch
time.
2003-03-13 17:13:34 +00:00
Keith Whitwell
3f00e34097 Merge from trunk to bring in GL_ATI_texture_env_combine3 tokens (Jon Smirl) 2003-03-11 10:32:22 +00:00
Keith Whitwell
3e48e6fce4 Add r200 chipids (Jon Smirl) -- for real this time 2003-03-11 10:26:57 +00:00
Keith Whitwell
d1fa9af224 Ugh. Back out bogus commit. 2003-03-11 10:25:28 +00:00
Keith Whitwell
c20d946424 Add r200 chipids (Jon Smirl) 2003-03-11 10:23:45 +00:00
Brian Paul
ff6068b217 merge from 5.0.1 branch 2003-03-10 14:10:46 +00:00
Keith Whitwell
ed1b6e98e2 r200 driver, brought over by Jon Smirl 2003-03-10 11:23:04 +00:00
Keith Whitwell
b52901eb89 Add r200 chipids (Jon Smirl) 2003-03-10 11:07:05 +00:00
Keith Whitwell
cff70d16aa Add FEATURE_texgen (Jon Smirl) 2003-03-10 11:02:14 +00:00
Jose Fonseca
bafbdcb703 Doxygen documentation additions and fixes 2003-03-09 10:52:20 +00:00
Keith Whitwell
50d1c2c921 Define FEATURE_userclip, the first of many? 2003-03-05 14:27:33 +00:00
Keith Whitwell
a1fd12ab84 Remove most of the math module 2003-03-05 14:22:21 +00:00
Keith Whitwell
360bec8a6f Start subsetting core mesa 2003-03-05 14:04:18 +00:00
Keith Whitwell
6440630d79 Use vertex2f instead of 2i 2003-03-05 14:02:44 +00:00
Keith Whitwell
02a6f4b56a Fix modules needed for subset build 2003-03-05 13:16:20 +00:00
Keith Whitwell
f828410458 new file 2003-03-05 13:04:43 +00:00
211 changed files with 34477 additions and 11329 deletions

View File

@@ -1,7 +1,9 @@
*.tag
array_cache
core
core_subset
math
math_subset
miniglx
radeon_subset
swrast

View File

@@ -6,4 +6,5 @@ See http://www.doxygen.org/ for more info.
Either run 'make' (Unix) or 'doxy.bat' (Windows) to run doxygen
and generate souce code documentation.
Then, load doxy/core/index.html into your web browser.
Then, load either doxy/core/index.html or doxy/core_subset/index.html into
your web browser.

View File

@@ -55,7 +55,7 @@ INPUT = ../src/
FILE_PATTERNS = *.c *.h
RECURSIVE = NO
EXCLUDE = ../src/glapitemp.h ../src/glapioffsets.h
EXCLUDE_PATTERNS =
EXCLUDE_PATTERNS = subset_*
EXAMPLE_PATH =
EXAMPLE_PATTERNS =
EXAMPLE_RECURSIVE = NO
@@ -132,13 +132,13 @@ GENERATE_AUTOGEN_DEF = NO
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = NO
EXPAND_ONLY_PREDEF = NO
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
SEARCH_INCLUDES = YES
INCLUDE_PATH = ../include/
INCLUDE_FILE_PATTERNS =
PREDEFINED =
EXPAND_AS_DEFINED =
PREDEFINED = _HAVE_FULL_GL=1
EXPAND_AS_DEFINED = _glthread_DECLARE_STATIC_MUTEX
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration::addtions related to external references
@@ -148,8 +148,7 @@ TAGFILES = tnl_dd.tag=../tnl_dd \
math.tag=../math \
swrast.tag=../swrast \
swrast_setup.tag=../swrast_setup \
tnl.tag=../tnl \
miniglx.tag=../miniglx
tnl.tag=../tnl
GENERATE_TAGFILE = core.tag
ALLEXTERNALS = NO
PERL_PATH =

226
doxygen/core_subset.doxy Normal file
View File

@@ -0,0 +1,226 @@
# Doxyfile 0.1
#---------------------------------------------------------------------------
# General configuration options
#---------------------------------------------------------------------------
PROJECT_NAME = "Mesa Core"
PROJECT_NUMBER =
OUTPUT_DIRECTORY =
OUTPUT_LANGUAGE = English
EXTRACT_ALL = NO
EXTRACT_PRIVATE = NO
EXTRACT_STATIC = YES
EXTRACT_LOCAL_CLASSES = YES
HIDE_UNDOC_MEMBERS = NO
HIDE_UNDOC_CLASSES = 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 = YES
STRIP_CODE_COMMENTS = YES
CASE_SENSE_NAMES = YES
SHORT_NAMES = NO
HIDE_SCOPE_NAMES = NO
VERBATIM_HEADERS = YES
SHOW_INCLUDE_FILES = YES
JAVADOC_AUTOBRIEF = NO
INHERIT_DOCS = YES
INLINE_INFO = YES
SORT_MEMBER_DOCS = NO
DISTRIBUTE_GROUP_DOC = NO
TAB_SIZE = 8
GENERATE_TODOLIST = YES
GENERATE_TESTLIST = YES
GENERATE_BUGLIST = YES
ALIASES =
ENABLED_SECTIONS = subset
MAX_INITIALIZER_LINES = 30
OPTIMIZE_OUTPUT_FOR_C = NO
SHOW_USED_FILES = YES
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
QUIET = YES
WARNINGS = YES
WARN_IF_UNDOCUMENTED = NO
WARN_FORMAT =
WARN_LOGFILE =
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = ../src/
FILE_PATTERNS = \
accum.h \
attrib.h \
blend.[ch] \
buffers.[ch] \
dd.h \
debug.h \
depth.h \
dlist.h \
context.[ch] \
config.h \
colormac.h \
colortab.h \
enable.h \
enums.h \
eval.h \
extensions.h \
feedback.[ch] \
fog.h \
get.h \
glheader.h \
glthread.h \
hash.[ch] \
hint.h \
histogram.h \
image.[ch] \
imports.[ch] \
lines.[ch] \
light.h \
matrix.[ch] \
macros.h \
mmath.h \
mtypes.h \
pixel.h \
points.[ch] \
polygon.[ch] \
rastpos.[ch] \
simple_list.h \
state.[ch] \
stencil.[ch] \
subset_*.c \
texformat.h \
teximage.h \
texstate.h \
texstore.h \
texobj.[ch] \
texutil_tmp.h \
varray.h
RECURSIVE = NO
EXCLUDE =
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 = YES
INLINE_SOURCES = NO
REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = 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 = core_subset
HTML_HEADER = header_subset.html
HTML_FOOTER =
HTML_STYLESHEET =
HTML_ALIGN_MEMBERS = YES
GENERATE_HTMLHELP = NO
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 = NO
LATEX_OUTPUT =
COMPACT_LATEX = NO
PAPER_TYPE = a4wide
EXTRA_PACKAGES =
LATEX_HEADER =
PDF_HYPERLINKS = NO
USE_PDFLATEX = NO
LATEX_BATCHMODE = NO
#---------------------------------------------------------------------------
# configuration options related to the RTF output
#---------------------------------------------------------------------------
GENERATE_RTF = NO
RTF_OUTPUT =
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_EXTENSION =
MAN_LINKS = NO
#---------------------------------------------------------------------------
# configuration options related to the XML output
#---------------------------------------------------------------------------
GENERATE_XML = NO
#---------------------------------------------------------------------------
# configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = NO
EXPAND_ONLY_PREDEF = NO
SEARCH_INCLUDES = YES
INCLUDE_PATH = ../include/
INCLUDE_FILE_PATTERNS =
PREDEFINED =
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration::addtions related to external references
#---------------------------------------------------------------------------
TAGFILES = \
math_subset.tag=../math_subset \
miniglx.tag=../miniglx
GENERATE_TAGFILE = core_subset.tag
ALLEXTERNALS = NO
PERL_PATH =
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
CLASS_DIAGRAMS = NO
HAVE_DOT = NO
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
TEMPLATE_RELATIONS = YES
HIDE_UNDOC_RELATIONS = YES
INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
GRAPHICAL_HIERARCHY = YES
DOT_PATH =
DOTFILE_DIRS =
MAX_DOT_GRAPH_WIDTH = 1024
MAX_DOT_GRAPH_HEIGHT = 1024
GENERATE_LEGEND = YES
DOT_CLEANUP = YES
#---------------------------------------------------------------------------
# Configuration::addtions related to the search engine
#---------------------------------------------------------------------------
SEARCHENGINE = NO
CGI_NAME =
CGI_URL =
DOC_URL =
DOC_ABSPATH =
BIN_ABSPATH =
EXT_DOC_PATHS =

View File

@@ -3,12 +3,10 @@
</head>
<body><center>
<a href="../core/index.html">Mesa Core</a>&nbsp;
<a href="../miniglx/index.html">MiniGLX</a>&nbsp;
<a href="../array_cache/index.html">array_cache</a>&nbsp;
<a href="../math/index.html">math</a>&nbsp;
<a href="../swrast/index.html">swrast</a>&nbsp;
<a href="../swrast_setup/index.html">swrast_setup</a>&nbsp;
<a href="../tnl/index.html">tnl</a>&nbsp;
<a href="../tnl_dd/index.html">tnl_dd</a>&nbsp;
<a href="../radeon_subset/index.html">radeon_subset</a>&nbsp;
</center>
</center>

View File

@@ -0,0 +1,9 @@
<html><head><title>Mesa Source Code Documentation</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head>
<body><center>
<a href="../core_subset/index.html">Mesa Core</a>&nbsp;
<a href="../math_subset/index.html">math</a>&nbsp;
<a href="../miniglx/index.html">MiniGLX</a>&nbsp;
<a href="../radeon_subset/index.html">radeon_subset</a>&nbsp;
</center>

View File

@@ -1,11 +1,12 @@
default:
default: subset
full:
doxygen tnl_dd.doxy
doxygen array_cache.doxy
doxygen math.doxy
doxygen swrast.doxy
doxygen swrast_setup.doxy
doxygen tnl.doxy
doxygen miniglx.doxy
doxygen core.doxy
echo "Building again, to resolve tags"
doxygen tnl_dd.doxy
@@ -14,11 +15,30 @@ default:
doxygen swrast.doxy
doxygen swrast_setup.doxy
doxygen tnl.doxy
doxygen core.doxy
subset:
doxygen core_subset.doxy
doxygen math_subset.doxy
doxygen miniglx.doxy
echo "Building again, to resolve tags"
doxygen core_subset.doxy
doxygen math_subset.doxy
doxygen miniglx.doxy
doxygen radeon_subset.doxy
clean:
rm -rf array_cache core math swrast swrast_setup tnl_dd tnl miniglx radeon_subset
rm -rf \
array_cache \
core \
core_subset \
math \
math_subset \
swrast \
swrast_setup \
tnl_dd \
tnl \
miniglx \
radeon_subset
rm -rf *.tag

177
doxygen/math_subset.doxy Normal file
View File

@@ -0,0 +1,177 @@
# Doxyfile 0.1
#---------------------------------------------------------------------------
# General configuration options
#---------------------------------------------------------------------------
PROJECT_NAME = "Mesa math module"
PROJECT_NUMBER =
OUTPUT_DIRECTORY = .
OUTPUT_LANGUAGE = English
EXTRACT_ALL = NO
EXTRACT_PRIVATE = NO
EXTRACT_STATIC = YES
EXTRACT_LOCAL_CLASSES = YES
HIDE_UNDOC_MEMBERS = NO
HIDE_UNDOC_CLASSES = 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
STRIP_CODE_COMMENTS = YES
CASE_SENSE_NAMES = YES
SHORT_NAMES = NO
HIDE_SCOPE_NAMES = NO
VERBATIM_HEADERS = YES
SHOW_INCLUDE_FILES = YES
JAVADOC_AUTOBRIEF = NO
INHERIT_DOCS = YES
INLINE_INFO = YES
SORT_MEMBER_DOCS = NO
DISTRIBUTE_GROUP_DOC = NO
TAB_SIZE = 8
GENERATE_TODOLIST = YES
GENERATE_TESTLIST = YES
GENERATE_BUGLIST = YES
ALIASES =
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
OPTIMIZE_OUTPUT_FOR_C = YES
SHOW_USED_FILES = YES
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
QUIET = YES
WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
WARN_FORMAT =
WARN_LOGFILE =
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = ../src/math/
FILE_PATTERNS = m_matrix.[ch]
RECURSIVE = NO
EXCLUDE =
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
REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = 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 = math_subset
HTML_HEADER = header_subset.html
HTML_FOOTER =
HTML_STYLESHEET =
HTML_ALIGN_MEMBERS = YES
GENERATE_HTMLHELP = NO
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 = NO
LATEX_OUTPUT =
COMPACT_LATEX = NO
PAPER_TYPE = a4wide
EXTRA_PACKAGES =
LATEX_HEADER =
PDF_HYPERLINKS = NO
USE_PDFLATEX = NO
LATEX_BATCHMODE = NO
#---------------------------------------------------------------------------
# configuration options related to the RTF output
#---------------------------------------------------------------------------
GENERATE_RTF = NO
RTF_OUTPUT =
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_EXTENSION =
MAN_LINKS = NO
#---------------------------------------------------------------------------
# configuration options related to the XML output
#---------------------------------------------------------------------------
GENERATE_XML = NO
#---------------------------------------------------------------------------
# configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# 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 = core_subset.tag=../core_subset
GENERATE_TAGFILE = math_subset.tag
ALLEXTERNALS = NO
PERL_PATH =
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
CLASS_DIAGRAMS = YES
HAVE_DOT = NO
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
TEMPLATE_RELATIONS = YES
HIDE_UNDOC_RELATIONS = YES
INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
GRAPHICAL_HIERARCHY = YES
DOT_PATH =
DOTFILE_DIRS =
MAX_DOT_GRAPH_WIDTH = 1024
MAX_DOT_GRAPH_HEIGHT = 1024
GENERATE_LEGEND = YES
DOT_CLEANUP = YES
#---------------------------------------------------------------------------
# Configuration::addtions related to the search engine
#---------------------------------------------------------------------------
SEARCHENGINE = NO
CGI_NAME =
CGI_URL =
DOC_URL =
DOC_ABSPATH =
BIN_ABSPATH =
EXT_DOC_PATHS =

View File

@@ -80,7 +80,7 @@ IGNORE_PREFIX =
#---------------------------------------------------------------------------
GENERATE_HTML = YES
HTML_OUTPUT = miniglx
HTML_HEADER = header.html
HTML_HEADER = header_subset.html
HTML_FOOTER =
HTML_STYLESHEET =
HTML_ALIGN_MEMBERS = YES
@@ -143,14 +143,9 @@ SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration::addtions related to external references
#---------------------------------------------------------------------------
TAGFILES = core.tag=../core \
tnl_dd.tag=../tnl_dd \
array_cache.tag=../array_cache \
math.tag=../math \
swrast.tag=../swrast \
swrast_setup.tag=../swrast_setup \
tnl.tag=../tnl \
array_cache.tag=array_cache
TAGFILES = \
core_subset.tag=../core_subset \
math_subset.tag=../math_subset
GENERATE_TAGFILE = miniglx.tag
ALLEXTERNALS = NO
PERL_PATH =

View File

@@ -103,7 +103,7 @@ IGNORE_PREFIX =
#---------------------------------------------------------------------------
GENERATE_HTML = YES
HTML_OUTPUT = radeon_subset
HTML_HEADER = header.html
HTML_HEADER = header_subset.html
HTML_FOOTER =
HTML_STYLESHEET =
HTML_ALIGN_MEMBERS = YES
@@ -166,15 +166,10 @@ SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration::addtions related to external references
#---------------------------------------------------------------------------
TAGFILES = core.tag=../core \
tnl_dd.tag=../tnl_dd \
array_cache.tag=../array_cache \
math.tag=../math \
swrast.tag=../swrast \
swrast_setup.tag=../swrast_setup \
tnl.tag=../tnl \
miniglx.tag=../miniglx \
array_cache.tag=array_cache
TAGFILES = \
core_subset.tag=../core_subset \
math_subset.tag=../math_subset \
miniglx.tag=../miniglx
GENERATE_TAGFILE = radeon_subset.tag
ALLEXTERNALS = NO
PERL_PATH =

View File

@@ -1,10 +1,9 @@
/* $Id: gl.h,v 1.72 2002/10/17 19:39:31 kschultz Exp $ */
/*
* Mesa 3-D graphics library
* Version: 4.1
* Version: 5.0.1
*
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
* Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -2646,6 +2645,13 @@ GLAPI void GLAPIENTRY glTracePointerRangeMESA( const GLvoid* first, const GLvoid
#endif /* GL_APPLE_ycbcr_422 */
#ifndef GL_ATI_texture_env_combine3
#define GL_ATI_texture_env_combine3 1
#define GL_MODULATE_ADD_ATI 0x8744
#define GL_MODULATE_SIGNED_ADD_ATI 0x8745
#define GL_MODULATE_SUBTRACT_ATI 0x8746
#endif
/**********************************************************************
* Begin system-specific stuff

View File

@@ -2423,6 +2423,11 @@ extern "C" {
#define GL_ACTIVE_STENCIL_FACE_EXT 0x8911
#endif
#ifndef GL_ATI_texture_env_combine3
#define GL_MODULATE_ADD_ATI 0x8744
#define GL_MODULATE_SIGNED_ADD_ATI 0x8745
#define GL_MODULATE_SUBTRACT_ATI 0x8746
#endif
/*************************************************************/
@@ -5016,6 +5021,9 @@ GLAPI void APIENTRY glActiveStencilFaceEXT (GLenum);
typedef void (APIENTRY * PFNGLACTIVESTENCILFACEEXTPROC) (GLenum face);
#endif
#ifndef GL_ATI_texture_env_combine3
#define GL_ATI_texture_env_combine3 1
#endif
#ifdef __cplusplus
}

View File

@@ -14,12 +14,12 @@ PROGS = gears \
# make executable from .c file:
.c: $(LIB_DEP)
gcc -I../include -I../util -g $< -L../lib -lglut -lGL -lm -o $@
gcc -I../include -I../util -g $< -L../lib -lglut -lGL -lGLU -lm -o $@
default: $(PROGS)
clean:
-rm *.o *~
-rm -f *.o *~ $(PROGS)

View File

@@ -1,4 +1,4 @@
/* $Id: bounce.c,v 1.3.8.1 2003/02/23 19:25:07 keithw Exp $ */
/* $Id: bounce.c,v 1.3.8.2 2003/03/22 08:40:35 keithw Exp $ */
/*
* Bouncing ball demo.
@@ -115,15 +115,15 @@ draw(void)
glColor3f(0, 1, 1);
glBegin(GL_LINES);
for (i = -5; i <= 5; i++) {
glVertex2i(i, -5);
glVertex2i(i, 5);
glVertex2f(i, -5);
glVertex2f(i, 5);
}
for (i = -5; i <= 5; i++) {
glVertex2i(-5, i);
glVertex2i(5, i);
glVertex2f(-5, i);
glVertex2f(5, i);
}
for (i = -5; i <= 5; i++) {
glVertex2i(i, -5);
glVertex2f(i, -5);
glVertex2f(i * 1.15, -5.9);
}
glVertex2f(-5.3, -5.35);

View File

@@ -1,4 +1,4 @@
/* $Id: isosurf.c,v 1.15.4.1 2003/02/23 21:04:25 keithw Exp $ */
/* $Id: isosurf.c,v 1.15.4.2 2003/03/22 08:40:35 keithw Exp $ */
/*
* Display an isosurface of 3-D wind speed volume.
@@ -37,7 +37,7 @@
#define GL_GLEXT_LEGACY
#include "GL/glut.h"
#include "readtex.c" /* I know, this is a hack. KW: me too. */
#include "readtex.c"
#define TEXTURE_FILE "../images/reflect.rgb"
#define LIT 0x00000001
@@ -805,10 +805,10 @@ static void Init(int argc, char *argv[])
expand_arrays();
make_tri_indices();
if (!LoadRGBMipmaps(TEXTURE_FILE, GL_RGB)) {
printf("Error: couldn't load texture image\n");
exit(1);
}
/* if (!LoadRGBMipmaps(TEXTURE_FILE, GL_RGB)) { */
/* printf("Error: couldn't load texture image\n"); */
/* exit(1); */
/* } */
}
}

View File

@@ -680,18 +680,13 @@ loadpic(void)
}
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
if ((gluerr = gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, 256, 256, GL_RGBA,
GL_UNSIGNED_BYTE,
(GLvoid *) (&terrainpic[0][0])))) {
fprintf(stderr, "GLULib%s\n", (char *) gluErrorString(gluerr));
exit(-1);
}
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, GL_RGBA, 256, 256, GL_RGBA,
GL_UNSIGNED_BYTE, (GLvoid *) terrainpic);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

View File

@@ -1,4 +1,4 @@
/* $Id: texobj.c,v 1.6.6.1 2003/02/23 19:25:07 keithw Exp $ */
/* $Id: texobj.c,v 1.6.6.2 2003/03/22 08:40:35 keithw Exp $ */
/*
* Example of using the 1.1 texture object functions.
@@ -50,7 +50,7 @@ static void draw( void )
#endif
}
else {
glCallList( TexObj[0] );
/* glCallList( TexObj[0] ); */
}
glBegin( GL_POLYGON );
glTexCoord2f( 0.0, 0.0 ); glVertex2f( -1.0, -1.0 );
@@ -70,7 +70,7 @@ static void draw( void )
#endif
}
else {
glCallList( TexObj[1] );
/* glCallList( TexObj[1] ); */
}
glBegin( GL_POLYGON );
glTexCoord2f( 0.0, 0.0 ); glVertex2f( -1.0, -1.0 );
@@ -166,8 +166,8 @@ static void init( void )
#endif
}
else {
TexObj[0] = glGenLists(2);
TexObj[1] = TexObj[0]+1;
/* TexObj[0] = glGenLists(2); */
/* TexObj[1] = TexObj[0]+1; */
}
/* setup first texture object */
@@ -178,7 +178,7 @@ static void init( void )
#endif
}
else {
glNewList( TexObj[0], GL_COMPILE );
/* glNewList( TexObj[0], GL_COMPILE ); */
}
/* red on white */
for (i=0;i<height;i++) {
@@ -201,7 +201,7 @@ static void init( void )
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
if (!UseObj) {
glEndList();
/* glEndList(); */
}
/* end of texture object */
@@ -214,7 +214,7 @@ static void init( void )
/* assert(!glIsTexture(TexObj[1] + 999)); */
}
else {
glNewList( TexObj[1], GL_COMPILE );
/* glNewList( TexObj[1], GL_COMPILE ); */
}
/* green on blue */
for (i=0;i<height;i++) {
@@ -235,7 +235,7 @@ static void init( void )
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
if (!UseObj) {
glEndList();
/* glEndList(); */
}
/* end texture object */

View File

@@ -17,12 +17,14 @@ PROGS = prim \
# make executable from .c file:
.c: $(LIB_DEP)
gcc -I../include -g $< -L../lib -lglut -lGL -lm -o $@
gcc -I../include -g $< -L../lib -lglut -lGL -lGLU -lm -o $@
default: $(PROGS)
clean:
-rm *.o *~
clean: clean_here
clean_here:
rm -f *.o *~ $(PROGS)

View File

@@ -62,7 +62,7 @@ static void Init(void)
GLint i;
glClearColor(0.0, 0.0, 0.0, 0.0);
glClearIndex(0.0);
/* glClearIndex(0.0); */
if (!rgb) {
for (i = 0; i < 16; i++) {
@@ -71,7 +71,7 @@ static void Init(void)
}
}
glPolygonStipple(stippleBits);
/* glPolygonStipple(stippleBits); */
antiAlias = GL_FALSE;
stipple = GL_FALSE;
@@ -135,11 +135,11 @@ static void Draw(void)
}
glBegin(GL_TRIANGLES);
(rgb) ? glColor3fv(RGBMap[COLOR_BLUE]) : glIndexi(ci1);
glColor3fv(RGBMap[COLOR_BLUE]);
glVertex3f( 0.9, -0.9, -30.0);
glVertex3f( 0.9, 0.9, -30.0);
glVertex3f(-0.9, 0.0, -30.0);
(rgb) ? glColor3fv(RGBMap[COLOR_GREEN]) : glIndexi(ci2);
glColor3fv(RGBMap[COLOR_GREEN]);
glVertex3f(-0.9, -0.9, -40.0);
glVertex3f(-0.9, 0.9, -40.0);
glVertex3f( 0.9, 0.0, -25.0);

View File

@@ -141,7 +141,7 @@ static void Draw(void)
for (i = 0; i < 360; i += 5) {
glRotatef(5.0, 0,0,1);
(rgb) ? glColor3f(1.0, 1.0, 0.0) : glIndexi(ci);
glColor3f(1.0, 1.0, 0.0);
glBegin(GL_LINE_STRIP);
glVertex3fv(pntA);
glVertex3fv(pntB);
@@ -199,7 +199,7 @@ int main(int argc, char **argv)
glutInitWindowPosition(0, 0); glutInitWindowSize( 300, 300);
windType = (rgb) ? GLUT_RGB : GLUT_INDEX;
windType = GLUT_RGB;
windType |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
glutInitDisplayMode(windType);

View File

@@ -153,9 +153,9 @@ static void Draw(void)
/* glPointSize(size); */
if (mode) {
(rgb) ? glColor3f(1.0, 0.0, 0.0) : glIndexf(CI_ANTI_ALIAS_RED);
glColor3f(1.0, 0.0, 0.0);
} else {
(rgb) ? glColor3f(1.0, 0.0, 0.0) : glIndexf(CI_RED);
glColor3f(1.0, 0.0, 0.0);
}
glBegin(GL_POINTS);
glVertex3fv(point);

View File

@@ -126,18 +126,18 @@ static void Point(void)
glBegin(GL_POINTS);
SetColor(COLOR_WHITE);
glVertex2i(0, 0);
glVertex2f(0, 0);
for (i = 1; i < 8; i++) {
GLint j = i * 2;
SetColor(COLOR_BLACK+i);
glVertex2i(-j, -j);
glVertex2i(-j, 0);
glVertex2i(-j, j);
glVertex2i(0, j);
glVertex2i(j, j);
glVertex2i(j, 0);
glVertex2i(j, -j);
glVertex2i(0, -j);
glVertex2f(-j, -j);
glVertex2f(-j, 0);
glVertex2f(-j, j);
glVertex2f(0, j);
glVertex2f(j, j);
glVertex2f(j, 0);
glVertex2f(j, -j);
glVertex2f(0, -j);
}
glEnd();
}
@@ -152,8 +152,8 @@ static void Lines(void)
for (i = 1; i < 8; i++) {
SetColor(COLOR_BLACK+i);
glBegin(GL_LINES);
glVertex2i(-boxW/4, -boxH/4);
glVertex2i(boxW/4, boxH/4);
glVertex2f(-boxW/4, -boxH/4);
glVertex2f(boxW/4, boxH/4);
glEnd();
glTranslatef(4, 0, 0);
}
@@ -161,7 +161,7 @@ static void Lines(void)
glPopMatrix();
glBegin(GL_LINES);
glVertex2i(0, 0);
glVertex2f(0, 0);
glEnd();
}
@@ -180,7 +180,7 @@ static void LineStrip(void)
glEnd();
glBegin(GL_LINE_STRIP);
glVertex2i(0, 0);
glVertex2f(0, 0);
glEnd();
}
@@ -218,11 +218,11 @@ static void LineLoop(void)
SetColor(COLOR_GREEN);
glBegin(GL_POINTS);
glVertex2i(0, 0);
glVertex2f(0, 0);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex2i(0, 0);
glVertex2f(0, 0);
glEnd();
}
@@ -231,16 +231,16 @@ static void Bitmap(void)
glBegin(GL_LINES);
SetColor(COLOR_GREEN);
glVertex2i(-boxW/2, 0);
glVertex2i(boxW/2, 0);
glVertex2i(0, -boxH/2);
glVertex2i(0, boxH/2);
glVertex2f(-boxW/2, 0);
glVertex2f(boxW/2, 0);
glVertex2f(0, -boxH/2);
glVertex2f(0, boxH/2);
SetColor(COLOR_RED);
glVertex2i(0, -3);
glVertex2i(0, -3+OPENGL_HEIGHT);
glVertex2f(0, -3);
glVertex2f(0, -3+OPENGL_HEIGHT);
SetColor(COLOR_BLUE);
glVertex2i(0, -3);
glVertex2i(OPENGL_WIDTH, -3);
glVertex2f(0, -3);
glVertex2f(OPENGL_WIDTH, -3);
glEnd();
SetColor(COLOR_GREEN);
@@ -257,23 +257,23 @@ static void Triangles(void)
glBegin(GL_TRIANGLES);
SetColor(COLOR_GREEN);
glVertex2i(-boxW/4, -boxH/4);
glVertex2f(-boxW/4, -boxH/4);
SetColor(COLOR_RED);
glVertex2i(-boxW/8, -boxH/16);
glVertex2f(-boxW/8, -boxH/16);
SetColor(COLOR_BLUE);
glVertex2i(boxW/8, -boxH/16);
glVertex2f(boxW/8, -boxH/16);
SetColor(COLOR_GREEN);
glVertex2i(-boxW/4, boxH/4);
glVertex2f(-boxW/4, boxH/4);
SetColor(COLOR_RED);
glVertex2i(-boxW/8, boxH/16);
glVertex2f(-boxW/8, boxH/16);
SetColor(COLOR_BLUE);
glVertex2i(boxW/8, boxH/16);
glVertex2f(boxW/8, boxH/16);
glEnd();
glBegin(GL_TRIANGLES);
glVertex2i(0, 0);
glVertex2i(-100, 100);
glVertex2f(0, 0);
glVertex2f(-100, 100);
glEnd();
}
@@ -282,28 +282,28 @@ static void TriangleStrip(void)
glBegin(GL_TRIANGLE_STRIP);
SetColor(COLOR_GREEN);
glVertex2i(-boxW/4, -boxH/4);
glVertex2f(-boxW/4, -boxH/4);
SetColor(COLOR_RED);
glVertex2i(-boxW/4, boxH/4);
glVertex2f(-boxW/4, boxH/4);
SetColor(COLOR_BLUE);
glVertex2i(0, -boxH/4);
glVertex2f(0, -boxH/4);
SetColor(COLOR_WHITE);
glVertex2i(0, boxH/4);
glVertex2f(0, boxH/4);
SetColor(COLOR_CYAN);
glVertex2i(boxW/4, -boxH/4);
glVertex2f(boxW/4, -boxH/4);
SetColor(COLOR_YELLOW);
glVertex2i(boxW/4, boxH/4);
glVertex2f(boxW/4, boxH/4);
glEnd();
glBegin(GL_TRIANGLE_STRIP);
glVertex2i(0, 0);
glVertex2i(-100, 100);
glVertex2f(0, 0);
glVertex2f(-100, 100);
glEnd();
}
static void TriangleFan(void)
{
GLint vx[8][2];
GLfloat vx[8][2];
GLint x0, y0, x1, y1, x2, y2, x3, y3;
GLint i;
@@ -327,16 +327,16 @@ static void TriangleFan(void)
glBegin(GL_TRIANGLE_FAN);
SetColor(COLOR_WHITE);
glVertex2i(0, 0);
glVertex2f(0, 0);
for (i = 0; i < 8; i++) {
SetColor(COLOR_WHITE-i);
glVertex2iv(vx[i]);
glVertex2fv(vx[i]);
}
glEnd();
glBegin(GL_TRIANGLE_FAN);
glVertex2i(0, 0);
glVertex2i(-100, 100);
glVertex2f(0, 0);
glVertex2f(-100, 100);
glEnd();
}
@@ -349,7 +349,7 @@ static void Rect(void)
static void PolygonFunc(void)
{
GLint vx[8][2];
GLfloat vx[8][2];
GLint x0, y0, x1, y1, x2, y2, x3, y3;
GLint i;
@@ -374,13 +374,13 @@ static void PolygonFunc(void)
glBegin(GL_POLYGON);
for (i = 0; i < 8; i++) {
SetColor(COLOR_WHITE-i);
glVertex2iv(vx[i]);
glVertex2fv(vx[i]);
}
glEnd();
glBegin(GL_POLYGON);
glVertex2i(0, 0);
glVertex2i(100, 100);
glVertex2f(0, 0);
glVertex2f(100, 100);
glEnd();
}
@@ -389,28 +389,28 @@ static void Quads(void)
glBegin(GL_QUADS);
SetColor(COLOR_GREEN);
glVertex2i(-boxW/4, -boxH/4);
glVertex2f(-boxW/4, -boxH/4);
SetColor(COLOR_RED);
glVertex2i(-boxW/8, -boxH/16);
glVertex2f(-boxW/8, -boxH/16);
SetColor(COLOR_BLUE);
glVertex2i(boxW/8, -boxH/16);
glVertex2f(boxW/8, -boxH/16);
SetColor(COLOR_WHITE);
glVertex2i(boxW/4, -boxH/4);
glVertex2f(boxW/4, -boxH/4);
SetColor(COLOR_GREEN);
glVertex2i(-boxW/4, boxH/4);
glVertex2f(-boxW/4, boxH/4);
SetColor(COLOR_RED);
glVertex2i(-boxW/8, boxH/16);
glVertex2f(-boxW/8, boxH/16);
SetColor(COLOR_BLUE);
glVertex2i(boxW/8, boxH/16);
glVertex2f(boxW/8, boxH/16);
SetColor(COLOR_WHITE);
glVertex2i(boxW/4, boxH/4);
glVertex2f(boxW/4, boxH/4);
glEnd();
glBegin(GL_QUADS);
glVertex2i(0, 0);
glVertex2i(100, 100);
glVertex2i(-100, 100);
glVertex2f(0, 0);
glVertex2f(100, 100);
glVertex2f(-100, 100);
glEnd();
}
@@ -419,29 +419,30 @@ static void QuadStrip(void)
glBegin(GL_QUAD_STRIP);
SetColor(COLOR_GREEN);
glVertex2i(-boxW/4, -boxH/4);
glVertex2f(-boxW/4, -boxH/4);
SetColor(COLOR_RED);
glVertex2i(-boxW/4, boxH/4);
glVertex2f(-boxW/4, boxH/4);
SetColor(COLOR_BLUE);
glVertex2i(0, -boxH/4);
glVertex2f(0, -boxH/4);
SetColor(COLOR_WHITE);
glVertex2i(0, boxH/4);
glVertex2f(0, boxH/4);
SetColor(COLOR_CYAN);
glVertex2i(boxW/4, -boxH/4);
glVertex2f(boxW/4, -boxH/4);
SetColor(COLOR_YELLOW);
glVertex2i(boxW/4, boxH/4);
glVertex2f(boxW/4, boxH/4);
glEnd();
glBegin(GL_QUAD_STRIP);
glVertex2i(0, 0);
glVertex2i(100, 100);
glVertex2i(-100, 100);
glVertex2f(0, 0);
glVertex2f(100, 100);
glVertex2f(-100, 100);
glEnd();
}
static void Draw(void)
{
fprintf(stderr, "%s\n", __FUNCTION__);
glViewport(0, 0, windW, windH);
glDisable(GL_SCISSOR_TEST);

View File

@@ -255,7 +255,6 @@ static void Key(unsigned char key, int x, int y)
void Draw(void)
{
MoveStars();
ShowStars();
if (nitro > 0) {

View File

@@ -26,8 +26,8 @@ static void SetColor(int c)
{
if (glutGet(GLUT_WINDOW_RGBA))
glColor3fv(RGBMap[c]);
else
glIndexf(c);
/* else */
/* glIndexf(c); */
}
static void InitMap(void)

View File

@@ -278,11 +278,11 @@ static void Draw(void)
EndPrim();
if (showVerticies) {
(rgb) ? glColor3fv(RGBMap[COLOR_RED]) : glIndexf(color1);
glColor3fv(RGBMap[COLOR_RED]);
/* glRectf(p0[0]-2, p0[1]-2, p0[0]+2, p0[1]+2); */
(rgb) ? glColor3fv(RGBMap[COLOR_GREEN]) : glIndexf(color2);
glColor3fv(RGBMap[COLOR_GREEN]);
/* glRectf(p1[0]-2, p1[1]-2, p1[0]+2, p1[1]+2); */
(rgb) ? glColor3fv(RGBMap[COLOR_BLUE]) : glIndexf(color3);
glColor3fv(RGBMap[COLOR_BLUE]);
/* glRectf(p2[0]-2, p2[1]-2, p2[0]+2, p2[1]+2); */
}
@@ -314,11 +314,11 @@ static void Draw(void)
SetColor(COLOR_RED);
BeginPrim();
(rgb) ? glColor3fv(RGBMap[COLOR_RED]) : glIndexf(color1);
glColor3fv(RGBMap[COLOR_RED]);
glVertex3fv(p0);
(rgb) ? glColor3fv(RGBMap[COLOR_GREEN]) : glIndexf(color2);
glColor3fv(RGBMap[COLOR_GREEN]);
glVertex3fv(p1);
(rgb) ? glColor3fv(RGBMap[COLOR_BLUE]) : glIndexf(color3);
glColor3fv(RGBMap[COLOR_BLUE]);
glVertex3fv(p2);
EndPrim();

View File

@@ -6,9 +6,9 @@
CC = gcc
CFLAGS = -g -I../include
LIBS = -L../lib -lGL -lglut -lm
LIBS = -L../lib -lGL -lGLU -lglut -lm
PROGS = miniglxtest miniglxsample manytex
PROGS = miniglxtest miniglxsample manytex texline
##### RULES #####

View File

@@ -1,4 +1,4 @@
/* $Id: manytex.c,v 1.4 2002/10/18 17:47:36 kschultz Exp $ */
/* $Id: manytex.c,v 1.4.4.1 2003/03/22 08:46:22 keithw Exp $ */
/*
* test handling of many texture maps
@@ -191,8 +191,8 @@ static void Init( void )
glBindTexture(GL_TEXTURE_2D, TextureID[i]);
if (i < LowPriorityCount)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_PRIORITY, 0.5F);
/* if (i < LowPriorityCount) */
/* glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_PRIORITY, 0.5F); */
if (RandomSize) {
#if 0

View File

@@ -79,6 +79,8 @@ MakeWindow(Display * dpy, unsigned int width, unsigned int height)
/* Bind the rendering context and window */
glXMakeCurrent(dpy, win, ctx);
glViewport(0, 0, width, height);
return win;
}

View File

@@ -1,4 +1,4 @@
/* $Id: miniglxtest.c,v 1.1.4.7 2003/02/21 22:18:24 keithw Exp $ */
/* $Id: miniglxtest.c,v 1.1.4.9 2003/03/24 18:46:57 keithw Exp $ */
/*
* Test the mini GLX interface.
@@ -122,6 +122,8 @@ static Window make_rgb_db_window( Display *dpy,
glXMakeCurrent( dpy, win, ctx );
glViewport(0, 0, width, height);
return win;
}
@@ -161,7 +163,6 @@ int foo( )
XMapWindow( dpy, win );
#if !USE_MINI_GLX
{
XEvent e;
while (1) {
@@ -171,8 +172,6 @@ int foo( )
}
}
}
#endif
event_loop( dpy, win );

View File

@@ -1,4 +1,4 @@
/* $Id: texline.c,v 1.4 2002/08/17 00:30:36 brianp Exp $ */
/* $Id: texline.c,v 1.4.6.1 2003/03/22 08:46:22 keithw Exp $ */
/*
* Test textured lines.
@@ -59,7 +59,7 @@ static void Display( void )
y = t * 2.0 - 1.0;
if (!Texture)
glColor3f(1, 0, 1);
glMultiTexCoord2fARB(GL_TEXTURE1_ARB, t, s);
/* glMultiTexCoord2fARB(GL_TEXTURE1_ARB, t, s); */
glTexCoord2f(s, t);
glVertex2f(x, y);
}
@@ -73,12 +73,12 @@ static void Display( void )
if (!Texture)
glColor3f(1, 0, 1);
glTexCoord2f(t, 0.0);
glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0.0, t);
/* glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0.0, t); */
glVertex2f(x, -1.0);
if (!Texture)
glColor3f(0, 1, 0);
glTexCoord2f(t, 1.0);
glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 1.0, t);
/* glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 1.0, t); */
glVertex2f(x, 1.0);
}
glEnd();
@@ -127,22 +127,22 @@ static void Key( unsigned char key, int x, int y )
if (Texture > 2)
Texture = 0;
if (Texture == 0) {
glActiveTextureARB(GL_TEXTURE0_ARB);
glDisable(GL_TEXTURE_2D);
glActiveTextureARB(GL_TEXTURE1_ARB);
/* glActiveTextureARB(GL_TEXTURE0_ARB); */
glDisable(GL_TEXTURE_2D);
/* glActiveTextureARB(GL_TEXTURE1_ARB); */
/* glDisable(GL_TEXTURE_2D); */
}
else if (Texture == 1) {
glActiveTextureARB(GL_TEXTURE0_ARB);
/* glActiveTextureARB(GL_TEXTURE0_ARB); */
glEnable(GL_TEXTURE_2D);
glActiveTextureARB(GL_TEXTURE1_ARB);
glDisable(GL_TEXTURE_2D);
/* glActiveTextureARB(GL_TEXTURE1_ARB); */
/* glDisable(GL_TEXTURE_2D); */
}
else {
glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glActiveTextureARB(GL_TEXTURE1_ARB);
/* glActiveTextureARB(GL_TEXTURE0_ARB); */
glEnable(GL_TEXTURE_2D);
/* glActiveTextureARB(GL_TEXTURE1_ARB); */
/* glEnable(GL_TEXTURE_2D); */
}
break;
case 'w':
@@ -212,8 +212,8 @@ static void SpecialKey( int key, int x, int y )
static void Init( int argc, char *argv[] )
{
GLuint u;
for (u = 0; u < 2; u++) {
glActiveTextureARB(GL_TEXTURE0_ARB + u);
for (u = 0; u < 1; u++) {
/* glActiveTextureARB(GL_TEXTURE0_ARB + u); */
glBindTexture(GL_TEXTURE_2D, 10+u);
if (u == 0)
glEnable(GL_TEXTURE_2D);

7
src/glu/mini/.cvsignore Normal file
View File

@@ -0,0 +1,7 @@
.deps
.libs
Makefile.in
*.lo
*.o
*.la
depend

46
src/glu/mini/Makefile Normal file
View File

@@ -0,0 +1,46 @@
MESA = ../..
default: libGLU.so.1.1 install
include $(MESA)/Makefile.include
LIBDIR = $(MESA)/lib
INCLUDES = -I$(MESA)/include
CFLAGS = -c -g $(INCLUDES) -MD
SOURCES = glu.c \
mipmap.c \
nurbs.c \
polytest.c \
project.c \
quadric.c \
tess.c \
tesselat.c
OBJS = $(addsuffix .o,$(basename $(SOURCES)))
LIBS=-L$(MESA)/lib -lGL -lm
libGLU.so.1.1: $(OBJS) Makefile
gcc -shared -Wl,-soname,libGLU.so -Wl,-Bsymbolic $(OBJS) $(LIBS) -o $@
install:
rm -f $(MESA)/lib/libGLU.so*
install -D libGLU.so.1.1 $(MESA)/lib/libGLU.so.1.1
ln -s libGLU.so.1.1 $(MESA)/lib/libGLU.so.1
ln -s libGLU.so.1 $(MESA)/lib/libGLU.so
clean: clean_here
clean_here:
rm -f ../lib/libGLU.so*
-include $(SOURCES:.c=.d)

55
src/glu/mini/all.h Normal file
View File

@@ -0,0 +1,55 @@
/* $Id: all.h,v 1.1.2.1 2003/03/21 13:02:08 keithw Exp $ */
/*
* Mesa 3-D graphics library
* Version: 3.3
* Copyright (C) 1995-2000 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* This file includes all .h files needed for the GLU source code for
* the purpose of precompiled headers.
*
* If the preprocessor symbol PCH is defined at compile time then each
* of the .c files will #include "all.h" only, instead of a bunch of
* individual .h files.
*/
#ifndef GLU_ALL_H
#define GLU_ALL_H
#ifndef PC_HEADER
This is an error. all.h should be included only if PCH is defined.
#endif
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "GL/gl.h"
#include "GL/glu.h"
#include "gluP.h"
#include "nurbs.h"
#include "tess.h"
#endif /*GLU_ALL_H */

417
src/glu/mini/glu.c Normal file
View File

@@ -0,0 +1,417 @@
/* $Id: glu.c,v 1.1.2.1 2003/03/21 13:02:08 keithw Exp $ */
/*
* Mesa 3-D graphics library
* Version: 3.5
* Copyright (C) 1995-2001 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifdef PC_HEADER
#include "all.h"
#else
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "gluP.h"
#endif
/*
* Miscellaneous utility functions
*/
#ifndef M_PI
#define M_PI 3.1415926536
#endif
#define EPS 0.00001
#ifndef GLU_INCOMPATIBLE_GL_VERSION
#define GLU_INCOMPATIBLE_GL_VERSION 100903
#endif
void GLAPIENTRY
gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez,
GLdouble centerx, GLdouble centery, GLdouble centerz,
GLdouble upx, GLdouble upy, GLdouble upz)
{
GLfloat m[16];
GLfloat x[3], y[3], z[3];
GLfloat mag;
/* Make rotation matrix */
/* Z vector */
z[0] = eyex - centerx;
z[1] = eyey - centery;
z[2] = eyez - centerz;
mag = sqrt(z[0] * z[0] + z[1] * z[1] + z[2] * z[2]);
if (mag) { /* mpichler, 19950515 */
z[0] /= mag;
z[1] /= mag;
z[2] /= mag;
}
/* Y vector */
y[0] = upx;
y[1] = upy;
y[2] = upz;
/* X vector = Y cross Z */
x[0] = y[1] * z[2] - y[2] * z[1];
x[1] = -y[0] * z[2] + y[2] * z[0];
x[2] = y[0] * z[1] - y[1] * z[0];
/* Recompute Y = Z cross X */
y[0] = z[1] * x[2] - z[2] * x[1];
y[1] = -z[0] * x[2] + z[2] * x[0];
y[2] = z[0] * x[1] - z[1] * x[0];
/* mpichler, 19950515 */
/* cross product gives area of parallelogram, which is < 1.0 for
* non-perpendicular unit-length vectors; so normalize x, y here
*/
mag = sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]);
if (mag) {
x[0] /= mag;
x[1] /= mag;
x[2] /= mag;
}
mag = sqrt(y[0] * y[0] + y[1] * y[1] + y[2] * y[2]);
if (mag) {
y[0] /= mag;
y[1] /= mag;
y[2] /= mag;
}
#define M(row,col) m[col*4+row]
M(0, 0) = x[0];
M(0, 1) = x[1];
M(0, 2) = x[2];
M(0, 3) = 0.0;
M(1, 0) = y[0];
M(1, 1) = y[1];
M(1, 2) = y[2];
M(1, 3) = 0.0;
M(2, 0) = z[0];
M(2, 1) = z[1];
M(2, 2) = z[2];
M(2, 3) = 0.0;
M(3, 0) = 0.0;
M(3, 1) = 0.0;
M(3, 2) = 0.0;
M(3, 3) = 1.0;
#undef M
glMultMatrixf(m);
/* Translate Eye to Origin */
glTranslatef(-eyex, -eyey, -eyez);
}
void GLAPIENTRY
gluOrtho2D(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top)
{
glOrtho(left, right, bottom, top, -1.0, 1.0);
}
static void
frustum(GLfloat left, GLfloat right,
GLfloat bottom, GLfloat top,
GLfloat nearval, GLfloat farval)
{
GLfloat x, y, a, b, c, d;
GLfloat m[16];
x = (2.0 * nearval) / (right - left);
y = (2.0 * nearval) / (top - bottom);
a = (right + left) / (right - left);
b = (top + bottom) / (top - bottom);
c = -(farval + nearval) / ( farval - nearval);
d = -(2.0 * farval * nearval) / (farval - nearval);
#define M(row,col) m[col*4+row]
M(0,0) = x; M(0,1) = 0.0F; M(0,2) = a; M(0,3) = 0.0F;
M(1,0) = 0.0F; M(1,1) = y; M(1,2) = b; M(1,3) = 0.0F;
M(2,0) = 0.0F; M(2,1) = 0.0F; M(2,2) = c; M(2,3) = d;
M(3,0) = 0.0F; M(3,1) = 0.0F; M(3,2) = -1.0F; M(3,3) = 0.0F;
#undef M
glMultMatrixf(m);
}
void GLAPIENTRY
gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar)
{
GLfloat xmin, xmax, ymin, ymax;
ymax = zNear * tan(fovy * M_PI / 360.0);
ymin = -ymax;
xmin = ymin * aspect;
xmax = ymax * aspect;
/* don't call glFrustum() because of error semantics (covglu) */
frustum(xmin, xmax, ymin, ymax, zNear, zFar);
}
void GLAPIENTRY
gluPickMatrix(GLdouble x, GLdouble y,
GLdouble width, GLdouble height, GLint viewport[4])
{
GLfloat m[16];
GLfloat sx, sy;
GLfloat tx, ty;
sx = viewport[2] / width;
sy = viewport[3] / height;
tx = (viewport[2] + 2.0 * (viewport[0] - x)) / width;
ty = (viewport[3] + 2.0 * (viewport[1] - y)) / height;
#define M(row,col) m[col*4+row]
M(0, 0) = sx;
M(0, 1) = 0.0;
M(0, 2) = 0.0;
M(0, 3) = tx;
M(1, 0) = 0.0;
M(1, 1) = sy;
M(1, 2) = 0.0;
M(1, 3) = ty;
M(2, 0) = 0.0;
M(2, 1) = 0.0;
M(2, 2) = 1.0;
M(2, 3) = 0.0;
M(3, 0) = 0.0;
M(3, 1) = 0.0;
M(3, 2) = 0.0;
M(3, 3) = 1.0;
#undef M
glMultMatrixf(m);
}
const GLubyte *GLAPIENTRY
gluErrorString(GLenum errorCode)
{
static char *tess_error[] = {
"missing gluBeginPolygon",
"missing gluBeginContour",
"missing gluEndPolygon",
"missing gluEndContour",
"misoriented or self-intersecting loops",
"coincident vertices",
"colinear vertices",
"FIST recovery process fatal error"
};
static char *nurbs_error[] = {
"spline order un-supported",
"too few knots",
"valid knot range is empty",
"decreasing knot sequence knot",
"knot multiplicity greater than order of spline",
"endcurve() must follow bgncurve()",
"bgncurve() must precede endcurve()",
"missing or extra geometric data",
"can't draw pwlcurves",
"missing bgncurve()",
"missing bgnsurface()",
"endtrim() must precede endsurface()",
"bgnsurface() must precede endsurface()",
"curve of improper type passed as trim curve",
"bgnsurface() must precede bgntrim()",
"endtrim() must follow bgntrim()",
"bgntrim() must precede endtrim()",
"invalid or missing trim curve",
"bgntrim() must precede pwlcurve()",
"pwlcurve referenced twice",
"pwlcurve and nurbscurve mixed",
"improper usage of trim data type",
"nurbscurve referenced twice",
"nurbscurve and pwlcurve mixed",
"nurbssurface referenced twice",
"invalid property",
"endsurface() must follow bgnsurface()",
"misoriented trim curves",
"intersecting trim curves",
"UNUSED",
"unconnected trim curves",
"unknown knot error",
"negative vertex count encountered",
"negative byte-stride encountered",
"unknown type descriptor",
"null control array or knot vector",
"duplicate point on pwlcurve"
};
/* GL Errors */
if (errorCode == GL_NO_ERROR) {
return (GLubyte *) "no error";
}
else if (errorCode == GL_INVALID_VALUE) {
return (GLubyte *) "invalid value";
}
else if (errorCode == GL_INVALID_ENUM) {
return (GLubyte *) "invalid enum";
}
else if (errorCode == GL_INVALID_OPERATION) {
return (GLubyte *) "invalid operation";
}
else if (errorCode == GL_STACK_OVERFLOW) {
return (GLubyte *) "stack overflow";
}
else if (errorCode == GL_STACK_UNDERFLOW) {
return (GLubyte *) "stack underflow";
}
else if (errorCode == GL_OUT_OF_MEMORY) {
return (GLubyte *) "out of memory";
}
/* GLU Errors */
else if (errorCode == GLU_NO_ERROR) {
return (GLubyte *) "no error";
}
else if (errorCode == GLU_INVALID_ENUM) {
return (GLubyte *) "invalid enum";
}
else if (errorCode == GLU_INVALID_VALUE) {
return (GLubyte *) "invalid value";
}
else if (errorCode == GLU_OUT_OF_MEMORY) {
return (GLubyte *) "out of memory";
}
else if (errorCode == GLU_INCOMPATIBLE_GL_VERSION) {
return (GLubyte *) "incompatible GL version";
}
else if (errorCode >= GLU_TESS_ERROR1 && errorCode <= GLU_TESS_ERROR8) {
return (GLubyte *) tess_error[errorCode - GLU_TESS_ERROR1];
}
else if (errorCode >= GLU_NURBS_ERROR1 && errorCode <= GLU_NURBS_ERROR37) {
return (GLubyte *) nurbs_error[errorCode - GLU_NURBS_ERROR1];
}
else {
return NULL;
}
}
/*
* New in GLU 1.1
*/
const GLubyte *GLAPIENTRY
gluGetString(GLenum name)
{
static char *extensions = "GL_EXT_abgr";
static char *version = "1.1 Mesa 3.5";
switch (name) {
case GLU_EXTENSIONS:
return (GLubyte *) extensions;
case GLU_VERSION:
return (GLubyte *) version;
default:
return NULL;
}
}
#if 0 /* gluGetProcAddressEXT not finalized yet! */
#ifdef __cplusplus
/* for BeOS R4.5 */
void GLAPIENTRY(*gluGetProcAddressEXT(const GLubyte * procName)) (...)
#else
void (GLAPIENTRY * gluGetProcAddressEXT(const GLubyte * procName)) ()
#endif
{
struct proc
{
const char *name;
void *address;
};
static struct proc procTable[] = {
{"gluGetProcAddressEXT", (void *) gluGetProcAddressEXT}, /* me! */
/* new 1.1 functions */
{"gluGetString", (void *) gluGetString},
/* new 1.2 functions */
{"gluTessBeginPolygon", (void *) gluTessBeginPolygon},
{"gluTessBeginContour", (void *) gluTessBeginContour},
{"gluTessEndContour", (void *) gluTessEndContour},
{"gluTessEndPolygon", (void *) gluTessEndPolygon},
{"gluGetTessProperty", (void *) gluGetTessProperty},
/* new 1.3 functions */
{NULL, NULL}
};
GLuint i;
for (i = 0; procTable[i].address; i++) {
if (strcmp((const char *) procName, procTable[i].name) == 0)
return (void (GLAPIENTRY *) ()) procTable[i].address;
}
return NULL;
}
#endif
/*
* New in GLU 1.3
*/
#ifdef GLU_VERSION_1_3
GLboolean GLAPIENTRY
gluCheckExtension(const GLubyte *extName, const GLubyte * extString)
{
assert(extName);
assert(extString);
{
const int len = strlen((const char *) extName);
const char *start = (const char *) extString;
while (1) {
const char *c = strstr(start, (const char *) extName);
if (!c)
return GL_FALSE;
if ((c == start || c[-1] == ' ') && (c[len] == ' ' || c[len] == 0))
return GL_TRUE;
start = c + len;
}
}
}
#endif

142
src/glu/mini/gluP.h Normal file
View File

@@ -0,0 +1,142 @@
/* $Id: gluP.h,v 1.1.2.1 2003/03/21 13:02:10 keithw Exp $ */
/*
* Mesa 3-D graphics library
* Version: 3.3
* Copyright (C) 1995-2000 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* This file allows the GLU code to be compiled either with the Mesa
* headers or with the real OpenGL headers.
*/
#ifndef GLUP_H
#define GLUP_H
#include <GL/gl.h>
#include <GL/glu.h>
#include <string.h>
#if defined(_WIN32) && !defined(__WIN32__)
# define __WIN32__
#endif
#if !defined(OPENSTEP) && (defined(__WIN32__) || defined(__CYGWIN__))
# pragma warning( disable : 4068 ) /* unknown pragma */
# pragma warning( disable : 4710 ) /* function 'foo' not inlined */
# pragma warning( disable : 4711 ) /* function 'foo' selected for automatic inline expansion */
# pragma warning( disable : 4127 ) /* conditional expression is constant */
# if defined(MESA_MINWARN)
# pragma warning( disable : 4244 ) /* '=' : conversion from 'const double ' to 'float ', possible loss of data */
# pragma warning( disable : 4018 ) /* '<' : signed/unsigned mismatch */
# pragma warning( disable : 4305 ) /* '=' : truncation from 'const double ' to 'float ' */
# pragma warning( disable : 4550 ) /* 'function' undefined; assuming extern returning int */
# pragma warning( disable : 4761 ) /* integral size mismatch in argument; conversion supplied */
# endif
# if defined(_MSC_VER) && defined(BUILD_GL32) /* tag specify we're building mesa as a DLL */
# define GLAPI __declspec(dllexport)
# define WGLAPI __declspec(dllexport)
# elif defined(_MSC_VER) && defined(_DLL) /* tag specifying we're building for DLL runtime support */
# define GLAPI __declspec(dllimport)
# define WGLAPI __declspec(dllimport)
# else /* for use with static link lib build of Win32 edition only */
# define GLAPI extern
# define WGLAPI __declspec(dllimport)
# endif /* _STATIC_MESA support */
# define GLAPIENTRY __stdcall
# define GLAPIENTRYP __stdcall *
# define GLCALLBACK __stdcall
# define GLCALLBACKP __stdcall *
# if defined(__CYGWIN__)
# define GLCALLBACKPCAST *
# else
# define GLCALLBACKPCAST __stdcall *
# endif
# define GLWINAPI __stdcall
# define GLWINAPIV __cdecl
#else
/* non-Windows compilation */
# define GLAPI extern
# define GLAPIENTRY
# define GLAPIENTRYP *
# define GLCALLBACK
# define GLCALLBACKP *
# define GLCALLBACKPCAST *
# define GLWINAPI
# define GLWINAPIV
#endif /* WIN32 / CYGWIN bracket */
/* compatability guard so we don't need to change client code */
#if defined(_WIN32) && !defined(_WINDEF_) && !defined(_GNU_H_WINDOWS32_BASE) && !defined(OPENSTEP)
# define CALLBACK GLCALLBACK
typedef int (GLAPIENTRY *PROC)();
typedef void *HGLRC;
typedef void *HDC;
typedef unsigned long COLORREF;
#endif
#if defined(_WIN32) && !defined(_WINGDI_) && !defined(_GNU_H_WINDOWS32_DEFINES) && !defined(OPENSTEP)
# define WGL_FONT_LINES 0
# define WGL_FONT_POLYGONS 1
#ifndef _GNU_H_WINDOWS32_FUNCTIONS
# ifdef UNICODE
# define wglUseFontBitmaps wglUseFontBitmapsW
# define wglUseFontOutlines wglUseFontOutlinesW
# else
# define wglUseFontBitmaps wglUseFontBitmapsA
# define wglUseFontOutlines wglUseFontOutlinesA
# endif /* !UNICODE */
#endif /* _GNU_H_WINDOWS32_FUNCTIONS */
typedef struct tagLAYERPLANEDESCRIPTOR LAYERPLANEDESCRIPTOR, *PLAYERPLANEDESCRIPTOR, *LPLAYERPLANEDESCRIPTOR;
typedef struct _GLYPHMETRICSFLOAT GLYPHMETRICSFLOAT, *PGLYPHMETRICSFLOAT, *LPGLYPHMETRICSFLOAT;
typedef struct tagPIXELFORMATDESCRIPTOR PIXELFORMATDESCRIPTOR, *PPIXELFORMATDESCRIPTOR, *LPPIXELFORMATDESCRIPTOR;
#include <gl/mesa_wgl.h>
#endif
#ifndef GLU_TESS_ERROR9
/* If we're using the real OpenGL header files... */
# define GLU_TESS_ERROR9 100159
#endif
#define GLU_NO_ERROR GL_NO_ERROR
/* for Sun: */
#ifdef SUNOS4
#define MEMCPY( DST, SRC, BYTES) \
memcpy( (char *) (DST), (char *) (SRC), (int) (BYTES) )
#else
#define MEMCPY( DST, SRC, BYTES) \
memcpy( (void *) (DST), (void *) (SRC), (size_t) (BYTES) )
#endif
#ifndef NULL
# define NULL 0
#endif
#endif

764
src/glu/mini/mipmap.c Normal file
View File

@@ -0,0 +1,764 @@
/* $Id: mipmap.c,v 1.1.2.1 2003/03/21 13:02:12 keithw Exp $ */
/*
* Mesa 3-D graphics library
* Version: 3.4
* Copyright (C) 1995-2000 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifdef PC_HEADER
#include "all.h"
#else
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "gluP.h"
#endif
/*
* Compute ceiling of integer quotient of A divided by B:
*/
#define CEILING( A, B ) ( (A) % (B) == 0 ? (A)/(B) : (A)/(B)+1 )
#ifdef EPSILON
#undef EPSILON
#endif
#define EPSILON 0.001
/* To work around optimizer bug in MSVC4.1 */
#if defined(__WIN32__) && !defined(OPENSTEP)
void
dummy(GLuint j, GLuint k)
{
}
#else
#define dummy(J, K)
#endif
GLint GLAPIENTRY
gluScaleImage(GLenum format,
GLsizei widthin, GLsizei heightin,
GLenum typein, const void *datain,
GLsizei widthout, GLsizei heightout,
GLenum typeout, void *dataout)
{
GLint components, i, j, k;
GLfloat *tempin, *tempout, f;
GLfloat sx, sy;
GLint unpackrowlength, unpackalignment, unpackskiprows, unpackskippixels;
GLint packrowlength, packalignment, packskiprows, packskippixels;
GLint sizein, sizeout;
GLint rowstride, rowlen;
/* Determine number of components per pixel */
switch (format) {
case GL_COLOR_INDEX:
case GL_STENCIL_INDEX:
case GL_DEPTH_COMPONENT:
case GL_RED:
case GL_GREEN:
case GL_BLUE:
case GL_ALPHA:
case GL_LUMINANCE:
components = 1;
break;
case GL_LUMINANCE_ALPHA:
components = 2;
break;
case GL_RGB:
case GL_BGR:
components = 3;
break;
case GL_RGBA:
case GL_BGRA:
#ifdef GL_EXT_abgr
case GL_ABGR_EXT:
#endif
components = 4;
break;
default:
return GLU_INVALID_ENUM;
}
/* Determine bytes per input datum */
switch (typein) {
case GL_UNSIGNED_BYTE:
sizein = sizeof(GLubyte);
break;
case GL_BYTE:
sizein = sizeof(GLbyte);
break;
case GL_UNSIGNED_SHORT:
sizein = sizeof(GLushort);
break;
case GL_SHORT:
sizein = sizeof(GLshort);
break;
case GL_UNSIGNED_INT:
sizein = sizeof(GLuint);
break;
case GL_INT:
sizein = sizeof(GLint);
break;
case GL_FLOAT:
sizein = sizeof(GLfloat);
break;
case GL_BITMAP:
/* not implemented yet */
default:
return GL_INVALID_ENUM;
}
/* Determine bytes per output datum */
switch (typeout) {
case GL_UNSIGNED_BYTE:
sizeout = sizeof(GLubyte);
break;
case GL_BYTE:
sizeout = sizeof(GLbyte);
break;
case GL_UNSIGNED_SHORT:
sizeout = sizeof(GLushort);
break;
case GL_SHORT:
sizeout = sizeof(GLshort);
break;
case GL_UNSIGNED_INT:
sizeout = sizeof(GLuint);
break;
case GL_INT:
sizeout = sizeof(GLint);
break;
case GL_FLOAT:
sizeout = sizeof(GLfloat);
break;
case GL_BITMAP:
/* not implemented yet */
default:
return GL_INVALID_ENUM;
}
/* Get glPixelStore state */
glGetFloatv(GL_UNPACK_ROW_LENGTH, &f); unpackrowlength = (int)f;
glGetFloatv(GL_UNPACK_ALIGNMENT, &f); unpackalignment = (int)f;
glGetFloatv(GL_UNPACK_SKIP_ROWS, &f); unpackskiprows = (int)f;
glGetFloatv(GL_UNPACK_SKIP_PIXELS, &f); unpackskippixels = (int)f;
glGetFloatv(GL_PACK_ROW_LENGTH, &f); packrowlength = (int)f;
glGetFloatv(GL_PACK_ALIGNMENT, &f); packalignment = (int)f;
glGetFloatv(GL_PACK_SKIP_ROWS, &f); packskiprows = (int)f;
glGetFloatv(GL_PACK_SKIP_PIXELS, &f); packskippixels = (int)f;
/* Allocate storage for intermediate images */
tempin = (GLfloat *) malloc(widthin * heightin
* components * sizeof(GLfloat));
if (!tempin) {
return GLU_OUT_OF_MEMORY;
}
tempout = (GLfloat *) malloc(widthout * heightout
* components * sizeof(GLfloat));
if (!tempout) {
free(tempin);
return GLU_OUT_OF_MEMORY;
}
/*
* Unpack the pixel data and convert to floating point
*/
if (unpackrowlength > 0) {
rowlen = unpackrowlength;
}
else {
rowlen = widthin;
}
if (sizein >= unpackalignment) {
rowstride = components * rowlen;
}
else {
rowstride = unpackalignment / sizein
* CEILING(components * rowlen * sizein, unpackalignment);
}
switch (typein) {
case GL_UNSIGNED_BYTE:
k = 0;
for (i = 0; i < heightin; i++) {
GLubyte *ubptr = (GLubyte *) datain
+ i * rowstride
+ unpackskiprows * rowstride + unpackskippixels * components;
for (j = 0; j < widthin * components; j++) {
dummy(j, k);
tempin[k++] = (GLfloat) * ubptr++;
}
}
break;
case GL_BYTE:
k = 0;
for (i = 0; i < heightin; i++) {
GLbyte *bptr = (GLbyte *) datain
+ i * rowstride
+ unpackskiprows * rowstride + unpackskippixels * components;
for (j = 0; j < widthin * components; j++) {
dummy(j, k);
tempin[k++] = (GLfloat) * bptr++;
}
}
break;
case GL_UNSIGNED_SHORT:
k = 0;
for (i = 0; i < heightin; i++) {
GLushort *usptr = (GLushort *) datain
+ i * rowstride
+ unpackskiprows * rowstride + unpackskippixels * components;
for (j = 0; j < widthin * components; j++) {
dummy(j, k);
tempin[k++] = (GLfloat) * usptr++;
}
}
break;
case GL_SHORT:
k = 0;
for (i = 0; i < heightin; i++) {
GLshort *sptr = (GLshort *) datain
+ i * rowstride
+ unpackskiprows * rowstride + unpackskippixels * components;
for (j = 0; j < widthin * components; j++) {
dummy(j, k);
tempin[k++] = (GLfloat) * sptr++;
}
}
break;
case GL_UNSIGNED_INT:
k = 0;
for (i = 0; i < heightin; i++) {
GLuint *uiptr = (GLuint *) datain
+ i * rowstride
+ unpackskiprows * rowstride + unpackskippixels * components;
for (j = 0; j < widthin * components; j++) {
dummy(j, k);
tempin[k++] = (GLfloat) * uiptr++;
}
}
break;
case GL_INT:
k = 0;
for (i = 0; i < heightin; i++) {
GLint *iptr = (GLint *) datain
+ i * rowstride
+ unpackskiprows * rowstride + unpackskippixels * components;
for (j = 0; j < widthin * components; j++) {
dummy(j, k);
tempin[k++] = (GLfloat) * iptr++;
}
}
break;
case GL_FLOAT:
k = 0;
for (i = 0; i < heightin; i++) {
GLfloat *fptr = (GLfloat *) datain
+ i * rowstride
+ unpackskiprows * rowstride + unpackskippixels * components;
for (j = 0; j < widthin * components; j++) {
dummy(j, k);
tempin[k++] = *fptr++;
}
}
break;
default:
return GLU_INVALID_ENUM;
}
/*
* Scale the image!
*/
if (widthout > 1)
sx = (GLfloat) (widthin - 1) / (GLfloat) (widthout - 1);
else
sx = (GLfloat) (widthin - 1);
if (heightout > 1)
sy = (GLfloat) (heightin - 1) / (GLfloat) (heightout - 1);
else
sy = (GLfloat) (heightin - 1);
/*#define POINT_SAMPLE*/
#ifdef POINT_SAMPLE
for (i = 0; i < heightout; i++) {
GLint ii = i * sy;
for (j = 0; j < widthout; j++) {
GLint jj = j * sx;
GLfloat *src = tempin + (ii * widthin + jj) * components;
GLfloat *dst = tempout + (i * widthout + j) * components;
for (k = 0; k < components; k++) {
*dst++ = *src++;
}
}
}
#else
if (sx < 1.0 && sy < 1.0) {
/* magnify both width and height: use weighted sample of 4 pixels */
GLint i0, i1, j0, j1;
GLfloat alpha, beta;
GLfloat *src00, *src01, *src10, *src11;
GLfloat s1, s2;
GLfloat *dst;
for (i = 0; i < heightout; i++) {
i0 = i * sy;
i1 = i0 + 1;
if (i1 >= heightin)
i1 = heightin - 1;
/* i1 = (i+1) * sy - EPSILON;*/
alpha = i * sy - i0;
for (j = 0; j < widthout; j++) {
j0 = j * sx;
j1 = j0 + 1;
if (j1 >= widthin)
j1 = widthin - 1;
/* j1 = (j+1) * sx - EPSILON; */
beta = j * sx - j0;
/* compute weighted average of pixels in rect (i0,j0)-(i1,j1) */
src00 = tempin + (i0 * widthin + j0) * components;
src01 = tempin + (i0 * widthin + j1) * components;
src10 = tempin + (i1 * widthin + j0) * components;
src11 = tempin + (i1 * widthin + j1) * components;
dst = tempout + (i * widthout + j) * components;
for (k = 0; k < components; k++) {
s1 = *src00++ * (1.0 - beta) + *src01++ * beta;
s2 = *src10++ * (1.0 - beta) + *src11++ * beta;
*dst++ = s1 * (1.0 - alpha) + s2 * alpha;
}
}
}
}
else {
/* shrink width and/or height: use an unweighted box filter */
GLint i0, i1;
GLint j0, j1;
GLint ii, jj;
GLfloat sum, *dst;
for (i = 0; i < heightout; i++) {
i0 = i * sy;
i1 = i0 + 1;
if (i1 >= heightin)
i1 = heightin - 1;
/* i1 = (i+1) * sy - EPSILON; */
for (j = 0; j < widthout; j++) {
j0 = j * sx;
j1 = j0 + 1;
if (j1 >= widthin)
j1 = widthin - 1;
/* j1 = (j+1) * sx - EPSILON; */
dst = tempout + (i * widthout + j) * components;
/* compute average of pixels in the rectangle (i0,j0)-(i1,j1) */
for (k = 0; k < components; k++) {
sum = 0.0;
for (ii = i0; ii <= i1; ii++) {
for (jj = j0; jj <= j1; jj++) {
sum += *(tempin + (ii * widthin + jj) * components + k);
}
}
sum /= (j1 - j0 + 1) * (i1 - i0 + 1);
*dst++ = sum;
}
}
}
}
#endif
/*
* Return output image
*/
if (packrowlength > 0) {
rowlen = packrowlength;
}
else {
rowlen = widthout;
}
if (sizeout >= packalignment) {
rowstride = components * rowlen;
}
else {
rowstride = packalignment / sizeout
* CEILING(components * rowlen * sizeout, packalignment);
}
switch (typeout) {
case GL_UNSIGNED_BYTE:
k = 0;
for (i = 0; i < heightout; i++) {
GLubyte *ubptr = (GLubyte *) dataout
+ i * rowstride
+ packskiprows * rowstride + packskippixels * components;
for (j = 0; j < widthout * components; j++) {
dummy(j, k + i);
*ubptr++ = (GLubyte) tempout[k++];
}
}
break;
case GL_BYTE:
k = 0;
for (i = 0; i < heightout; i++) {
GLbyte *bptr = (GLbyte *) dataout
+ i * rowstride
+ packskiprows * rowstride + packskippixels * components;
for (j = 0; j < widthout * components; j++) {
dummy(j, k + i);
*bptr++ = (GLbyte) tempout[k++];
}
}
break;
case GL_UNSIGNED_SHORT:
k = 0;
for (i = 0; i < heightout; i++) {
GLushort *usptr = (GLushort *) dataout
+ i * rowstride
+ packskiprows * rowstride + packskippixels * components;
for (j = 0; j < widthout * components; j++) {
dummy(j, k + i);
*usptr++ = (GLushort) tempout[k++];
}
}
break;
case GL_SHORT:
k = 0;
for (i = 0; i < heightout; i++) {
GLshort *sptr = (GLshort *) dataout
+ i * rowstride
+ packskiprows * rowstride + packskippixels * components;
for (j = 0; j < widthout * components; j++) {
dummy(j, k + i);
*sptr++ = (GLshort) tempout[k++];
}
}
break;
case GL_UNSIGNED_INT:
k = 0;
for (i = 0; i < heightout; i++) {
GLuint *uiptr = (GLuint *) dataout
+ i * rowstride
+ packskiprows * rowstride + packskippixels * components;
for (j = 0; j < widthout * components; j++) {
dummy(j, k + i);
*uiptr++ = (GLuint) tempout[k++];
}
}
break;
case GL_INT:
k = 0;
for (i = 0; i < heightout; i++) {
GLint *iptr = (GLint *) dataout
+ i * rowstride
+ packskiprows * rowstride + packskippixels * components;
for (j = 0; j < widthout * components; j++) {
dummy(j, k + i);
*iptr++ = (GLint) tempout[k++];
}
}
break;
case GL_FLOAT:
k = 0;
for (i = 0; i < heightout; i++) {
GLfloat *fptr = (GLfloat *) dataout
+ i * rowstride
+ packskiprows * rowstride + packskippixels * components;
for (j = 0; j < widthout * components; j++) {
dummy(j, k + i);
*fptr++ = tempout[k++];
}
}
break;
default:
return GLU_INVALID_ENUM;
}
/* free temporary image storage */
free(tempin);
free(tempout);
return 0;
}
/*
* Return the largest k such that 2^k <= n.
*/
static GLint
ilog2(GLint n)
{
GLint k;
if (n <= 0)
return 0;
for (k = 0; n >>= 1; k++);
return k;
}
/*
* Find the value nearest to n which is also a power of two.
*/
static GLint
round2(GLint n)
{
GLint m;
for (m = 1; m < n; m *= 2);
/* m>=n */
if (m - n <= n - m / 2) {
return m;
}
else {
return m / 2;
}
}
/*
* Given an pixel format and datatype, return the number of bytes to
* store one pixel.
*/
static GLint
bytes_per_pixel(GLenum format, GLenum type)
{
GLint n, m;
switch (format) {
case GL_COLOR_INDEX:
case GL_STENCIL_INDEX:
case GL_DEPTH_COMPONENT:
case GL_RED:
case GL_GREEN:
case GL_BLUE:
case GL_ALPHA:
case GL_LUMINANCE:
n = 1;
break;
case GL_LUMINANCE_ALPHA:
n = 2;
break;
case GL_RGB:
case GL_BGR:
n = 3;
break;
case GL_RGBA:
case GL_BGRA:
#ifdef GL_EXT_abgr
case GL_ABGR_EXT:
#endif
n = 4;
break;
default:
n = 0;
}
switch (type) {
case GL_UNSIGNED_BYTE:
m = sizeof(GLubyte);
break;
case GL_BYTE:
m = sizeof(GLbyte);
break;
case GL_BITMAP:
m = 1;
break;
case GL_UNSIGNED_SHORT:
m = sizeof(GLushort);
break;
case GL_SHORT:
m = sizeof(GLshort);
break;
case GL_UNSIGNED_INT:
m = sizeof(GLuint);
break;
case GL_INT:
m = sizeof(GLint);
break;
case GL_FLOAT:
m = sizeof(GLfloat);
break;
default:
m = 0;
}
return n * m;
}
/*
* WARNING: This function isn't finished and has never been tested!!!!
*/
GLint GLAPIENTRY
gluBuild1DMipmaps(GLenum target, GLint components,
GLsizei width, GLenum format, GLenum type, const void *data)
{
return 0;
}
GLint GLAPIENTRY
gluBuild2DMipmaps(GLenum target, GLint components,
GLsizei width, GLsizei height, GLenum format,
GLenum type, const void *data)
{
GLint w, h;
GLint maxsize;
void *image, *newimage;
GLint neww, newh, level, bpp;
int error;
GLboolean done;
GLint retval = 0;
GLint unpackrowlength, unpackalignment, unpackskiprows, unpackskippixels;
GLint packrowlength, packalignment, packskiprows, packskippixels;
GLfloat f;
if (width < 1 || height < 1)
return GLU_INVALID_VALUE;
glGetFloatv(GL_MAX_TEXTURE_SIZE, &f); maxsize = (int)f;
w = round2(width);
if (w > maxsize) {
w = maxsize;
}
h = round2(height);
if (h > maxsize) {
h = maxsize;
}
bpp = bytes_per_pixel(format, type);
if (bpp == 0) {
/* probably a bad format or type enum */
return GLU_INVALID_ENUM;
}
/* Get current glPixelStore values */
glGetFloatv(GL_UNPACK_ROW_LENGTH, &f); unpackrowlength = (int)f;
glGetFloatv(GL_UNPACK_ALIGNMENT, &f); unpackalignment = (int)f;
glGetFloatv(GL_UNPACK_SKIP_ROWS, &f); unpackskiprows = (int)f;
glGetFloatv(GL_UNPACK_SKIP_PIXELS, &f); unpackskippixels = (int)f;
glGetFloatv(GL_PACK_ROW_LENGTH, &f); packrowlength = (int)f;
glGetFloatv(GL_PACK_ALIGNMENT, &f); packalignment = (int)f;
glGetFloatv(GL_PACK_SKIP_ROWS, &f); packskiprows = (int)f;
glGetFloatv(GL_PACK_SKIP_PIXELS, &f); packskippixels = (int)f;
/* set pixel packing */
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glPixelStorei(GL_PACK_SKIP_ROWS, 0);
glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
done = GL_FALSE;
if (w != width || h != height) {
/* must rescale image to get "top" mipmap texture image */
image = malloc((w + 4) * h * bpp);
if (!image) {
return GLU_OUT_OF_MEMORY;
}
error = gluScaleImage(format, width, height, type, data,
w, h, type, image);
if (error) {
retval = error;
done = GL_TRUE;
}
}
else {
image = (void *) data;
}
level = 0;
while (!done) {
if (image != data) {
/* set pixel unpacking */
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
}
glTexImage2D(target, level, components, w, h, 0, format, type, image);
if (w == 1 && h == 1)
break;
neww = (w < 2) ? 1 : w / 2;
newh = (h < 2) ? 1 : h / 2;
newimage = malloc((neww + 4) * newh * bpp);
if (!newimage) {
return GLU_OUT_OF_MEMORY;
}
error = gluScaleImage(format, w, h, type, image,
neww, newh, type, newimage);
if (error) {
retval = error;
done = GL_TRUE;
}
if (image != data) {
free(image);
}
image = newimage;
w = neww;
h = newh;
level++;
}
if (image != data) {
free(image);
}
/* Restore original glPixelStore state */
glPixelStorei(GL_UNPACK_ROW_LENGTH, unpackrowlength);
glPixelStorei(GL_UNPACK_ALIGNMENT, unpackalignment);
glPixelStorei(GL_UNPACK_SKIP_ROWS, unpackskiprows);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, unpackskippixels);
glPixelStorei(GL_PACK_ROW_LENGTH, packrowlength);
glPixelStorei(GL_PACK_ALIGNMENT, packalignment);
glPixelStorei(GL_PACK_SKIP_ROWS, packskiprows);
glPixelStorei(GL_PACK_SKIP_PIXELS, packskippixels);
return retval;
}

158
src/glu/mini/nurbs.c Normal file
View File

@@ -0,0 +1,158 @@
/* $Id: nurbs.c,v 1.1.2.1 2003/03/21 13:02:13 keithw Exp $ */
/*
* Mesa 3-D graphics library
* Version: 3.3
* Copyright (C) 1995-2000 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* NURBS implementation written by Bogdan Sikorski (bogdan@cira.it)
* See README2 for more info.
*/
#ifdef PC_HEADER
#include "all.h"
#else
#include <stdio.h>
#include <stdlib.h>
#include "gluP.h"
#include "nurbs.h"
#endif
void
call_user_error(GLUnurbsObj * nobj, GLenum error)
{
nobj->error = error;
if (nobj->error_callback != NULL) {
(*(nobj->error_callback)) (error);
}
else {
printf("NURBS error %d %s\n", error, (char *) gluErrorString(error));
}
}
GLUnurbsObj *GLAPIENTRY
gluNewNurbsRenderer(void)
{
GLUnurbsObj *n;
GLfloat tmp_viewport[4];
GLint i, j;
n = (GLUnurbsObj *) malloc(sizeof(GLUnurbsObj));
return n;
}
void GLAPIENTRY
gluDeleteNurbsRenderer(GLUnurbsObj * nobj)
{
if (nobj) {
free(nobj);
}
}
void GLAPIENTRY
gluLoadSamplingMatrices(GLUnurbsObj * nobj,
const GLfloat modelMatrix[16],
const GLfloat projMatrix[16], const GLint viewport[4])
{
}
void GLAPIENTRY
gluNurbsProperty(GLUnurbsObj * nobj, GLenum property, GLfloat value)
{
}
void GLAPIENTRY
gluGetNurbsProperty(GLUnurbsObj * nobj, GLenum property, GLfloat * value)
{
}
void GLAPIENTRY
gluBeginCurve(GLUnurbsObj * nobj)
{
}
void GLAPIENTRY
gluEndCurve(GLUnurbsObj * nobj)
{
}
void GLAPIENTRY
gluNurbsCurve(GLUnurbsObj * nobj, GLint nknots, GLfloat * knot,
GLint stride, GLfloat * ctlarray, GLint order, GLenum type)
{
}
void GLAPIENTRY
gluBeginSurface(GLUnurbsObj * nobj)
{
}
void GLAPIENTRY
gluEndSurface(GLUnurbsObj * nobj)
{
}
void GLAPIENTRY
gluNurbsSurface(GLUnurbsObj * nobj,
GLint sknot_count, GLfloat * sknot,
GLint tknot_count, GLfloat * tknot,
GLint s_stride, GLint t_stride,
GLfloat * ctrlarray, GLint sorder, GLint torder, GLenum type)
{
}
void GLAPIENTRY
gluNurbsCallback(GLUnurbsObj * nobj, GLenum which, void (GLCALLBACK * fn) ())
{
}
void GLAPIENTRY
gluBeginTrim(GLUnurbsObj * nobj)
{
}
void GLAPIENTRY
gluPwlCurve(GLUnurbsObj * nobj, GLint count, GLfloat * array, GLint stride,
GLenum type)
{
}
void GLAPIENTRY
gluEndTrim(GLUnurbsObj * nobj)
{
}

253
src/glu/mini/nurbs.h Normal file
View File

@@ -0,0 +1,253 @@
/* $Id: nurbs.h,v 1.1.2.1 2003/03/21 13:02:14 keithw Exp $ */
/*
* Mesa 3-D graphics library
* Version: 3.3
* Copyright (C) 1995-2000 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* NURBS implementation written by Bogdan Sikorski (bogdan@cira.it)
* See README2 for more info.
*/
#ifndef NURBS_H
#define NURBS_H
#define EPSILON 1e-06 /* epsilon for double precision compares */
typedef enum
{
GLU_NURBS_CURVE, GLU_NURBS_SURFACE, GLU_NURBS_TRIM, GLU_NURBS_NO_TRIM,
GLU_NURBS_TRIM_DONE, GLU_NURBS_NONE
}
GLU_nurbs_enum;
typedef enum
{
GLU_TRIM_NURBS, GLU_TRIM_PWL
}
GLU_trim_enum;
typedef struct
{
GLint sknot_count;
GLfloat *sknot;
GLint tknot_count;
GLfloat *tknot;
GLint s_stride;
GLint t_stride;
GLfloat *ctrlarray;
GLint sorder;
GLint torder;
GLint dim;
GLenum type;
}
surface_attribs;
typedef struct
{
surface_attribs geom;
surface_attribs color;
surface_attribs texture;
surface_attribs normal;
}
nurbs_surface;
typedef struct
{
GLint knot_count;
GLfloat *knot;
GLint stride;
GLfloat *ctrlarray;
GLint order;
GLint dim;
GLenum type;
}
curve_attribs;
typedef struct
{
GLint pt_count;
GLfloat *ctrlarray;
GLint stride;
GLint dim;
GLenum type;
}
pwl_curve_attribs;
typedef struct
{
curve_attribs geom;
curve_attribs color;
curve_attribs texture;
curve_attribs normal;
}
nurbs_curve;
typedef struct trim_list_str
{
GLU_trim_enum trim_type;
union
{
pwl_curve_attribs pwl_curve;
curve_attribs nurbs_curve;
}
curve;
struct trim_list_str *next;
}
trim_list;
typedef struct seg_trim_str
{
GLfloat *points;
GLint pt_cnt, seg_array_len;
struct seg_trim_str *next;
}
trim_segments;
typedef struct nurbs_trim_str
{
trim_list *trim_loop;
trim_segments *segments;
struct nurbs_trim_str *next;
}
nurbs_trim;
typedef struct
{
GLfloat model[16], proj[16], viewport[4];
}
culling_and_sampling_str;
struct GLUnurbs
{
GLboolean culling;
GLenum error;
void (GLCALLBACK * error_callback) (GLenum err);
GLenum display_mode;
GLU_nurbs_enum nurbs_type;
GLboolean auto_load_matrix;
culling_and_sampling_str sampling_matrices;
GLenum sampling_method;
GLfloat sampling_tolerance;
GLfloat parametric_tolerance;
GLint u_step, v_step;
nurbs_surface surface;
nurbs_curve curve;
nurbs_trim *trim;
};
typedef struct
{
GLfloat *knot;
GLint nknots;
GLfloat *unified_knot;
GLint unified_nknots;
GLint order;
GLint t_min, t_max;
GLint delta_nknots;
GLboolean open_at_begin, open_at_end;
GLfloat *new_knot;
GLfloat *alpha;
}
knot_str_type;
typedef struct
{
GLfloat *geom_ctrl;
GLint geom_s_stride, geom_t_stride;
GLfloat **geom_offsets;
GLint geom_s_pt_cnt, geom_t_pt_cnt;
GLfloat *color_ctrl;
GLint color_s_stride, color_t_stride;
GLfloat **color_offsets;
GLint color_s_pt_cnt, color_t_pt_cnt;
GLfloat *normal_ctrl;
GLint normal_s_stride, normal_t_stride;
GLfloat **normal_offsets;
GLint normal_s_pt_cnt, normal_t_pt_cnt;
GLfloat *texture_ctrl;
GLint texture_s_stride, texture_t_stride;
GLfloat **texture_offsets;
GLint texture_s_pt_cnt, texture_t_pt_cnt;
GLint s_bezier_cnt, t_bezier_cnt;
}
new_ctrl_type;
extern void call_user_error(GLUnurbsObj * nobj, GLenum error);
extern GLenum test_knot(GLint nknots, GLfloat * knot, GLint order);
extern GLenum explode_knot(knot_str_type * the_knot);
extern GLenum calc_alphas(knot_str_type * the_knot);
extern GLenum calc_new_ctrl_pts(GLfloat * ctrl, GLint stride,
knot_str_type * the_knot, GLint dim,
GLfloat ** new_ctrl, GLint * ncontrol);
extern GLenum glu_do_sampling_crv(GLUnurbsObj * nobj, GLfloat * new_ctrl,
GLint n_ctrl, GLint order, GLint dim,
GLint ** factors);
extern GLenum glu_do_sampling_3D(GLUnurbsObj * nobj, new_ctrl_type * new_ctrl,
int **sfactors, GLint ** tfactors);
extern GLenum glu_do_sampling_uv(GLUnurbsObj * nobj, new_ctrl_type * new_ctrl,
int **sfactors, GLint ** tfactors);
extern GLenum glu_do_sampling_param_3D(GLUnurbsObj * nobj,
new_ctrl_type * new_ctrl,
int **sfactors, GLint ** tfactors);
extern GLboolean fine_culling_test_2D(GLUnurbsObj * nobj, GLfloat * ctrl,
GLint n_ctrl, GLint stride, GLint dim);
extern GLboolean fine_culling_test_3D(GLUnurbsObj * nobj, GLfloat * ctrl,
GLint s_n_ctrl, GLint t_n_ctrl,
GLint s_stride, GLint t_stride,
GLint dim);
extern void do_nurbs_curve(GLUnurbsObj * nobj);
extern void do_nurbs_surface(GLUnurbsObj * nobj);
extern GLenum patch_trimming(GLUnurbsObj * nobj, new_ctrl_type * new_ctrl,
GLint * sfactors, GLint * tfactors);
extern void collect_unified_knot(knot_str_type * dest, knot_str_type * src,
GLfloat maximal_min_knot,
GLfloat minimal_max_knot);
extern GLenum select_knot_working_range(GLUnurbsObj * nobj,
knot_str_type * geom_knot,
knot_str_type * color_knot,
knot_str_type * normal_knot,
knot_str_type * texture_knot);
extern void free_unified_knots(knot_str_type * geom_knot,
knot_str_type * color_knot,
knot_str_type * normal_knot,
knot_str_type * texture_knot);
#endif

133
src/glu/mini/nurbscrv.c Normal file
View File

@@ -0,0 +1,133 @@
/* $Id: nurbscrv.c,v 1.1.2.1 2003/03/21 13:02:16 keithw Exp $ */
/*
* Mesa 3-D graphics library
* Version: 3.3
* Copyright (C) 1995-2000 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* NURBS implementation written by Bogdan Sikorski (bogdan@cira.it)
* See README2 for more info.
*/
#ifdef PC_HEADER
#include "all.h"
#else
#include <math.h>
#include <stdlib.h>
#include "gluP.h"
#include "nurbs.h"
#endif
/* main NURBS curve procedure */
void
do_nurbs_curve(GLUnurbsObj * nobj)
{
GLint geom_order, color_order = 0, normal_order = 0, texture_order = 0;
GLenum geom_type;
GLint n_ctrl;
GLfloat *new_geom_ctrl, *new_color_ctrl, *new_normal_ctrl,
*new_texture_ctrl;
GLfloat *geom_ctrl = 0, *color_ctrl = 0, *normal_ctrl = 0, *texture_ctrl = 0;
GLint *factors;
GLint i, j;
GLint geom_dim, color_dim = 0, normal_dim = 0, texture_dim = 0;
/* test the user supplied data */
if (test_nurbs_curves(nobj) != GLU_NO_ERROR)
return;
if (convert_curves(nobj, &new_geom_ctrl, &n_ctrl, &new_color_ctrl,
&new_normal_ctrl, &new_texture_ctrl) != GLU_NO_ERROR)
return;
geom_order = nobj->curve.geom.order;
geom_type = nobj->curve.geom.type;
geom_dim = nobj->curve.geom.dim;
if (glu_do_sampling_crv(nobj, new_geom_ctrl, n_ctrl, geom_order, geom_dim,
&factors) != GLU_NO_ERROR) {
free(new_geom_ctrl);
if (new_color_ctrl)
free(new_color_ctrl);
if (new_normal_ctrl)
free(new_normal_ctrl);
if (new_texture_ctrl)
free(new_texture_ctrl);
return;
}
glEnable(geom_type);
if (new_color_ctrl) {
glEnable(nobj->curve.color.type);
color_dim = nobj->curve.color.dim;
color_ctrl = new_color_ctrl;
color_order = nobj->curve.color.order;
}
if (new_normal_ctrl) {
glEnable(nobj->curve.normal.type);
normal_dim = nobj->curve.normal.dim;
normal_ctrl = new_normal_ctrl;
normal_order = nobj->curve.normal.order;
}
if (new_texture_ctrl) {
glEnable(nobj->curve.texture.type);
texture_dim = nobj->curve.texture.dim;
texture_ctrl = new_texture_ctrl;
texture_order = nobj->curve.texture.order;
}
for (i = 0, j = 0, geom_ctrl = new_geom_ctrl;
i < n_ctrl; i += geom_order, j++, geom_ctrl += geom_order * geom_dim) {
if (fine_culling_test_2D
(nobj, geom_ctrl, geom_order, geom_dim, geom_dim)) {
color_ctrl += color_order * color_dim;
normal_ctrl += normal_order * normal_dim;
texture_ctrl += texture_order * texture_dim;
continue;
}
glMap1f(geom_type, 0.0, 1.0, geom_dim, geom_order, geom_ctrl);
if (new_color_ctrl) {
glMap1f(nobj->curve.color.type, 0.0, 1.0, color_dim,
color_order, color_ctrl);
color_ctrl += color_order * color_dim;
}
if (new_normal_ctrl) {
glMap1f(nobj->curve.normal.type, 0.0, 1.0, normal_dim,
normal_order, normal_ctrl);
normal_ctrl += normal_order * normal_dim;
}
if (new_texture_ctrl) {
glMap1f(nobj->curve.texture.type, 0.0, 1.0, texture_dim,
texture_order, texture_ctrl);
texture_ctrl += texture_order * texture_dim;
}
glMapGrid1f(factors[j], 0.0, 1.0);
glEvalMesh1(GL_LINE, 0, factors[j]);
}
free(new_geom_ctrl);
free(factors);
if (new_color_ctrl)
free(new_color_ctrl);
if (new_normal_ctrl)
free(new_normal_ctrl);
if (new_texture_ctrl)
free(new_texture_ctrl);
}

938
src/glu/mini/polytest.c Normal file
View File

@@ -0,0 +1,938 @@
/* $Id: polytest.c,v 1.1.2.1 2003/03/21 13:02:17 keithw Exp $ */
/*
* Mesa 3-D graphics library
* Version: 3.3
* Copyright (C) 1995-2000 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* This file is part of the polygon tesselation code contributed by
* Bogdan Sikorski
*/
#ifdef PC_HEADER
#include "all.h"
#else
#include <math.h>
#include <stdlib.h>
#include "gluP.h"
#include "tess.h"
#endif
static GLenum store_polygon_as_contour(GLUtriangulatorObj *);
static void free_current_polygon(tess_polygon *);
static void prepare_projection_info(GLUtriangulatorObj *);
static GLdouble twice_the_polygon_area(tess_vertex *, tess_vertex *);
static GLenum verify_edge_vertex_intersections(GLUtriangulatorObj *);
void tess_find_contour_hierarchies(GLUtriangulatorObj *);
static GLenum test_for_overlapping_contours(GLUtriangulatorObj *);
static GLenum contours_overlap(tess_contour *, tess_polygon *);
static GLenum is_contour_contained_in(tess_contour *, tess_contour *);
static void add_new_exterior(GLUtriangulatorObj *, tess_contour *);
static void add_new_interior(GLUtriangulatorObj *, tess_contour *,
tess_contour *);
static void add_interior_with_hierarchy_check(GLUtriangulatorObj *,
tess_contour *, tess_contour *);
static void reverse_hierarchy_and_add_exterior(GLUtriangulatorObj *,
tess_contour *,
tess_contour *);
static GLboolean point_in_polygon(tess_contour *, GLdouble, GLdouble);
static void shift_interior_to_exterior(GLUtriangulatorObj *, tess_contour *);
static void add_exterior_with_check(GLUtriangulatorObj *, tess_contour *,
tess_contour *);
static GLenum cut_out_hole(GLUtriangulatorObj *, tess_contour *,
tess_contour *);
static GLenum merge_hole_with_contour(GLUtriangulatorObj *,
tess_contour *, tess_contour *,
tess_vertex *, tess_vertex *);
static GLenum
find_normal(GLUtriangulatorObj * tobj)
{
tess_polygon *polygon = tobj->current_polygon;
tess_vertex *va, *vb, *vc;
GLdouble A, B, C;
GLdouble A0, A1, A2, B0, B1, B2;
va = polygon->vertices;
vb = va->next;
A0 = vb->location[0] - va->location[0];
A1 = vb->location[1] - va->location[1];
A2 = vb->location[2] - va->location[2];
for (vc = vb->next; vc != va; vc = vc->next) {
B0 = vc->location[0] - va->location[0];
B1 = vc->location[1] - va->location[1];
B2 = vc->location[2] - va->location[2];
A = A1 * B2 - A2 * B1;
B = A2 * B0 - A0 * B2;
C = A0 * B1 - A1 * B0;
if (fabs(A) > EPSILON || fabs(B) > EPSILON || fabs(C) > EPSILON) {
polygon->A = A;
polygon->B = B;
polygon->C = C;
polygon->D =
-A * va->location[0] - B * va->location[1] - C * va->location[2];
return GLU_NO_ERROR;
}
}
tess_call_user_error(tobj, GLU_TESS_ERROR7);
return GLU_ERROR;
}
void
tess_test_polygon(GLUtriangulatorObj * tobj)
{
tess_polygon *polygon = tobj->current_polygon;
/* any vertices defined? */
if (polygon->vertex_cnt < 3) {
free_current_polygon(polygon);
return;
}
/* wrap pointers */
polygon->last_vertex->next = polygon->vertices;
polygon->vertices->previous = polygon->last_vertex;
/* determine the normal */
if (find_normal(tobj) == GLU_ERROR)
return;
/* compare the normals of previously defined contours and this one */
/* first contour define ? */
if (tobj->contours == NULL) {
tobj->A = polygon->A;
tobj->B = polygon->B;
tobj->C = polygon->C;
tobj->D = polygon->D;
/* determine the best projection to use */
if (fabs(polygon->A) > fabs(polygon->B))
if (fabs(polygon->A) > fabs(polygon->C))
tobj->projection = OYZ;
else
tobj->projection = OXY;
else if (fabs(polygon->B) > fabs(polygon->C))
tobj->projection = OXZ;
else
tobj->projection = OXY;
}
else {
GLdouble a[3], b[3];
tess_vertex *vertex = polygon->vertices;
a[0] = tobj->A;
a[1] = tobj->B;
a[2] = tobj->C;
b[0] = polygon->A;
b[1] = polygon->B;
b[2] = polygon->C;
/* compare the normals */
if (fabs(a[1] * b[2] - a[2] * b[1]) > EPSILON ||
fabs(a[2] * b[0] - a[0] * b[2]) > EPSILON ||
fabs(a[0] * b[1] - a[1] * b[0]) > EPSILON) {
/* not coplanar */
tess_call_user_error(tobj, GLU_TESS_ERROR9);
return;
}
/* the normals are parallel - test for plane equation */
if (fabs(a[0] * vertex->location[0] + a[1] * vertex->location[1] +
a[2] * vertex->location[2] + tobj->D) > EPSILON) {
/* not the same plane */
tess_call_user_error(tobj, GLU_TESS_ERROR9);
return;
}
}
prepare_projection_info(tobj);
if (verify_edge_vertex_intersections(tobj) == GLU_ERROR)
return;
if (test_for_overlapping_contours(tobj) == GLU_ERROR)
return;
if (store_polygon_as_contour(tobj) == GLU_ERROR)
return;
}
static GLenum
test_for_overlapping_contours(GLUtriangulatorObj * tobj)
{
tess_contour *contour;
tess_polygon *polygon;
polygon = tobj->current_polygon;
for (contour = tobj->contours; contour != NULL; contour = contour->next)
if (contours_overlap(contour, polygon) != GLU_NO_ERROR) {
tess_call_user_error(tobj, GLU_TESS_ERROR5);
return GLU_ERROR;
}
return GLU_NO_ERROR;
}
static GLenum
store_polygon_as_contour(GLUtriangulatorObj * tobj)
{
tess_polygon *polygon = tobj->current_polygon;
tess_contour *contour = tobj->contours;
/* the first contour defined */
if (contour == NULL) {
if ((contour = (tess_contour *) malloc(sizeof(tess_contour))) == NULL) {
tess_call_user_error(tobj, GLU_OUT_OF_MEMORY);
free_current_polygon(polygon);
return GLU_ERROR;
}
tobj->contours = tobj->last_contour = contour;
contour->next = contour->previous = NULL;
}
else {
if ((contour = (tess_contour *) malloc(sizeof(tess_contour))) == NULL) {
tess_call_user_error(tobj, GLU_OUT_OF_MEMORY);
free_current_polygon(polygon);
return GLU_ERROR;
}
contour->previous = tobj->last_contour;
tobj->last_contour->next = contour;
tobj->last_contour = contour;
contour->next = NULL;
}
/* mark all vertices in new contour as not special */
/* and all are boundary edges */
{
tess_vertex *vertex;
GLuint vertex_cnt, i;
for (vertex = polygon->vertices, i = 0, vertex_cnt =
polygon->vertex_cnt; i < vertex_cnt; vertex = vertex->next, i++) {
vertex->shadow_vertex = NULL;
vertex->edge_flag = GL_TRUE;
}
}
contour->vertex_cnt = polygon->vertex_cnt;
contour->area = polygon->area;
contour->orientation = polygon->orientation;
contour->type = GLU_UNKNOWN;
contour->vertices = polygon->vertices;
contour->last_vertex = polygon->last_vertex;
polygon->vertices = polygon->last_vertex = NULL;
polygon->vertex_cnt = 0;
++(tobj->contour_cnt);
return GLU_NO_ERROR;
}
static void
free_current_polygon(tess_polygon * polygon)
{
tess_vertex *vertex, *vertex_tmp;
GLuint i;
/* free current_polygon structures */
for (vertex = polygon->vertices, i = 0; i < polygon->vertex_cnt; i++) {
vertex_tmp = vertex->next;
free(vertex);
vertex = vertex_tmp;
}
polygon->vertices = polygon->last_vertex = NULL;
polygon->vertex_cnt = 0;
}
static void
prepare_projection_info(GLUtriangulatorObj * tobj)
{
tess_polygon *polygon = tobj->current_polygon;
tess_vertex *vertex, *last_vertex_ptr;
GLdouble area;
last_vertex_ptr = polygon->last_vertex;
switch (tobj->projection) {
case OXY:
for (vertex = polygon->vertices; vertex != last_vertex_ptr;
vertex = vertex->next) {
vertex->x = vertex->location[0];
vertex->y = vertex->location[1];
}
last_vertex_ptr->x = last_vertex_ptr->location[0];
last_vertex_ptr->y = last_vertex_ptr->location[1];
break;
case OXZ:
for (vertex = polygon->vertices; vertex != last_vertex_ptr;
vertex = vertex->next) {
vertex->x = vertex->location[0];
vertex->y = vertex->location[2];
}
last_vertex_ptr->x = last_vertex_ptr->location[0];
last_vertex_ptr->y = last_vertex_ptr->location[2];
break;
case OYZ:
for (vertex = polygon->vertices; vertex != last_vertex_ptr;
vertex = vertex->next) {
vertex->x = vertex->location[1];
vertex->y = vertex->location[2];
}
last_vertex_ptr->x = last_vertex_ptr->location[1];
last_vertex_ptr->y = last_vertex_ptr->location[2];
break;
}
area = twice_the_polygon_area(polygon->vertices, polygon->last_vertex);
if (area >= 0.0) {
polygon->orientation = GLU_CCW;
polygon->area = area;
}
else {
polygon->orientation = GLU_CW;
polygon->area = -area;
}
}
static GLdouble
twice_the_polygon_area(tess_vertex * vertex, tess_vertex * last_vertex)
{
tess_vertex *next;
GLdouble area, x, y;
area = 0.0;
x = vertex->x;
y = vertex->y;
vertex = vertex->next;
for (; vertex != last_vertex; vertex = vertex->next) {
next = vertex->next;
area +=
(vertex->x - x) * (next->y - y) - (vertex->y - y) * (next->x - x);
}
return area;
}
/* test if edges ab and cd intersect */
/* if not return GLU_NO_ERROR, else if cross return GLU_TESS_ERROR8, */
/* else if adjacent return GLU_TESS_ERROR4 */
static GLenum
edge_edge_intersect(tess_vertex * a,
tess_vertex * b, tess_vertex * c, tess_vertex * d)
{
GLdouble denom, r, s;
GLdouble xba, ydc, yba, xdc, yac, xac;
xba = b->x - a->x;
yba = b->y - a->y;
xdc = d->x - c->x;
ydc = d->y - c->y;
xac = a->x - c->x;
yac = a->y - c->y;
denom = xba * ydc - yba * xdc;
r = yac * xdc - xac * ydc;
/* parallel? */
if (fabs(denom) < EPSILON) {
if (fabs(r) < EPSILON) {
/* colinear */
if (fabs(xba) < EPSILON) {
/* compare the Y coordinate */
if (yba > 0.0) {
if (
(fabs(a->y - c->y) < EPSILON
&& fabs(c->y - b->y) < EPSILON)
|| (fabs(a->y - d->y) < EPSILON
&& fabs(d->y - b->y) <
EPSILON)) return GLU_TESS_ERROR4;
}
else {
if (
(fabs(b->y - c->y) < EPSILON
&& fabs(c->y - a->y) < EPSILON)
|| (fabs(b->y - d->y) < EPSILON
&& fabs(d->y - a->y) <
EPSILON)) return GLU_TESS_ERROR4;
}
}
else {
/* compare the X coordinate */
if (xba > 0.0) {
if (
(fabs(a->x - c->x) < EPSILON
&& fabs(c->x - b->x) < EPSILON)
|| (fabs(a->x - d->x) < EPSILON
&& fabs(d->x - b->x) <
EPSILON)) return GLU_TESS_ERROR4;
}
else {
if (
(fabs(b->x - c->x) < EPSILON
&& fabs(c->x - a->x) < EPSILON)
|| (fabs(b->x - d->x) < EPSILON
&& fabs(d->x - a->x) <
EPSILON)) return GLU_TESS_ERROR4;
}
}
}
return GLU_NO_ERROR;
}
r /= denom;
s = (yac * xba - xac * yba) / denom;
/* test if one vertex lies on other edge */
if (((fabs(r) < EPSILON || (r < 1.0 + EPSILON && r > 1.0 - EPSILON)) &&
s > -EPSILON && s < 1.0 + EPSILON) ||
((fabs(s) < EPSILON || (s < 1.0 + EPSILON && s > 1.0 - EPSILON)) &&
r > -EPSILON && r < 1.0 + EPSILON)) {
return GLU_TESS_ERROR4;
}
/* test for crossing */
if (r > -EPSILON && r < 1.0 + EPSILON && s > -EPSILON && s < 1.0 + EPSILON) {
return GLU_TESS_ERROR8;
}
return GLU_NO_ERROR;
}
static GLenum
verify_edge_vertex_intersections(GLUtriangulatorObj * tobj)
{
tess_polygon *polygon = tobj->current_polygon;
tess_vertex *vertex1, *last_vertex, *vertex2;
GLenum test;
last_vertex = polygon->last_vertex;
vertex1 = last_vertex;
for (vertex2 = vertex1->next->next;
vertex2->next != last_vertex; vertex2 = vertex2->next) {
test = edge_edge_intersect(vertex1, vertex1->next, vertex2,
vertex2->next);
if (test != GLU_NO_ERROR) {
tess_call_user_error(tobj, test);
return GLU_ERROR;
}
}
for (vertex1 = polygon->vertices;
vertex1->next->next != last_vertex; vertex1 = vertex1->next) {
for (vertex2 = vertex1->next->next;
vertex2 != last_vertex; vertex2 = vertex2->next) {
test = edge_edge_intersect(vertex1, vertex1->next, vertex2,
vertex2->next);
if (test != GLU_NO_ERROR) {
tess_call_user_error(tobj, test);
return GLU_ERROR;
}
}
}
return GLU_NO_ERROR;
}
static int
#ifdef WIN32
__cdecl
#endif
area_compare(const void *a, const void *b)
{
GLdouble area1, area2;
area1 = (*((tess_contour **) a))->area;
area2 = (*((tess_contour **) b))->area;
if (area1 < area2)
return 1;
if (area1 > area2)
return -1;
return 0;
}
void
tess_find_contour_hierarchies(GLUtriangulatorObj * tobj)
{
tess_contour **contours; /* dinamic array of pointers */
tess_contour *tmp_contour_ptr = tobj->contours;
GLuint cnt, i;
GLenum result;
GLboolean hierarchy_changed;
/* any contours? */
if (tobj->contour_cnt < 2) {
tobj->contours->type = GLU_EXTERIOR;
return;
}
if ((contours = (tess_contour **)
malloc(sizeof(tess_contour *) * (tobj->contour_cnt))) == NULL) {
tess_call_user_error(tobj, GLU_OUT_OF_MEMORY);
return;
}
for (tmp_contour_ptr = tobj->contours, cnt = 0;
tmp_contour_ptr != NULL; tmp_contour_ptr = tmp_contour_ptr->next)
contours[cnt++] = tmp_contour_ptr;
/* now sort the contours in decreasing area size order */
qsort((void *) contours, (size_t) cnt, (size_t) sizeof(tess_contour *),
area_compare);
/* we leave just the first contour - remove others from list */
tobj->contours = contours[0];
tobj->contours->next = tobj->contours->previous = NULL;
tobj->last_contour = tobj->contours;
tobj->contour_cnt = 1;
/* first contour is the one with greatest area */
/* must be EXTERIOR */
tobj->contours->type = GLU_EXTERIOR;
tmp_contour_ptr = tobj->contours;
/* now we play! */
for (i = 1; i < cnt; i++) {
hierarchy_changed = GL_FALSE;
for (tmp_contour_ptr = tobj->contours;
tmp_contour_ptr != NULL; tmp_contour_ptr = tmp_contour_ptr->next) {
if (tmp_contour_ptr->type == GLU_EXTERIOR) {
/* check if contour completely contained in EXTERIOR */
result = is_contour_contained_in(tmp_contour_ptr, contours[i]);
switch (result) {
case GLU_INTERIOR:
/* now we have to check if contour is inside interiors */
/* or not */
/* any interiors? */
if (tmp_contour_ptr->next != NULL &&
tmp_contour_ptr->next->type == GLU_INTERIOR) {
/* for all interior, check if inside any of them */
/* if not inside any of interiors, its another */
/* interior */
/* or it may contain some interiors, then change */
/* the contained interiors to exterior ones */
add_interior_with_hierarchy_check(tobj,
tmp_contour_ptr,
contours[i]);
}
else {
/* not in interior, add as new interior contour */
add_new_interior(tobj, tmp_contour_ptr, contours[i]);
}
hierarchy_changed = GL_TRUE;
break;
case GLU_EXTERIOR:
/* ooops, the marked as EXTERIOR (contours[i]) is */
/* actually an interior of tmp_contour_ptr */
/* reverse the local hierarchy */
reverse_hierarchy_and_add_exterior(tobj, tmp_contour_ptr,
contours[i]);
hierarchy_changed = GL_TRUE;
break;
case GLU_NO_ERROR:
break;
default:
abort();
}
}
if (hierarchy_changed)
break; /* break from for loop */
}
if (hierarchy_changed == GL_FALSE) {
/* disjoint with all contours, add to contour list */
add_new_exterior(tobj, contours[i]);
}
}
free(contours);
}
/* returns GLU_INTERIOR if inner is completey enclosed within outer */
/* returns GLU_EXTERIOR if outer is completely enclosed within inner */
/* returns GLU_NO_ERROR if contours are disjoint */
static GLenum
is_contour_contained_in(tess_contour * outer, tess_contour * inner)
{
GLenum relation_flag;
/* set relation_flag to relation of containment of first inner vertex */
/* regarding outer contour */
if (point_in_polygon(outer, inner->vertices->x, inner->vertices->y))
relation_flag = GLU_INTERIOR;
else
relation_flag = GLU_EXTERIOR;
if (relation_flag == GLU_INTERIOR)
return GLU_INTERIOR;
if (point_in_polygon(inner, outer->vertices->x, outer->vertices->y))
return GLU_EXTERIOR;
return GLU_NO_ERROR;
}
static GLboolean
point_in_polygon(tess_contour * contour, GLdouble x, GLdouble y)
{
tess_vertex *v1, *v2;
GLuint i, vertex_cnt;
GLdouble xp1, yp1, xp2, yp2;
GLboolean tst;
tst = GL_FALSE;
v1 = contour->vertices;
v2 = contour->vertices->previous;
for (i = 0, vertex_cnt = contour->vertex_cnt; i < vertex_cnt; i++) {
xp1 = v1->x;
yp1 = v1->y;
xp2 = v2->x;
yp2 = v2->y;
if ((((yp1 <= y) && (y < yp2)) || ((yp2 <= y) && (y < yp1))) &&
(x < (xp2 - xp1) * (y - yp1) / (yp2 - yp1) + xp1))
tst = (tst == GL_FALSE ? GL_TRUE : GL_FALSE);
v2 = v1;
v1 = v1->next;
}
return tst;
}
static GLenum
contours_overlap(tess_contour * contour, tess_polygon * polygon)
{
tess_vertex *vertex1, *vertex2;
GLuint vertex1_cnt, vertex2_cnt, i, j;
GLenum test;
vertex1 = contour->vertices;
vertex2 = polygon->vertices;
vertex1_cnt = contour->vertex_cnt;
vertex2_cnt = polygon->vertex_cnt;
for (i = 0; i < vertex1_cnt; vertex1 = vertex1->next, i++) {
for (j = 0; j < vertex2_cnt; vertex2 = vertex2->next, j++)
if ((test = edge_edge_intersect(vertex1, vertex1->next, vertex2,
vertex2->next)) != GLU_NO_ERROR)
return test;
}
return GLU_NO_ERROR;
}
static void
add_new_exterior(GLUtriangulatorObj * tobj, tess_contour * contour)
{
contour->type = GLU_EXTERIOR;
contour->next = NULL;
contour->previous = tobj->last_contour;
tobj->last_contour->next = contour;
tobj->last_contour = contour;
}
static void
add_new_interior(GLUtriangulatorObj * tobj,
tess_contour * outer, tess_contour * contour)
{
contour->type = GLU_INTERIOR;
contour->next = outer->next;
contour->previous = outer;
if (outer->next != NULL)
outer->next->previous = contour;
outer->next = contour;
if (tobj->last_contour == outer)
tobj->last_contour = contour;
}
static void
add_interior_with_hierarchy_check(GLUtriangulatorObj * tobj,
tess_contour * outer,
tess_contour * contour)
{
tess_contour *ptr;
/* for all interiors of outer check if they are interior of contour */
/* if so, change that interior to exterior and move it of of the */
/* interior sequence */
if (outer->next != NULL && outer->next->type == GLU_INTERIOR) {
GLenum test;
for (ptr = outer->next; ptr != NULL && ptr->type == GLU_INTERIOR;
ptr = ptr->next) {
test = is_contour_contained_in(ptr, contour);
switch (test) {
case GLU_INTERIOR:
/* contour is contained in one of the interiors */
/* check if possibly contained in other exteriors */
/* move ptr to first EXTERIOR */
for (; ptr != NULL && ptr->type == GLU_INTERIOR; ptr = ptr->next);
if (ptr == NULL)
/* another exterior */
add_new_exterior(tobj, contour);
else
add_exterior_with_check(tobj, ptr, contour);
return;
case GLU_EXTERIOR:
/* one of the interiors is contained in the contour */
/* change it to EXTERIOR, and shift it away from the */
/* interior sequence */
shift_interior_to_exterior(tobj, ptr);
break;
case GLU_NO_ERROR:
/* disjoint */
break;
default:
abort();
}
}
}
/* add contour to the interior sequence */
add_new_interior(tobj, outer, contour);
}
static void
reverse_hierarchy_and_add_exterior(GLUtriangulatorObj * tobj,
tess_contour * outer,
tess_contour * contour)
{
tess_contour *ptr;
/* reverse INTERIORS to EXTERIORS */
/* any INTERIORS? */
if (outer->next != NULL && outer->next->type == GLU_INTERIOR)
for (ptr = outer->next; ptr != NULL && ptr->type == GLU_INTERIOR;
ptr = ptr->next) ptr->type = GLU_EXTERIOR;
/* the outer now becomes inner */
outer->type = GLU_INTERIOR;
/* contour is the EXTERIOR */
contour->next = outer;
if (tobj->contours == outer) {
/* first contour beeing reversed */
contour->previous = NULL;
tobj->contours = contour;
}
else {
outer->previous->next = contour;
contour->previous = outer->previous;
}
outer->previous = contour;
}
static void
shift_interior_to_exterior(GLUtriangulatorObj * tobj, tess_contour * contour)
{
contour->previous->next = contour->next;
if (contour->next != NULL)
contour->next->previous = contour->previous;
else
tobj->last_contour = contour->previous;
}
static void
add_exterior_with_check(GLUtriangulatorObj * tobj,
tess_contour * outer, tess_contour * contour)
{
GLenum test;
/* this contour might be interior to further exteriors - check */
/* if not, just add as a new exterior */
for (; outer != NULL && outer->type == GLU_EXTERIOR; outer = outer->next) {
test = is_contour_contained_in(outer, contour);
switch (test) {
case GLU_INTERIOR:
/* now we have to check if contour is inside interiors */
/* or not */
/* any interiors? */
if (outer->next != NULL && outer->next->type == GLU_INTERIOR) {
/* for all interior, check if inside any of them */
/* if not inside any of interiors, its another */
/* interior */
/* or it may contain some interiors, then change */
/* the contained interiors to exterior ones */
add_interior_with_hierarchy_check(tobj, outer, contour);
}
else {
/* not in interior, add as new interior contour */
add_new_interior(tobj, outer, contour);
}
return;
case GLU_NO_ERROR:
/* disjoint */
break;
default:
abort();
}
}
/* add contour to the exterior sequence */
add_new_exterior(tobj, contour);
}
void
tess_handle_holes(GLUtriangulatorObj * tobj)
{
tess_contour *contour, *hole;
GLenum exterior_orientation;
/* verify hole orientation */
for (contour = tobj->contours; contour != NULL;) {
exterior_orientation = contour->orientation;
for (contour = contour->next;
contour != NULL && contour->type == GLU_INTERIOR;
contour = contour->next) {
if (contour->orientation == exterior_orientation) {
tess_call_user_error(tobj, GLU_TESS_ERROR5);
return;
}
}
}
/* now cut-out holes */
for (contour = tobj->contours; contour != NULL;) {
hole = contour->next;
while (hole != NULL && hole->type == GLU_INTERIOR) {
if (cut_out_hole(tobj, contour, hole) == GLU_ERROR)
return;
hole = contour->next;
}
contour = contour->next;
}
}
static GLenum
cut_out_hole(GLUtriangulatorObj * tobj,
tess_contour * contour, tess_contour * hole)
{
tess_contour *tmp_hole;
tess_vertex *v1, *v2, *tmp_vertex;
GLuint vertex1_cnt, vertex2_cnt, tmp_vertex_cnt;
GLuint i, j, k;
GLenum test = 0;
/* find an edge connecting contour and hole not intersecting any other */
/* edge belonging to either the contour or any of the other holes */
for (v1 = contour->vertices, vertex1_cnt = contour->vertex_cnt, i = 0;
i < vertex1_cnt; i++, v1 = v1->next) {
for (v2 = hole->vertices, vertex2_cnt = hole->vertex_cnt, j = 0;
j < vertex2_cnt; j++, v2 = v2->next) {
/* does edge (v1,v2) intersect any edge of contour */
for (tmp_vertex = contour->vertices, tmp_vertex_cnt =
contour->vertex_cnt, k = 0; k < tmp_vertex_cnt;
tmp_vertex = tmp_vertex->next, k++) {
/* skip edge tests for edges directly connected */
if (v1 == tmp_vertex || v1 == tmp_vertex->next)
continue;
test = edge_edge_intersect(v1, v2, tmp_vertex, tmp_vertex->next);
if (test != GLU_NO_ERROR)
break;
}
if (test == GLU_NO_ERROR) {
/* does edge (v1,v2) intersect any edge of hole */
for (tmp_vertex = hole->vertices,
tmp_vertex_cnt = hole->vertex_cnt, k = 0;
k < tmp_vertex_cnt; tmp_vertex = tmp_vertex->next, k++) {
/* skip edge tests for edges directly connected */
if (v2 == tmp_vertex || v2 == tmp_vertex->next)
continue;
test =
edge_edge_intersect(v1, v2, tmp_vertex, tmp_vertex->next);
if (test != GLU_NO_ERROR)
break;
}
if (test == GLU_NO_ERROR) {
/* does edge (v1,v2) intersect any other hole? */
for (tmp_hole = hole->next;
tmp_hole != NULL && tmp_hole->type == GLU_INTERIOR;
tmp_hole = tmp_hole->next) {
/* does edge (v1,v2) intersect any edge of hole */
for (tmp_vertex = tmp_hole->vertices,
tmp_vertex_cnt = tmp_hole->vertex_cnt, k = 0;
k < tmp_vertex_cnt; tmp_vertex = tmp_vertex->next, k++) {
test = edge_edge_intersect(v1, v2, tmp_vertex,
tmp_vertex->next);
if (test != GLU_NO_ERROR)
break;
}
if (test != GLU_NO_ERROR)
break;
}
}
}
if (test == GLU_NO_ERROR) {
/* edge (v1,v2) is good for eliminating the hole */
if (merge_hole_with_contour(tobj, contour, hole, v1, v2)
== GLU_NO_ERROR)
return GLU_NO_ERROR;
else
return GLU_ERROR;
}
}
}
/* other holes are blocking all possible connections of hole */
/* with contour, we shift this hole as the last hole and retry */
for (tmp_hole = hole;
tmp_hole != NULL && tmp_hole->type == GLU_INTERIOR;
tmp_hole = tmp_hole->next);
contour->next = hole->next;
hole->next->previous = contour;
if (tmp_hole == NULL) {
/* last EXTERIOR contour, shift hole as last contour */
hole->next = NULL;
hole->previous = tobj->last_contour;
tobj->last_contour->next = hole;
tobj->last_contour = hole;
}
else {
tmp_hole->previous->next = hole;
hole->previous = tmp_hole->previous;
tmp_hole->previous = hole;
hole->next = tmp_hole;
}
hole = contour->next;
/* try once again - recurse */
return cut_out_hole(tobj, contour, hole);
}
static GLenum
merge_hole_with_contour(GLUtriangulatorObj * tobj,
tess_contour * contour,
tess_contour * hole,
tess_vertex * v1, tess_vertex * v2)
{
tess_vertex *v1_new, *v2_new;
/* make copies of v1 and v2, place them respectively after their originals */
if ((v1_new = (tess_vertex *) malloc(sizeof(tess_vertex))) == NULL) {
tess_call_user_error(tobj, GLU_OUT_OF_MEMORY);
return GLU_ERROR;
}
if ((v2_new = (tess_vertex *) malloc(sizeof(tess_vertex))) == NULL) {
tess_call_user_error(tobj, GLU_OUT_OF_MEMORY);
return GLU_ERROR;
}
v1_new->edge_flag = GL_TRUE;
v1_new->data = v1->data;
v1_new->location[0] = v1->location[0];
v1_new->location[1] = v1->location[1];
v1_new->location[2] = v1->location[2];
v1_new->x = v1->x;
v1_new->y = v1->y;
v1_new->shadow_vertex = v1;
v1->shadow_vertex = v1_new;
v1_new->next = v1->next;
v1_new->previous = v1;
v1->next->previous = v1_new;
v1->next = v1_new;
v2_new->edge_flag = GL_TRUE;
v2_new->data = v2->data;
v2_new->location[0] = v2->location[0];
v2_new->location[1] = v2->location[1];
v2_new->location[2] = v2->location[2];
v2_new->x = v2->x;
v2_new->y = v2->y;
v2_new->shadow_vertex = v2;
v2->shadow_vertex = v2_new;
v2_new->next = v2->next;
v2_new->previous = v2;
v2->next->previous = v2_new;
v2->next = v2_new;
/* link together the two lists */
v1->next = v2_new;
v2_new->previous = v1;
v2->next = v1_new;
v1_new->previous = v2;
/* update the vertex count of the contour */
contour->vertex_cnt += hole->vertex_cnt + 2;
/* remove the INTERIOR contour */
contour->next = hole->next;
if (hole->next != NULL)
hole->next->previous = contour;
free(hole);
/* update tobj structure */
--(tobj->contour_cnt);
if (contour->last_vertex == v1)
contour->last_vertex = v1_new;
/* mark two vertices with edge_flag */
v2->edge_flag = GL_FALSE;
v1->edge_flag = GL_FALSE;
return GLU_NO_ERROR;
}

402
src/glu/mini/project.c Normal file
View File

@@ -0,0 +1,402 @@
/* $Id: project.c,v 1.1.2.1 2003/03/21 13:02:18 keithw Exp $ */
/*
* Mesa 3-D graphics library
* Version: 3.3
* Copyright (C) 1995-2000 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifdef PC_HEADER
#include "all.h"
#else
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "gluP.h"
#endif
/*
* This code was contributed by Marc Buffat (buffat@mecaflu.ec-lyon.fr).
* Thanks Marc!!!
*/
/* implementation de gluProject et gluUnproject */
/* M. Buffat 17/2/95 */
/*
* Transform a point (column vector) by a 4x4 matrix. I.e. out = m * in
* Input: m - the 4x4 matrix
* in - the 4x1 vector
* Output: out - the resulting 4x1 vector.
*/
static void
transform_point(GLdouble out[4], const GLdouble m[16], const GLdouble in[4])
{
#define M(row,col) m[col*4+row]
out[0] =
M(0, 0) * in[0] + M(0, 1) * in[1] + M(0, 2) * in[2] + M(0, 3) * in[3];
out[1] =
M(1, 0) * in[0] + M(1, 1) * in[1] + M(1, 2) * in[2] + M(1, 3) * in[3];
out[2] =
M(2, 0) * in[0] + M(2, 1) * in[1] + M(2, 2) * in[2] + M(2, 3) * in[3];
out[3] =
M(3, 0) * in[0] + M(3, 1) * in[1] + M(3, 2) * in[2] + M(3, 3) * in[3];
#undef M
}
/*
* Perform a 4x4 matrix multiplication (product = a x b).
* Input: a, b - matrices to multiply
* Output: product - product of a and b
*/
static void
matmul(GLdouble * product, const GLdouble * a, const GLdouble * b)
{
/* This matmul was contributed by Thomas Malik */
GLdouble temp[16];
GLint i;
#define A(row,col) a[(col<<2)+row]
#define B(row,col) b[(col<<2)+row]
#define T(row,col) temp[(col<<2)+row]
/* i-te Zeile */
for (i = 0; i < 4; i++) {
T(i, 0) =
A(i, 0) * B(0, 0) + A(i, 1) * B(1, 0) + A(i, 2) * B(2, 0) + A(i,
3) *
B(3, 0);
T(i, 1) =
A(i, 0) * B(0, 1) + A(i, 1) * B(1, 1) + A(i, 2) * B(2, 1) + A(i,
3) *
B(3, 1);
T(i, 2) =
A(i, 0) * B(0, 2) + A(i, 1) * B(1, 2) + A(i, 2) * B(2, 2) + A(i,
3) *
B(3, 2);
T(i, 3) =
A(i, 0) * B(0, 3) + A(i, 1) * B(1, 3) + A(i, 2) * B(2, 3) + A(i,
3) *
B(3, 3);
}
#undef A
#undef B
#undef T
MEMCPY(product, temp, 16 * sizeof(GLdouble));
}
/*
* Compute inverse of 4x4 transformation matrix.
* Code contributed by Jacques Leroy jle@star.be
* Return GL_TRUE for success, GL_FALSE for failure (singular matrix)
*/
static GLboolean
invert_matrix(const GLdouble * m, GLdouble * out)
{
/* NB. OpenGL Matrices are COLUMN major. */
#define SWAP_ROWS(a, b) { GLdouble *_tmp = a; (a)=(b); (b)=_tmp; }
#define MAT(m,r,c) (m)[(c)*4+(r)]
GLdouble wtmp[4][8];
GLdouble m0, m1, m2, m3, s;
GLdouble *r0, *r1, *r2, *r3;
r0 = wtmp[0], r1 = wtmp[1], r2 = wtmp[2], r3 = wtmp[3];
r0[0] = MAT(m, 0, 0), r0[1] = MAT(m, 0, 1),
r0[2] = MAT(m, 0, 2), r0[3] = MAT(m, 0, 3),
r0[4] = 1.0, r0[5] = r0[6] = r0[7] = 0.0,
r1[0] = MAT(m, 1, 0), r1[1] = MAT(m, 1, 1),
r1[2] = MAT(m, 1, 2), r1[3] = MAT(m, 1, 3),
r1[5] = 1.0, r1[4] = r1[6] = r1[7] = 0.0,
r2[0] = MAT(m, 2, 0), r2[1] = MAT(m, 2, 1),
r2[2] = MAT(m, 2, 2), r2[3] = MAT(m, 2, 3),
r2[6] = 1.0, r2[4] = r2[5] = r2[7] = 0.0,
r3[0] = MAT(m, 3, 0), r3[1] = MAT(m, 3, 1),
r3[2] = MAT(m, 3, 2), r3[3] = MAT(m, 3, 3),
r3[7] = 1.0, r3[4] = r3[5] = r3[6] = 0.0;
/* choose pivot - or die */
if (fabs(r3[0]) > fabs(r2[0]))
SWAP_ROWS(r3, r2);
if (fabs(r2[0]) > fabs(r1[0]))
SWAP_ROWS(r2, r1);
if (fabs(r1[0]) > fabs(r0[0]))
SWAP_ROWS(r1, r0);
if (0.0 == r0[0])
return GL_FALSE;
/* eliminate first variable */
m1 = r1[0] / r0[0];
m2 = r2[0] / r0[0];
m3 = r3[0] / r0[0];
s = r0[1];
r1[1] -= m1 * s;
r2[1] -= m2 * s;
r3[1] -= m3 * s;
s = r0[2];
r1[2] -= m1 * s;
r2[2] -= m2 * s;
r3[2] -= m3 * s;
s = r0[3];
r1[3] -= m1 * s;
r2[3] -= m2 * s;
r3[3] -= m3 * s;
s = r0[4];
if (s != 0.0) {
r1[4] -= m1 * s;
r2[4] -= m2 * s;
r3[4] -= m3 * s;
}
s = r0[5];
if (s != 0.0) {
r1[5] -= m1 * s;
r2[5] -= m2 * s;
r3[5] -= m3 * s;
}
s = r0[6];
if (s != 0.0) {
r1[6] -= m1 * s;
r2[6] -= m2 * s;
r3[6] -= m3 * s;
}
s = r0[7];
if (s != 0.0) {
r1[7] -= m1 * s;
r2[7] -= m2 * s;
r3[7] -= m3 * s;
}
/* choose pivot - or die */
if (fabs(r3[1]) > fabs(r2[1]))
SWAP_ROWS(r3, r2);
if (fabs(r2[1]) > fabs(r1[1]))
SWAP_ROWS(r2, r1);
if (0.0 == r1[1])
return GL_FALSE;
/* eliminate second variable */
m2 = r2[1] / r1[1];
m3 = r3[1] / r1[1];
r2[2] -= m2 * r1[2];
r3[2] -= m3 * r1[2];
r2[3] -= m2 * r1[3];
r3[3] -= m3 * r1[3];
s = r1[4];
if (0.0 != s) {
r2[4] -= m2 * s;
r3[4] -= m3 * s;
}
s = r1[5];
if (0.0 != s) {
r2[5] -= m2 * s;
r3[5] -= m3 * s;
}
s = r1[6];
if (0.0 != s) {
r2[6] -= m2 * s;
r3[6] -= m3 * s;
}
s = r1[7];
if (0.0 != s) {
r2[7] -= m2 * s;
r3[7] -= m3 * s;
}
/* choose pivot - or die */
if (fabs(r3[2]) > fabs(r2[2]))
SWAP_ROWS(r3, r2);
if (0.0 == r2[2])
return GL_FALSE;
/* eliminate third variable */
m3 = r3[2] / r2[2];
r3[3] -= m3 * r2[3], r3[4] -= m3 * r2[4],
r3[5] -= m3 * r2[5], r3[6] -= m3 * r2[6], r3[7] -= m3 * r2[7];
/* last check */
if (0.0 == r3[3])
return GL_FALSE;
s = 1.0 / r3[3]; /* now back substitute row 3 */
r3[4] *= s;
r3[5] *= s;
r3[6] *= s;
r3[7] *= s;
m2 = r2[3]; /* now back substitute row 2 */
s = 1.0 / r2[2];
r2[4] = s * (r2[4] - r3[4] * m2), r2[5] = s * (r2[5] - r3[5] * m2),
r2[6] = s * (r2[6] - r3[6] * m2), r2[7] = s * (r2[7] - r3[7] * m2);
m1 = r1[3];
r1[4] -= r3[4] * m1, r1[5] -= r3[5] * m1,
r1[6] -= r3[6] * m1, r1[7] -= r3[7] * m1;
m0 = r0[3];
r0[4] -= r3[4] * m0, r0[5] -= r3[5] * m0,
r0[6] -= r3[6] * m0, r0[7] -= r3[7] * m0;
m1 = r1[2]; /* now back substitute row 1 */
s = 1.0 / r1[1];
r1[4] = s * (r1[4] - r2[4] * m1), r1[5] = s * (r1[5] - r2[5] * m1),
r1[6] = s * (r1[6] - r2[6] * m1), r1[7] = s * (r1[7] - r2[7] * m1);
m0 = r0[2];
r0[4] -= r2[4] * m0, r0[5] -= r2[5] * m0,
r0[6] -= r2[6] * m0, r0[7] -= r2[7] * m0;
m0 = r0[1]; /* now back substitute row 0 */
s = 1.0 / r0[0];
r0[4] = s * (r0[4] - r1[4] * m0), r0[5] = s * (r0[5] - r1[5] * m0),
r0[6] = s * (r0[6] - r1[6] * m0), r0[7] = s * (r0[7] - r1[7] * m0);
MAT(out, 0, 0) = r0[4];
MAT(out, 0, 1) = r0[5], MAT(out, 0, 2) = r0[6];
MAT(out, 0, 3) = r0[7], MAT(out, 1, 0) = r1[4];
MAT(out, 1, 1) = r1[5], MAT(out, 1, 2) = r1[6];
MAT(out, 1, 3) = r1[7], MAT(out, 2, 0) = r2[4];
MAT(out, 2, 1) = r2[5], MAT(out, 2, 2) = r2[6];
MAT(out, 2, 3) = r2[7], MAT(out, 3, 0) = r3[4];
MAT(out, 3, 1) = r3[5], MAT(out, 3, 2) = r3[6];
MAT(out, 3, 3) = r3[7];
return GL_TRUE;
#undef MAT
#undef SWAP_ROWS
}
/* projection du point (objx,objy,obz) sur l'ecran (winx,winy,winz) */
GLint GLAPIENTRY
gluProject(GLdouble objx, GLdouble objy, GLdouble objz,
const GLdouble model[16], const GLdouble proj[16],
const GLint viewport[4],
GLdouble * winx, GLdouble * winy, GLdouble * winz)
{
/* matrice de transformation */
GLdouble in[4], out[4];
/* initilise la matrice et le vecteur a transformer */
in[0] = objx;
in[1] = objy;
in[2] = objz;
in[3] = 1.0;
transform_point(out, model, in);
transform_point(in, proj, out);
/* d'ou le resultat normalise entre -1 et 1 */
if (in[3] == 0.0)
return GL_FALSE;
in[0] /= in[3];
in[1] /= in[3];
in[2] /= in[3];
/* en coordonnees ecran */
*winx = viewport[0] + (1 + in[0]) * viewport[2] / 2;
*winy = viewport[1] + (1 + in[1]) * viewport[3] / 2;
/* entre 0 et 1 suivant z */
*winz = (1 + in[2]) / 2;
return GL_TRUE;
}
/* transformation du point ecran (winx,winy,winz) en point objet */
GLint GLAPIENTRY
gluUnProject(GLdouble winx, GLdouble winy, GLdouble winz,
const GLdouble model[16], const GLdouble proj[16],
const GLint viewport[4],
GLdouble * objx, GLdouble * objy, GLdouble * objz)
{
/* matrice de transformation */
GLdouble m[16], A[16];
GLdouble in[4], out[4];
/* transformation coordonnees normalisees entre -1 et 1 */
in[0] = (winx - viewport[0]) * 2 / viewport[2] - 1.0;
in[1] = (winy - viewport[1]) * 2 / viewport[3] - 1.0;
in[2] = 2 * winz - 1.0;
in[3] = 1.0;
/* calcul transformation inverse */
matmul(A, proj, model);
invert_matrix(A, m);
/* d'ou les coordonnees objets */
transform_point(out, m, in);
if (out[3] == 0.0)
return GL_FALSE;
*objx = out[0] / out[3];
*objy = out[1] / out[3];
*objz = out[2] / out[3];
return GL_TRUE;
}
/*
* New in GLU 1.3
* This is like gluUnProject but also takes near and far DepthRange values.
*/
#ifdef GLU_VERSION_1_3
GLint GLAPIENTRY
gluUnProject4(GLdouble winx, GLdouble winy, GLdouble winz, GLdouble clipw,
const GLdouble modelMatrix[16],
const GLdouble projMatrix[16],
const GLint viewport[4],
GLclampd nearZ, GLclampd farZ,
GLdouble * objx, GLdouble * objy, GLdouble * objz,
GLdouble * objw)
{
/* matrice de transformation */
GLdouble m[16], A[16];
GLdouble in[4], out[4];
GLdouble z = nearZ + winz * (farZ - nearZ);
/* transformation coordonnees normalisees entre -1 et 1 */
in[0] = (winx - viewport[0]) * 2 / viewport[2] - 1.0;
in[1] = (winy - viewport[1]) * 2 / viewport[3] - 1.0;
in[2] = 2.0 * z - 1.0;
in[3] = clipw;
/* calcul transformation inverse */
matmul(A, projMatrix, modelMatrix);
invert_matrix(A, m);
/* d'ou les coordonnees objets */
transform_point(out, m, in);
if (out[3] == 0.0)
return GL_FALSE;
*objx = out[0] / out[3];
*objy = out[1] / out[3];
*objz = out[2] / out[3];
*objw = out[3];
return GL_TRUE;
}
#endif

774
src/glu/mini/quadric.c Normal file
View File

@@ -0,0 +1,774 @@
/* $Id: quadric.c,v 1.1.2.1 2003/03/21 13:02:22 keithw Exp $ */
/*
* Mesa 3-D graphics library
* Version: 3.3
* Copyright (C) 1999-2000 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* TODO:
* texture coordinate support
* flip normals according to orientation
* there's still some inside/outside orientation bugs in possibly all
* but the sphere function
*/
#ifdef PC_HEADER
#include "all.h"
#else
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "gluP.h"
#endif
#ifndef M_PI
# define M_PI (3.1415926)
#endif
/*
* Convert degrees to radians:
*/
#define DEG_TO_RAD(A) ((A)*(M_PI/180.0))
/*
* Sin and Cos for degree angles:
*/
#define SIND( A ) sin( (A)*(M_PI/180.0) )
#define COSD( A) cos( (A)*(M_PI/180.0) )
/*
* Texture coordinates if texture flag is set
*/
#define TXTR_COORD(x,y) if (qobj->TextureFlag) glTexCoord2f(x,y);
struct GLUquadric
{
GLenum DrawStyle; /* GLU_FILL, LINE, SILHOUETTE, or POINT */
GLenum Orientation; /* GLU_INSIDE or GLU_OUTSIDE */
GLboolean TextureFlag; /* Generate texture coords? */
GLenum Normals; /* GLU_NONE, GLU_FLAT, or GLU_SMOOTH */
void (GLCALLBACK * ErrorFunc) (GLenum err); /* Error handler callback function */
};
/*
* Process a GLU error.
*/
static void
quadric_error(GLUquadricObj * qobj, GLenum error, const char *msg)
{
/* Call the error call back function if any */
if (qobj->ErrorFunc) {
(*qobj->ErrorFunc) (error);
}
/* Print a message to stdout if MESA_DEBUG variable is defined */
if (getenv("MESA_DEBUG")) {
fprintf(stderr, "GLUError: %s: %s\n", (char *) gluErrorString(error),
msg);
}
}
GLUquadricObj *GLAPIENTRY
gluNewQuadric(void)
{
GLUquadricObj *q;
q = (GLUquadricObj *) malloc(sizeof(struct GLUquadric));
if (q) {
q->DrawStyle = GLU_FILL;
q->Orientation = GLU_OUTSIDE;
q->TextureFlag = GL_FALSE;
q->Normals = GLU_SMOOTH;
q->ErrorFunc = NULL;
}
return q;
}
void GLAPIENTRY
gluDeleteQuadric(GLUquadricObj * state)
{
if (state) {
free((void *) state);
}
}
/*
* Set the drawing style to be GLU_FILL, GLU_LINE, GLU_SILHOUETTE,
* or GLU_POINT.
*/
void GLAPIENTRY
gluQuadricDrawStyle(GLUquadricObj * quadObject, GLenum drawStyle)
{
if (quadObject && (drawStyle == GLU_FILL || drawStyle == GLU_LINE
|| drawStyle == GLU_SILHOUETTE
|| drawStyle == GLU_POINT)) {
quadObject->DrawStyle = drawStyle;
}
else {
quadric_error(quadObject, GLU_INVALID_ENUM, "qluQuadricDrawStyle");
}
}
/*
* Set the orientation to GLU_INSIDE or GLU_OUTSIDE.
*/
void GLAPIENTRY
gluQuadricOrientation(GLUquadricObj * quadObject, GLenum orientation)
{
if (quadObject
&& (orientation == GLU_INSIDE || orientation == GLU_OUTSIDE)) {
quadObject->Orientation = orientation;
}
else {
quadric_error(quadObject, GLU_INVALID_ENUM, "qluQuadricOrientation");
}
}
/*
* Set the error handler callback function.
*/
void GLAPIENTRY
gluQuadricCallback(GLUquadricObj * qobj,
GLenum which, void (GLCALLBACK * fn) ())
{
/*
* UGH, this is a mess! I thought ANSI was a standard.
*/
if (qobj && which == GLU_ERROR) {
#ifdef __CYGWIN32__
qobj->ErrorFunc = (void (GLCALLBACKPCAST) (GLenum)) fn;
#elif defined(OPENSTEP)
qobj->ErrorFunc = (void (*)(GLenum)) fn;
#elif defined(_WIN32)
qobj->ErrorFunc = (void (GLCALLBACK *) (int)) fn;
#elif defined(__STORM__)
qobj->ErrorFunc = (void (GLCALLBACK *) (GLenum)) fn;
#elif defined(__BEOS__)
qobj->ErrorFunc = (void (*)(GLenum)) fn;
#else
qobj->ErrorFunc = (void (GLCALLBACK *) ()) fn;
#endif
}
}
void GLAPIENTRY
gluQuadricNormals(GLUquadricObj * quadObject, GLenum normals)
{
if (quadObject
&& (normals == GLU_NONE || normals == GLU_FLAT
|| normals == GLU_SMOOTH)) {
quadObject->Normals = normals;
}
}
void GLAPIENTRY
gluQuadricTexture(GLUquadricObj * quadObject, GLboolean textureCoords)
{
if (quadObject) {
quadObject->TextureFlag = textureCoords;
}
}
/*
* Call glNormal3f after scaling normal to unit length.
*/
static void
normal3f(GLfloat x, GLfloat y, GLfloat z)
{
}
void GLAPIENTRY
gluCylinder(GLUquadricObj * qobj,
GLdouble baseRadius, GLdouble topRadius,
GLdouble height, GLint slices, GLint stacks)
{
GLdouble da, r, dr, dz;
GLfloat x, y, z, nz, nsign;
GLint i, j;
if (qobj->Orientation == GLU_INSIDE) {
nsign = -1.0;
}
else {
nsign = 1.0;
}
da = 2.0 * M_PI / slices;
dr = (topRadius - baseRadius) / stacks;
dz = height / stacks;
nz = (baseRadius - topRadius) / height; /* Z component of normal vectors */
if (qobj->DrawStyle == GLU_POINT) {
glBegin(GL_POINTS);
for (i = 0; i < slices; i++) {
x = cos(i * da);
y = sin(i * da);
normal3f(x * nsign, y * nsign, nz * nsign);
z = 0.0;
r = baseRadius;
for (j = 0; j <= stacks; j++) {
glVertex3f(x * r, y * r, z);
z += dz;
r += dr;
}
}
glEnd();
}
else if (qobj->DrawStyle == GLU_LINE || qobj->DrawStyle == GLU_SILHOUETTE) {
/* Draw rings */
if (qobj->DrawStyle == GLU_LINE) {
z = 0.0;
r = baseRadius;
for (j = 0; j <= stacks; j++) {
glBegin(GL_LINE_LOOP);
for (i = 0; i < slices; i++) {
x = cos(i * da);
y = sin(i * da);
normal3f(x * nsign, y * nsign, nz * nsign);
glVertex3f(x * r, y * r, z);
}
glEnd();
z += dz;
r += dr;
}
}
else {
/* draw one ring at each end */
if (baseRadius != 0.0) {
glBegin(GL_LINE_LOOP);
for (i = 0; i < slices; i++) {
x = cos(i * da);
y = sin(i * da);
normal3f(x * nsign, y * nsign, nz * nsign);
glVertex3f(x * baseRadius, y * baseRadius, 0.0);
}
glEnd();
glBegin(GL_LINE_LOOP);
for (i = 0; i < slices; i++) {
x = cos(i * da);
y = sin(i * da);
normal3f(x * nsign, y * nsign, nz * nsign);
glVertex3f(x * topRadius, y * topRadius, height);
}
glEnd();
}
}
/* draw length lines */
glBegin(GL_LINES);
for (i = 0; i < slices; i++) {
x = cos(i * da);
y = sin(i * da);
normal3f(x * nsign, y * nsign, nz * nsign);
glVertex3f(x * baseRadius, y * baseRadius, 0.0);
glVertex3f(x * topRadius, y * topRadius, height);
}
glEnd();
}
else if (qobj->DrawStyle == GLU_FILL) {
GLfloat ds = 1.0 / slices;
GLfloat dt = 1.0 / stacks;
GLfloat t = 0.0;
z = 0.0;
r = baseRadius;
for (j = 0; j < stacks; j++) {
GLfloat s = 0.0;
glBegin(GL_QUAD_STRIP);
for (i = 0; i <= slices; i++) {
GLfloat x, y;
if (i == slices) {
x = sin(0.0);
y = cos(0.0);
}
else {
x = sin(i * da);
y = cos(i * da);
}
if (nsign == 1.0) {
normal3f(x * nsign, y * nsign, nz * nsign);
TXTR_COORD(s, t);
glVertex3f(x * r, y * r, z);
normal3f(x * nsign, y * nsign, nz * nsign);
TXTR_COORD(s, t + dt);
glVertex3f(x * (r + dr), y * (r + dr), z + dz);
}
else {
normal3f(x * nsign, y * nsign, nz * nsign);
TXTR_COORD(s, t);
glVertex3f(x * r, y * r, z);
normal3f(x * nsign, y * nsign, nz * nsign);
TXTR_COORD(s, t + dt);
glVertex3f(x * (r + dr), y * (r + dr), z + dz);
}
s += ds;
} /* for slices */
glEnd();
r += dr;
t += dt;
z += dz;
} /* for stacks */
}
}
void GLAPIENTRY
gluSphere(GLUquadricObj * qobj, GLdouble radius, GLint slices, GLint stacks)
{
GLfloat rho, drho, theta, dtheta;
GLfloat x, y, z;
GLfloat s, t, ds, dt;
GLint i, j, imin, imax;
GLboolean normals;
GLfloat nsign;
if (qobj->Normals == GLU_NONE) {
normals = GL_FALSE;
}
else {
normals = GL_TRUE;
}
if (qobj->Orientation == GLU_INSIDE) {
nsign = -1.0;
}
else {
nsign = 1.0;
}
drho = M_PI / (GLfloat) stacks;
dtheta = 2.0 * M_PI / (GLfloat) slices;
/* texturing: s goes from 0.0/0.25/0.5/0.75/1.0 at +y/+x/-y/-x/+y axis */
/* t goes from -1.0/+1.0 at z = -radius/+radius (linear along longitudes) */
/* cannot use triangle fan on texturing (s coord. at top/bottom tip varies) */
if (qobj->DrawStyle == GLU_FILL) {
if (!qobj->TextureFlag) {
/* draw +Z end as a triangle fan */
glBegin(GL_TRIANGLE_FAN);
/* glNormal3f(0.0, 0.0, 1.0); */
glVertex3f(0.0, 0.0, nsign * radius);
for (j = 0; j <= slices; j++) {
theta = (j == slices) ? 0.0 : j * dtheta;
x = -sin(theta) * sin(drho);
y = cos(theta) * sin(drho);
z = nsign * cos(drho);
glVertex3f(x * radius, y * radius, z * radius);
}
glEnd();
}
ds = 1.0 / slices;
dt = 1.0 / stacks;
t = 1.0; /* because loop now runs from 0 */
if (qobj->TextureFlag) {
imin = 0;
imax = stacks;
}
else {
imin = 1;
imax = stacks - 1;
}
/* draw intermediate stacks as quad strips */
for (i = imin; i < imax; i++) {
rho = i * drho;
glBegin(GL_QUAD_STRIP);
s = 0.0;
for (j = 0; j <= slices; j++) {
theta = (j == slices) ? 0.0 : j * dtheta;
x = -sin(theta) * sin(rho);
y = cos(theta) * sin(rho);
z = nsign * cos(rho);
TXTR_COORD(s, t);
glVertex3f(x * radius, y * radius, z * radius);
x = -sin(theta) * sin(rho + drho);
y = cos(theta) * sin(rho + drho);
z = nsign * cos(rho + drho);
TXTR_COORD(s, t - dt);
s += ds;
glVertex3f(x * radius, y * radius, z * radius);
}
glEnd();
t -= dt;
}
if (!qobj->TextureFlag) {
/* draw -Z end as a triangle fan */
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0.0, 0.0, -radius * nsign);
rho = M_PI - drho;
s = 1.0;
t = dt;
for (j = slices; j >= 0; j--) {
theta = (j == slices) ? 0.0 : j * dtheta;
x = -sin(theta) * sin(rho);
y = cos(theta) * sin(rho);
z = nsign * cos(rho);
s -= ds;
glVertex3f(x * radius, y * radius, z * radius);
}
glEnd();
}
}
else if (qobj->DrawStyle == GLU_LINE || qobj->DrawStyle == GLU_SILHOUETTE) {
/* draw stack lines */
for (i = 1; i < stacks; i++) { /* stack line at i==stacks-1 was missing here */
rho = i * drho;
glBegin(GL_LINE_LOOP);
for (j = 0; j < slices; j++) {
theta = j * dtheta;
x = cos(theta) * sin(rho);
y = sin(theta) * sin(rho);
z = cos(rho);
glVertex3f(x * radius, y * radius, z * radius);
}
glEnd();
}
/* draw slice lines */
for (j = 0; j < slices; j++) {
theta = j * dtheta;
glBegin(GL_LINE_STRIP);
for (i = 0; i <= stacks; i++) {
rho = i * drho;
x = cos(theta) * sin(rho);
y = sin(theta) * sin(rho);
z = cos(rho);
glVertex3f(x * radius, y * radius, z * radius);
}
glEnd();
}
}
else if (qobj->DrawStyle == GLU_POINT) {
/* top and bottom-most points */
glBegin(GL_POINTS);
glVertex3f(0.0, 0.0, radius);
glVertex3f(0.0, 0.0, -radius);
/* loop over stacks */
for (i = 1; i < stacks - 1; i++) {
rho = i * drho;
for (j = 0; j < slices; j++) {
theta = j * dtheta;
x = cos(theta) * sin(rho);
y = sin(theta) * sin(rho);
z = cos(rho);
glVertex3f(x * radius, y * radius, z * radius);
}
}
glEnd();
}
}
void GLAPIENTRY
gluDisk(GLUquadricObj * qobj,
GLdouble innerRadius, GLdouble outerRadius, GLint slices, GLint loops)
{
GLfloat da, dr;
#if 0
GLdouble a, da;
GLfloat r, dr;
GLfloat x, y;
GLfloat r1, r2, dtc;
GLint s, l;
#endif
da = 2.0 * M_PI / slices;
dr = (outerRadius - innerRadius) / (GLfloat) loops;
switch (qobj->DrawStyle) {
case GLU_FILL:
{
/* texture of a gluDisk is a cut out of the texture unit square
* x, y in [-outerRadius, +outerRadius]; s, t in [0, 1]
* (linear mapping)
*/
GLfloat dtc = 2.0f * outerRadius;
GLfloat sa, ca;
GLfloat r1 = innerRadius;
GLint l;
for (l = 0; l < loops; l++) {
GLfloat r2 = r1 + dr;
if (qobj->Orientation == GLU_OUTSIDE) {
GLint s;
glBegin(GL_QUAD_STRIP);
for (s = 0; s <= slices; s++) {
GLfloat a;
if (s == slices)
a = 0.0;
else
a = s * da;
sa = sin(a);
ca = cos(a);
TXTR_COORD(0.5 + sa * r2 / dtc, 0.5 + ca * r2 / dtc);
glVertex2f(r2 * sa, r2 * ca);
TXTR_COORD(0.5 + sa * r1 / dtc, 0.5 + ca * r1 / dtc);
glVertex2f(r1 * sa, r1 * ca);
}
glEnd();
}
else {
GLint s;
glBegin(GL_QUAD_STRIP);
for (s = slices; s >= 0; s--) {
GLfloat a;
if (s == slices)
a = 0.0;
else
a = s * da;
sa = sin(a);
ca = cos(a);
TXTR_COORD(0.5 - sa * r2 / dtc, 0.5 + ca * r2 / dtc);
glVertex2f(r2 * sa, r2 * ca);
TXTR_COORD(0.5 - sa * r1 / dtc, 0.5 + ca * r1 / dtc);
glVertex2f(r1 * sa, r1 * ca);
}
glEnd();
}
r1 = r2;
}
break;
}
case GLU_LINE:
{
GLint l, s;
/* draw loops */
for (l = 0; l <= loops; l++) {
GLfloat r = innerRadius + l * dr;
glBegin(GL_LINE_LOOP);
for (s = 0; s < slices; s++) {
GLfloat a = s * da;
glVertex2f(r * sin(a), r * cos(a));
}
glEnd();
}
/* draw spokes */
for (s = 0; s < slices; s++) {
GLfloat a = s * da;
GLfloat x = sin(a);
GLfloat y = cos(a);
glBegin(GL_LINE_STRIP);
for (l = 0; l <= loops; l++) {
GLfloat r = innerRadius + l * dr;
glVertex2f(r * x, r * y);
}
glEnd();
}
break;
}
case GLU_POINT:
{
GLint s;
glBegin(GL_POINTS);
for (s = 0; s < slices; s++) {
GLfloat a = s * da;
GLfloat x = sin(a);
GLfloat y = cos(a);
GLint l;
for (l = 0; l <= loops; l++) {
GLfloat r = innerRadius * l * dr;
glVertex2f(r * x, r * y);
}
}
glEnd();
break;
}
case GLU_SILHOUETTE:
{
if (innerRadius != 0.0) {
GLfloat a;
glBegin(GL_LINE_LOOP);
for (a = 0.0; a < 2.0 * M_PI; a += da) {
GLfloat x = innerRadius * sin(a);
GLfloat y = innerRadius * cos(a);
glVertex2f(x, y);
}
glEnd();
}
{
GLfloat a;
glBegin(GL_LINE_LOOP);
for (a = 0; a < 2.0 * M_PI; a += da) {
GLfloat x = outerRadius * sin(a);
GLfloat y = outerRadius * cos(a);
glVertex2f(x, y);
}
glEnd();
}
break;
}
default:
abort();
}
}
void GLAPIENTRY
gluPartialDisk(GLUquadricObj * qobj, GLdouble innerRadius,
GLdouble outerRadius, GLint slices, GLint loops,
GLdouble startAngle, GLdouble sweepAngle)
{
if (qobj->DrawStyle == GLU_POINT) {
GLint loop, slice;
GLdouble radius, delta_radius;
GLdouble angle, delta_angle;
delta_radius = (outerRadius - innerRadius) / (loops - 1);
delta_angle = DEG_TO_RAD((sweepAngle) / (slices - 1));
glBegin(GL_POINTS);
radius = innerRadius;
for (loop = 0; loop < loops; loop++) {
angle = DEG_TO_RAD(startAngle);
for (slice = 0; slice < slices; slice++) {
glVertex2f(radius * sin(angle), radius * cos(angle));
angle += delta_angle;
}
radius += delta_radius;
}
glEnd();
}
else if (qobj->DrawStyle == GLU_LINE) {
GLint loop, slice;
GLdouble radius, delta_radius;
GLdouble angle, delta_angle;
delta_radius = (outerRadius - innerRadius) / loops;
delta_angle = DEG_TO_RAD(sweepAngle / slices);
/* draw rings */
radius = innerRadius;
for (loop = 0; loop < loops; loop++) {
angle = DEG_TO_RAD(startAngle);
glBegin(GL_LINE_STRIP);
for (slice = 0; slice <= slices; slice++) {
glVertex2f(radius * sin(angle), radius * cos(angle));
angle += delta_angle;
}
glEnd();
radius += delta_radius;
}
/* draw spokes */
angle = DEG_TO_RAD(startAngle);
for (slice = 0; slice <= slices; slice++) {
radius = innerRadius;
glBegin(GL_LINE_STRIP);
for (loop = 0; loop < loops; loop++) {
glVertex2f(radius * sin(angle), radius * cos(angle));
radius += delta_radius;
}
glEnd();
angle += delta_angle;
}
}
else if (qobj->DrawStyle == GLU_SILHOUETTE) {
GLint slice;
GLdouble angle, delta_angle;
delta_angle = DEG_TO_RAD(sweepAngle / slices);
/* draw outer ring */
glBegin(GL_LINE_STRIP);
angle = DEG_TO_RAD(startAngle);
for (slice = 0; slice <= slices; slice++) {
glVertex2f(outerRadius * sin(angle), outerRadius * cos(angle));
angle += delta_angle;
}
glEnd();
/* draw inner ring */
if (innerRadius > 0.0) {
glBegin(GL_LINE_STRIP);
angle = DEG_TO_RAD(startAngle);
for (slice = 0; slice < slices; slice++) {
glVertex2f(innerRadius * sin(angle), innerRadius * cos(angle));
angle += delta_angle;
}
glEnd();
}
/* draw spokes */
if (sweepAngle < 360.0) {
GLdouble stopAngle = startAngle + sweepAngle;
glBegin(GL_LINES);
glVertex2f(innerRadius * SIND(startAngle),
innerRadius * COSD(startAngle));
glVertex2f(outerRadius * SIND(startAngle),
outerRadius * COSD(startAngle));
glVertex2f(innerRadius * SIND(stopAngle),
innerRadius * COSD(stopAngle));
glVertex2f(outerRadius * SIND(stopAngle),
outerRadius * COSD(stopAngle));
glEnd();
}
}
else if (qobj->DrawStyle == GLU_FILL) {
GLint loop, slice;
GLdouble radius, delta_radius;
GLdouble angle, delta_angle;
delta_radius = (outerRadius - innerRadius) / loops;
delta_angle = DEG_TO_RAD(sweepAngle / slices);
radius = innerRadius;
for (loop = 0; loop < loops; loop++) {
glBegin(GL_QUAD_STRIP);
angle = DEG_TO_RAD(startAngle);
for (slice = 0; slice <= slices; slice++) {
if (qobj->Orientation == GLU_OUTSIDE) {
glVertex2f((radius + delta_radius) * sin(angle),
(radius + delta_radius) * cos(angle));
glVertex2f(radius * sin(angle), radius * cos(angle));
}
else {
glVertex2f(radius * sin(angle), radius * cos(angle));
glVertex2f((radius + delta_radius) * sin(angle),
(radius + delta_radius) * cos(angle));
}
angle += delta_angle;
}
glEnd();
radius += delta_radius;
}
}
}

328
src/glu/mini/tess.c Normal file
View File

@@ -0,0 +1,328 @@
/* $Id: tess.c,v 1.1.2.1 2003/03/21 13:02:23 keithw Exp $ */
/*
* Mesa 3-D graphics library
* Version: 3.3
* Copyright (C) 1995-2000 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* This file is part of the polygon tesselation code contributed by
* Bogdan Sikorski
*/
#ifdef PC_HEADER
#include "all.h"
#else
#include <math.h>
#include <stdlib.h>
#include "tess.h"
#endif
/*
* This is ugly, but seems the easiest way to do things to make the
* code work under YellowBox for Windows
*/
#if defined(OPENSTEP) && defined(CALLBACK)
#undef CALLBACK
#define CALLBACK
#endif
static void delete_contours(GLUtriangulatorObj *);
#ifdef __CYGWIN32__
#define _CALLBACK
#else
#define _CALLBACK GLCALLBACK
#endif
static void
init_callbacks(tess_callbacks * callbacks)
{
callbacks->begin = (void (_CALLBACK *) (GLenum)) 0;
callbacks->edgeFlag = (void (_CALLBACK *) (GLboolean)) 0;
callbacks->vertex = (void (_CALLBACK *) (void *)) 0;
callbacks->end = (void (_CALLBACK *) (void)) 0;
callbacks->error = (void (_CALLBACK *) (GLenum)) 0;
}
void
tess_call_user_error(GLUtriangulatorObj * tobj, GLenum gluerr)
{
if (tobj->error == GLU_NO_ERROR)
tobj->error = gluerr;
if (tobj->callbacks.error != NULL)
(tobj->callbacks.error) (gluerr);
}
GLUtriangulatorObj *GLAPIENTRY
gluNewTess(void)
{
GLUtriangulatorObj *tobj;
if ((tobj = (GLUtriangulatorObj *)
malloc(sizeof(struct GLUtesselator))) == NULL)
return NULL;
tobj->contours = tobj->last_contour = NULL;
init_callbacks(&tobj->callbacks);
tobj->error = GLU_NO_ERROR;
tobj->current_polygon = NULL;
tobj->contour_cnt = 0;
return tobj;
}
void GLAPIENTRY
gluTessCallback(GLUtriangulatorObj * tobj, GLenum which,
void (GLCALLBACK * fn) ())
{
switch (which) {
case GLU_BEGIN:
tobj->callbacks.begin = (void (_CALLBACK *) (GLenum)) fn;
break;
case GLU_EDGE_FLAG:
tobj->callbacks.edgeFlag = (void (_CALLBACK *) (GLboolean)) fn;
break;
case GLU_VERTEX:
tobj->callbacks.vertex = (void (_CALLBACK *) (void *)) fn;
break;
case GLU_END:
tobj->callbacks.end = (void (_CALLBACK *) (void)) fn;
break;
case GLU_ERROR:
tobj->callbacks.error = (void (_CALLBACK *) (GLenum)) fn;
break;
default:
tobj->error = GLU_INVALID_ENUM;
break;
}
}
void GLAPIENTRY
gluDeleteTess(GLUtriangulatorObj * tobj)
{
if (tobj->error == GLU_NO_ERROR && tobj->contour_cnt)
/* was gluEndPolygon called? */
tess_call_user_error(tobj, GLU_TESS_ERROR1);
/* delete all internal structures */
delete_contours(tobj);
free(tobj);
}
void GLAPIENTRY
gluBeginPolygon(GLUtriangulatorObj * tobj)
{
/*
if(tobj->error!=GLU_NO_ERROR)
return;
*/
tobj->error = GLU_NO_ERROR;
if (tobj->current_polygon != NULL) {
/* gluEndPolygon was not called */
tess_call_user_error(tobj, GLU_TESS_ERROR1);
/* delete all internal structures */
delete_contours(tobj);
}
else {
if ((tobj->current_polygon =
(tess_polygon *) malloc(sizeof(tess_polygon))) == NULL) {
tess_call_user_error(tobj, GLU_OUT_OF_MEMORY);
return;
}
tobj->current_polygon->vertex_cnt = 0;
tobj->current_polygon->vertices =
tobj->current_polygon->last_vertex = NULL;
}
}
void GLAPIENTRY
gluEndPolygon(GLUtriangulatorObj * tobj)
{
/*tess_contour *contour_ptr; */
/* there was an error */
if (tobj->error != GLU_NO_ERROR)
goto end;
/* check if gluBeginPolygon was called */
if (tobj->current_polygon == NULL) {
tess_call_user_error(tobj, GLU_TESS_ERROR2);
return;
}
tess_test_polygon(tobj);
/* there was an error */
if (tobj->error != GLU_NO_ERROR)
goto end;
/* any real contours? */
if (tobj->contour_cnt == 0) {
/* delete all internal structures */
delete_contours(tobj);
return;
}
tess_find_contour_hierarchies(tobj);
/* there was an error */
if (tobj->error != GLU_NO_ERROR)
goto end;
tess_handle_holes(tobj);
/* there was an error */
if (tobj->error != GLU_NO_ERROR)
goto end;
/* if no callbacks, nothing to do */
if (tobj->callbacks.begin != NULL && tobj->callbacks.vertex != NULL &&
tobj->callbacks.end != NULL) {
if (tobj->callbacks.edgeFlag == NULL)
tess_tesselate(tobj);
else
tess_tesselate_with_edge_flag(tobj);
}
end:
/* delete all internal structures */
delete_contours(tobj);
}
void GLAPIENTRY
gluNextContour(GLUtriangulatorObj * tobj, GLenum type)
{
if (tobj->error != GLU_NO_ERROR)
return;
if (tobj->current_polygon == NULL) {
tess_call_user_error(tobj, GLU_TESS_ERROR2);
return;
}
/* first contour? */
if (tobj->current_polygon->vertex_cnt)
tess_test_polygon(tobj);
}
void GLAPIENTRY
gluTessVertex(GLUtriangulatorObj * tobj, GLdouble v[3], void *data)
{
tess_polygon *polygon = tobj->current_polygon;
tess_vertex *last_vertex_ptr;
if (tobj->error != GLU_NO_ERROR)
return;
if (polygon == NULL) {
tess_call_user_error(tobj, GLU_TESS_ERROR2);
return;
}
last_vertex_ptr = polygon->last_vertex;
if (last_vertex_ptr == NULL) {
if ((last_vertex_ptr = (tess_vertex *)
malloc(sizeof(tess_vertex))) == NULL) {
tess_call_user_error(tobj, GLU_OUT_OF_MEMORY);
return;
}
polygon->vertices = last_vertex_ptr;
polygon->last_vertex = last_vertex_ptr;
last_vertex_ptr->data = data;
last_vertex_ptr->location[0] = v[0];
last_vertex_ptr->location[1] = v[1];
last_vertex_ptr->location[2] = v[2];
last_vertex_ptr->next = NULL;
last_vertex_ptr->previous = NULL;
++(polygon->vertex_cnt);
}
else {
tess_vertex *vertex_ptr;
/* same point twice? */
if (fabs(last_vertex_ptr->location[0] - v[0]) < EPSILON &&
fabs(last_vertex_ptr->location[1] - v[1]) < EPSILON &&
fabs(last_vertex_ptr->location[2] - v[2]) < EPSILON) {
tess_call_user_error(tobj, GLU_TESS_ERROR6);
return;
}
if ((vertex_ptr = (tess_vertex *)
malloc(sizeof(tess_vertex))) == NULL) {
tess_call_user_error(tobj, GLU_OUT_OF_MEMORY);
return;
}
vertex_ptr->data = data;
vertex_ptr->location[0] = v[0];
vertex_ptr->location[1] = v[1];
vertex_ptr->location[2] = v[2];
vertex_ptr->next = NULL;
vertex_ptr->previous = last_vertex_ptr;
++(polygon->vertex_cnt);
last_vertex_ptr->next = vertex_ptr;
polygon->last_vertex = vertex_ptr;
}
}
static void
delete_contours(GLUtriangulatorObj * tobj)
{
tess_polygon *polygon = tobj->current_polygon;
tess_contour *contour, *contour_tmp;
tess_vertex *vertex, *vertex_tmp;
/* remove current_polygon list - if exists due to detected error */
if (polygon != NULL) {
if (polygon->vertices) {
for (vertex = polygon->vertices; vertex != polygon->last_vertex;) {
vertex_tmp = vertex->next;
free(vertex);
vertex = vertex_tmp;
}
free(vertex);
}
free(polygon);
tobj->current_polygon = NULL;
}
/* remove all contour data */
for (contour = tobj->contours; contour != NULL;) {
for (vertex = contour->vertices; vertex != contour->last_vertex;) {
vertex_tmp = vertex->next;
free(vertex);
vertex = vertex_tmp;
}
free(vertex);
contour_tmp = contour->next;
free(contour);
contour = contour_tmp;
}
tobj->contours = tobj->last_contour = NULL;
tobj->contour_cnt = 0;
}
void GLAPIENTRY
gluTessNormal(GLUtesselator *tess, GLdouble valueX, GLdouble valueY, GLdouble valueZ)
{
/* dummy function */
(void) tess;
(void) valueX;
(void) valueY;
(void) valueZ;
}

108
src/glu/mini/tess.h Normal file
View File

@@ -0,0 +1,108 @@
/* $Id: tess.h,v 1.1.2.1 2003/03/21 13:02:23 keithw Exp $ */
/*
* Mesa 3-D graphics library
* Version: 3.3
* Copyright (C) 1995-2000 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* This file is part of the polygon tesselation code contributed by
* Bogdan Sikorski
*/
#ifndef TESS_H
#define TESS_H
#include "gluP.h"
#define EPSILON 1e-06 /* epsilon for double precision compares */
typedef enum
{
OXY,
OYZ,
OXZ
}
projection_type;
typedef struct callbacks_str
{
void (GLCALLBACK * begin) (GLenum mode);
void (GLCALLBACK * edgeFlag) (GLboolean flag);
void (GLCALLBACK * vertex) (GLvoid * v);
void (GLCALLBACK * end) (void);
void (GLCALLBACK * error) (GLenum err);
}
tess_callbacks;
typedef struct vertex_str
{
void *data;
GLdouble location[3];
GLdouble x, y;
GLboolean edge_flag;
struct vertex_str *shadow_vertex;
struct vertex_str *next, *previous;
}
tess_vertex;
typedef struct contour_str
{
GLenum type;
GLuint vertex_cnt;
GLdouble area;
GLenum orientation;
struct vertex_str *vertices, *last_vertex;
struct contour_str *next, *previous;
}
tess_contour;
typedef struct polygon_str
{
GLuint vertex_cnt;
GLdouble A, B, C, D;
GLdouble area;
GLenum orientation;
struct vertex_str *vertices, *last_vertex;
}
tess_polygon;
struct GLUtesselator
{
tess_contour *contours, *last_contour;
GLuint contour_cnt;
tess_callbacks callbacks;
tess_polygon *current_polygon;
GLenum error;
GLdouble A, B, C, D;
projection_type projection;
};
extern void tess_call_user_error(GLUtriangulatorObj *, GLenum);
extern void tess_test_polygon(GLUtriangulatorObj *);
extern void tess_find_contour_hierarchies(GLUtriangulatorObj *);
extern void tess_handle_holes(GLUtriangulatorObj *);
extern void tess_tesselate(GLUtriangulatorObj *);
extern void tess_tesselate_with_edge_flag(GLUtriangulatorObj *);
#endif

407
src/glu/mini/tesselat.c Normal file
View File

@@ -0,0 +1,407 @@
/* $Id: tesselat.c,v 1.1.2.1 2003/03/21 13:02:23 keithw Exp $ */
/*
* Mesa 3-D graphics library
* Version: 3.3
* Copyright (C) 1995-2000 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* This file is part of the polygon tesselation code contributed by
* Bogdan Sikorski
*/
#ifdef PC_HEADER
#include "all.h"
#else
#include <stdlib.h>
#include <math.h>
#include "tess.h"
#endif
static GLboolean edge_flag;
static void emit_triangle(GLUtriangulatorObj *, tess_vertex *,
tess_vertex *, tess_vertex *);
static void emit_triangle_with_edge_flag(GLUtriangulatorObj *,
tess_vertex *, GLboolean,
tess_vertex *, GLboolean,
tess_vertex *, GLboolean);
static GLdouble
twice_the_triangle_area(tess_vertex * va, tess_vertex * vb, tess_vertex * vc)
{
return (vb->x - va->x) * (vc->y - va->y) - (vb->y - va->y) * (vc->x -
va->x);
}
static GLboolean
left(GLdouble A, GLdouble B, GLdouble C, GLdouble x, GLdouble y)
{
if (A * x + B * y + C > -EPSILON)
return GL_TRUE;
else
return GL_FALSE;
}
static GLboolean
right(GLdouble A, GLdouble B, GLdouble C, GLdouble x, GLdouble y)
{
if (A * x + B * y + C < EPSILON)
return GL_TRUE;
else
return GL_FALSE;
}
static GLint
convex_ccw(tess_vertex * va,
tess_vertex * vb, tess_vertex * vc, GLUtriangulatorObj * tobj)
{
GLdouble d;
d = twice_the_triangle_area(va, vb, vc);
if (d > EPSILON) {
return 1;
}
else if (d < -EPSILON) {
return 0;
}
else {
return -1;
}
}
static GLint
convex_cw(tess_vertex * va,
tess_vertex * vb, tess_vertex * vc, GLUtriangulatorObj * tobj)
{
GLdouble d;
d = twice_the_triangle_area(va, vb, vc);
if (d < -EPSILON) {
return 1;
}
else if (d > EPSILON) {
return 0;
}
else {
return -1;
}
}
static GLboolean
diagonal_ccw(tess_vertex * va,
tess_vertex * vb,
GLUtriangulatorObj * tobj, tess_contour * contour)
{
tess_vertex *vc = va->next, *vertex, *shadow_vertex;
struct
{
GLdouble A, B, C;
}
ac, cb, ba;
GLdouble x, y;
GLint res = convex_ccw(va, vc, vb, tobj);
if (res == 0)
return GL_FALSE;
if (res == -1)
return GL_TRUE;
ba.A = vb->y - va->y;
ba.B = va->x - vb->x;
ba.C = -ba.A * va->x - ba.B * va->y;
ac.A = va->y - vc->y;
ac.B = vc->x - va->x;
ac.C = -ac.A * vc->x - ac.B * vc->y;
cb.A = vc->y - vb->y;
cb.B = vb->x - vc->x;
cb.C = -cb.A * vb->x - cb.B * vb->y;
for (vertex = vb->next; vertex != va; vertex = vertex->next) {
shadow_vertex = vertex->shadow_vertex;
if (shadow_vertex != NULL &&
(shadow_vertex == va || shadow_vertex == vb || shadow_vertex == vc))
continue;
x = vertex->x;
y = vertex->y;
if (left(ba.A, ba.B, ba.C, x, y) &&
left(ac.A, ac.B, ac.C, x, y) && left(cb.A, cb.B, cb.C, x, y))
return GL_FALSE;
}
return GL_TRUE;
}
static GLboolean
diagonal_cw(tess_vertex * va,
tess_vertex * vb,
GLUtriangulatorObj * tobj, tess_contour * contour)
{
tess_vertex *vc = va->next, *vertex, *shadow_vertex;
struct
{
GLdouble A, B, C;
}
ac, cb, ba;
GLdouble x, y;
GLint res = convex_cw(va, vc, vb, tobj);
if (res == 0)
return GL_FALSE;
if (res == -1)
return GL_TRUE;
ba.A = vb->y - va->y;
ba.B = va->x - vb->x;
ba.C = -ba.A * va->x - ba.B * va->y;
ac.A = va->y - vc->y;
ac.B = vc->x - va->x;
ac.C = -ac.A * vc->x - ac.B * vc->y;
cb.A = vc->y - vb->y;
cb.B = vb->x - vc->x;
cb.C = -cb.A * vb->x - cb.B * vb->y;
for (vertex = vb->next; vertex != va; vertex = vertex->next) {
shadow_vertex = vertex->shadow_vertex;
if (shadow_vertex != NULL &&
(shadow_vertex == va || shadow_vertex == vb || shadow_vertex == vc))
continue;
x = vertex->x;
y = vertex->y;
if (right(ba.A, ba.B, ba.C, x, y) &&
right(ac.A, ac.B, ac.C, x, y) && right(cb.A, cb.B, cb.C, x, y))
return GL_FALSE;
}
return GL_TRUE;
}
static void
clip_ear(GLUtriangulatorObj * tobj, tess_vertex * v, tess_contour * contour)
{
emit_triangle(tobj, v->previous, v, v->next);
/* the first in the list */
if (contour->vertices == v) {
contour->vertices = v->next;
contour->last_vertex->next = v->next;
v->next->previous = contour->last_vertex;
}
else
/* the last ? */
if (contour->last_vertex == v) {
contour->vertices->previous = v->previous;
v->previous->next = v->next;
contour->last_vertex = v->previous;
}
else {
v->next->previous = v->previous;
v->previous->next = v->next;
}
free(v);
--(contour->vertex_cnt);
}
static void
clip_ear_with_edge_flag(GLUtriangulatorObj * tobj,
tess_vertex * v, tess_contour * contour)
{
emit_triangle_with_edge_flag(tobj, v->previous, v->previous->edge_flag,
v, v->edge_flag, v->next, GL_FALSE);
v->previous->edge_flag = GL_FALSE;
/* the first in the list */
if (contour->vertices == v) {
contour->vertices = v->next;
contour->last_vertex->next = v->next;
v->next->previous = contour->last_vertex;
}
else
/* the last ? */
if (contour->last_vertex == v) {
contour->vertices->previous = v->previous;
v->previous->next = v->next;
contour->last_vertex = v->previous;
}
else {
v->next->previous = v->previous;
v->previous->next = v->next;
}
free(v);
--(contour->vertex_cnt);
}
static void
triangulate_ccw(GLUtriangulatorObj * tobj, tess_contour * contour)
{
tess_vertex *vertex;
GLuint vertex_cnt = contour->vertex_cnt;
while (vertex_cnt > 3) {
vertex = contour->vertices;
while (diagonal_ccw(vertex, vertex->next->next, tobj, contour) ==
GL_FALSE && tobj->error == GLU_NO_ERROR)
vertex = vertex->next;
if (tobj->error != GLU_NO_ERROR)
return;
clip_ear(tobj, vertex->next, contour);
--vertex_cnt;
}
}
static void
triangulate_cw(GLUtriangulatorObj * tobj, tess_contour * contour)
{
tess_vertex *vertex;
GLuint vertex_cnt = contour->vertex_cnt;
while (vertex_cnt > 3) {
vertex = contour->vertices;
while (diagonal_cw(vertex, vertex->next->next, tobj, contour) ==
GL_FALSE && tobj->error == GLU_NO_ERROR)
vertex = vertex->next;
if (tobj->error != GLU_NO_ERROR)
return;
clip_ear(tobj, vertex->next, contour);
--vertex_cnt;
}
}
static void
triangulate_ccw_with_edge_flag(GLUtriangulatorObj * tobj,
tess_contour * contour)
{
tess_vertex *vertex;
GLuint vertex_cnt = contour->vertex_cnt;
while (vertex_cnt > 3) {
vertex = contour->vertices;
while (diagonal_ccw(vertex, vertex->next->next, tobj, contour) ==
GL_FALSE && tobj->error == GLU_NO_ERROR)
vertex = vertex->next;
if (tobj->error != GLU_NO_ERROR)
return;
clip_ear_with_edge_flag(tobj, vertex->next, contour);
--vertex_cnt;
}
}
static void
triangulate_cw_with_edge_flag(GLUtriangulatorObj * tobj,
tess_contour * contour)
{
tess_vertex *vertex;
GLuint vertex_cnt = contour->vertex_cnt;
while (vertex_cnt > 3) {
vertex = contour->vertices;
while (diagonal_cw(vertex, vertex->next->next, tobj, contour) ==
GL_FALSE && tobj->error == GLU_NO_ERROR)
vertex = vertex->next;
if (tobj->error != GLU_NO_ERROR)
return;
clip_ear_with_edge_flag(tobj, vertex->next, contour);
--vertex_cnt;
}
}
void
tess_tesselate(GLUtriangulatorObj * tobj)
{
tess_contour *contour;
for (contour = tobj->contours; contour != NULL; contour = contour->next) {
if (contour->orientation == GLU_CCW) {
triangulate_ccw(tobj, contour);
}
else {
triangulate_cw(tobj, contour);
}
if (tobj->error != GLU_NO_ERROR)
return;
/* emit the last triangle */
emit_triangle(tobj, contour->vertices, contour->vertices->next,
contour->vertices->next->next);
}
}
void
tess_tesselate_with_edge_flag(GLUtriangulatorObj * tobj)
{
tess_contour *contour;
edge_flag = GL_TRUE;
/* first callback with edgeFlag set to GL_TRUE */
(tobj->callbacks.edgeFlag) (GL_TRUE);
for (contour = tobj->contours; contour != NULL; contour = contour->next) {
if (contour->orientation == GLU_CCW)
triangulate_ccw_with_edge_flag(tobj, contour);
else
triangulate_cw_with_edge_flag(tobj, contour);
if (tobj->error != GLU_NO_ERROR)
return;
/* emit the last triangle */
emit_triangle_with_edge_flag(tobj, contour->vertices,
contour->vertices->edge_flag,
contour->vertices->next,
contour->vertices->next->edge_flag,
contour->vertices->next->next,
contour->vertices->next->next->edge_flag);
}
}
static void
emit_triangle(GLUtriangulatorObj * tobj,
tess_vertex * v1, tess_vertex * v2, tess_vertex * v3)
{
(tobj->callbacks.begin) (GL_TRIANGLES);
(tobj->callbacks.vertex) (v1->data);
(tobj->callbacks.vertex) (v2->data);
(tobj->callbacks.vertex) (v3->data);
(tobj->callbacks.end) ();
}
static void
emit_triangle_with_edge_flag(GLUtriangulatorObj * tobj,
tess_vertex * v1,
GLboolean edge_flag1,
tess_vertex * v2,
GLboolean edge_flag2,
tess_vertex * v3, GLboolean edge_flag3)
{
(tobj->callbacks.begin) (GL_TRIANGLES);
if (edge_flag1 != edge_flag) {
edge_flag = (edge_flag == GL_TRUE ? GL_FALSE : GL_TRUE);
(tobj->callbacks.edgeFlag) (edge_flag);
}
(tobj->callbacks.vertex) (v1->data);
if (edge_flag2 != edge_flag) {
edge_flag = (edge_flag == GL_TRUE ? GL_FALSE : GL_TRUE);
(tobj->callbacks.edgeFlag) (edge_flag);
}
(tobj->callbacks.vertex) (v2->data);
if (edge_flag3 != edge_flag) {
edge_flag = (edge_flag == GL_TRUE ? GL_FALSE : GL_TRUE);
(tobj->callbacks.edgeFlag) (edge_flag);
}
(tobj->callbacks.vertex) (v3->data);
(tobj->callbacks.end) ();
}

View File

@@ -1,43 +1,11 @@
# Mesa 3-D graphics library
# Version: 4.0
#
# Copyright (C) 1999 Brian Paul All Rights Reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# DOS/DJGPP glut makefile v1.1 for Mesa 4.0
#
# Copyright (C) 2002 - Borca Daniel
# Email : dborca@yahoo.com
# Web : http://www.geocities.com/dborca
MESA = ../..
MARK = $(MESA)/src-glut
default: libglut.so.3.7 install
include $(MESA)/Makefile.include
.PHONY: all clean
TOP = ../..
MARK = $(TOP)/src-glut
LIBDIR = $(TOP)/lib
GLUT_LIB = libglut.so
CC = gcc
INCLUDES = -I$(TOP)/include -I$(MARK)
CFLAGS = -c -g $(INCLUDES) -MD
INCLUDES = -I$(MESA)/include -I$(MARK)
CORE_SOURCES = \
bitmap.c \
@@ -64,35 +32,19 @@ MARK_SOURCES = \
SOURCES = $(CORE_SOURCES) $(MARK_SOURCES)
OBJS = $(addsuffix .o,$(basename $(SOURCES)))
LIBS=-L$(TOP)/lib -lGL -lGLU -lm
.c.o:
$(CC) -o $@ -c $(CFLAGS) $<
.S.o:
$(CC) -o $@ -c $(CFLAGS) $<
default: libglut.so.3.7 install
OBJS = $(SOURCES:.c=.o)
LIBS = -L$(MESA)/lib -lGL -lGLU -lm
libglut.so.3.7: $(OBJS) Makefile
gcc -shared -Wl,-soname,libglut.so -Wl,-Bsymbolic $(OBJS) $(LIBS) -o $@
install:
rm -f $(TOP)/lib/libglut.so*
install -D libglut.so.3.7 $(TOP)/lib/libglut.so.3.7
ln -s libglut.so.3.7 $(TOP)/lib/libglut.so.3
ln -s libglut.so.3 $(TOP)/lib/libglut.so
clean:
rm -f *~ .*~ *.o libglut.so* *.d
rm -f $(MESA)/lib/libglut.so*
install -D libglut.so.3.7 $(MESA)/lib/libglut.so.3.7
ln -s libglut.so.3.7 $(MESA)/lib/libglut.so.3
ln -s libglut.so.3 $(MESA)/lib/libglut.so
-include $(SOURCES:.c=.d)
.SUFFIXES: .c .d
.c.d:
$(CC) -M $(INCLUDES) $< > $@

View File

@@ -12,8 +12,8 @@ glutBitmapCharacter(GLUTbitmapFont font, int c)
{
const BitmapCharRec *ch;
BitmapFontPtr fontinfo;
GLint swapbytes, lsbfirst, rowlength;
GLint skiprows, skippixels, alignment;
GLfloat swapbytes, lsbfirst, rowlength;
GLfloat skiprows, skippixels, alignment;
#if defined(_WIN32)
fontinfo = (BitmapFontPtr) __glutFont(font);
@@ -27,30 +27,30 @@ glutBitmapCharacter(GLUTbitmapFont font, int c)
ch = fontinfo->ch[c - fontinfo->first];
if (ch) {
/* Save current modes. */
glGetIntegerv(GL_UNPACK_SWAP_BYTES, &swapbytes);
glGetIntegerv(GL_UNPACK_LSB_FIRST, &lsbfirst);
glGetIntegerv(GL_UNPACK_ROW_LENGTH, &rowlength);
glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skiprows);
glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skippixels);
glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment);
/* glGetFloatv(GL_UNPACK_SWAP_BYTES, &swapbytes); */
/* glGetFloatv(GL_UNPACK_LSB_FIRST, &lsbfirst); */
/* glGetFloatv(GL_UNPACK_ROW_LENGTH, &rowlength); */
/* glGetFloatv(GL_UNPACK_SKIP_ROWS, &skiprows); */
/* glGetFloatv(GL_UNPACK_SKIP_PIXELS, &skippixels); */
glGetFloatv(GL_UNPACK_ALIGNMENT, &alignment);
/* Little endian machines (DEC Alpha for example) could
benefit from setting GL_UNPACK_LSB_FIRST to GL_TRUE
instead of GL_FALSE, but this would require changing the
generated bitmaps too. */
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
/* glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); */
/* glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE); */
/* glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); */
/* glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); */
/* glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); */
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glBitmap(ch->width, ch->height, ch->xorig, ch->yorig,
ch->advance, 0, ch->bitmap);
/* Restore saved modes. */
glPixelStorei(GL_UNPACK_SWAP_BYTES, swapbytes);
glPixelStorei(GL_UNPACK_LSB_FIRST, lsbfirst);
glPixelStorei(GL_UNPACK_ROW_LENGTH, rowlength);
glPixelStorei(GL_UNPACK_SKIP_ROWS, skiprows);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, skippixels);
glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
/* glPixelStorei(GL_UNPACK_SWAP_BYTES, swapbytes); */
/* glPixelStorei(GL_UNPACK_LSB_FIRST, (int)lsbfirst); */
/* glPixelStorei(GL_UNPACK_ROW_LENGTH, (int)rowlength); */
/* glPixelStorei(GL_UNPACK_SKIP_ROWS, skiprows); */
/* glPixelStorei(GL_UNPACK_SKIP_PIXELS, skippixels); */
glPixelStorei(GL_UNPACK_ALIGNMENT, (int)alignment);
}
}

View File

@@ -40,9 +40,6 @@ void APIENTRY glutInit (int *argcp, char **argv)
void APIENTRY glutInitDisplayMode (unsigned int mode)
{
g_display_mode = mode;
/* pc_install_keyb(); */
/* g_mouse = pc_install_mouse(); */
}
@@ -60,103 +57,3 @@ void APIENTRY glutInitWindowSize (int width, int height)
}
void APIENTRY glutMainLoop (void)
{
GLboolean idle;
static int old_mouse_x = 0;
static int old_mouse_y = 0;
static int old_mouse_b = 0;
glutPostRedisplay();
if (reshape_func) reshape_func(g_width, g_height);
if (visibility_func) visibility_func(GLUT_VISIBLE);
/* if (g_mouse) pc_show_mouse(); */
while (GL_TRUE) {
idle = GL_TRUE;
if (g_redisplay && display_func) {
idle = GL_FALSE;
g_redisplay = GL_FALSE;
/* if (g_mouse && !(g_display_mode & GLUT_DOUBLE)) pc_scare_mouse(); */
display_func();
/* if (g_mouse && !(g_display_mode & GLUT_DOUBLE)) pc_unscare_mouse(); */
}
#if 0
if (pc_keypressed()) {
int key;
idle = GL_FALSE;
key = pc_readkey();
switch (key>>16) {
case KEY_F1: if (special_func) special_func(GLUT_KEY_F1, 0, 0); break;
case KEY_F2: if (special_func) special_func(GLUT_KEY_F2, 0, 0); break;
case KEY_F3: if (special_func) special_func(GLUT_KEY_F3, 0, 0); break;
case KEY_F4: if (special_func) special_func(GLUT_KEY_F4, 0, 0); break;
case KEY_F5: if (special_func) special_func(GLUT_KEY_F5, 0, 0); break;
case KEY_F6: if (special_func) special_func(GLUT_KEY_F6, 0, 0); break;
case KEY_F7: if (special_func) special_func(GLUT_KEY_F7, 0, 0); break;
case KEY_F8: if (special_func) special_func(GLUT_KEY_F8, 0, 0); break;
case KEY_F9: if (special_func) special_func(GLUT_KEY_F9, 0, 0); break;
case KEY_F10: if (special_func) special_func(GLUT_KEY_F10, 0, 0); break;
case KEY_F11: if (special_func) special_func(GLUT_KEY_F11, 0, 0); break;
case KEY_F12: if (special_func) special_func(GLUT_KEY_F12, 0, 0); break;
case KEY_LEFT: if (special_func) special_func(GLUT_KEY_LEFT, 0, 0); break;
case KEY_UP: if (special_func) special_func(GLUT_KEY_UP, 0, 0); break;
case KEY_RIGHT: if (special_func) special_func(GLUT_KEY_RIGHT, 0, 0); break;
case KEY_DOWN: if (special_func) special_func(GLUT_KEY_DOWN, 0, 0); break;
case KEY_PGUP: if (special_func) special_func(GLUT_KEY_PAGE_UP, 0, 0); break;
case KEY_PGDN: if (special_func) special_func(GLUT_KEY_PAGE_DOWN, 0, 0); break;
case KEY_HOME: if (special_func) special_func(GLUT_KEY_HOME, 0, 0); break;
case KEY_END: if (special_func) special_func(GLUT_KEY_END, 0, 0); break;
case KEY_INSERT: if (special_func) special_func(GLUT_KEY_INSERT, 0, 0); break;
default: if (keyboard_func) keyboard_func(key & 0xFF, 0, 0);
}
}
if (g_mouse) {
int mouse_x;
int mouse_y;
int mouse_b;
mouse_b = pc_query_mouse(&mouse_x, &mouse_y);
if (motion_func && ((mouse_x != old_mouse_x) || (mouse_y != old_mouse_y))) {
idle = GL_FALSE;
old_mouse_x = mouse_x;
old_mouse_y = mouse_y;
motion_func(old_mouse_x, old_mouse_y);
}
if (mouse_func && (mouse_b != old_mouse_b)) {
int new_mouse_b = mouse_b;
if ((old_mouse_b & 1) && !(new_mouse_b & 1))
mouse_func(GLUT_LEFT_BUTTON, GLUT_UP, mouse_x, mouse_y);
else if (!(old_mouse_b & 1) && (new_mouse_b & 1))
mouse_func(GLUT_LEFT_BUTTON, GLUT_DOWN, mouse_x, mouse_y);
if ((old_mouse_b & 2) && !(new_mouse_b & 2))
mouse_func(GLUT_RIGHT_BUTTON, GLUT_UP, mouse_x, mouse_y);
else if (!(old_mouse_b & 2) && (new_mouse_b & 2))
mouse_func(GLUT_RIGHT_BUTTON, GLUT_DOWN, mouse_x, mouse_y);
if ((old_mouse_b & 4) && !(new_mouse_b & 4))
mouse_func(GLUT_MIDDLE_BUTTON, GLUT_UP, mouse_x, mouse_y);
else if (!(old_mouse_b & 3) && (new_mouse_b & 4))
mouse_func(GLUT_MIDDLE_BUTTON, GLUT_DOWN, mouse_x, mouse_y);
idle = GL_FALSE;
old_mouse_b = new_mouse_b;
}
}
#endif
if (idle && idle_func)
idle_func();
}
}

View File

@@ -152,7 +152,7 @@ drawBox(GLfloat size, GLenum type)
for (i = 5; i >= 0; i--) {
glBegin(type);
glNormal3fv(&n[i][0]);
/* glNormal3fv(&n[i][0]); */
glVertex3fv(&v[faces[i][0]][0]);
glVertex3fv(&v[faces[i][1]][0]);
glVertex3fv(&v[faces[i][2]][0]);
@@ -205,9 +205,9 @@ doughnut(GLfloat r, GLfloat R, GLint nsides, GLint rings)
sinPhi = sin(phi);
dist = R + r * cosPhi;
glNormal3f(cosTheta1 * cosPhi, -sinTheta1 * cosPhi, sinPhi);
/* glNormal3f(cosTheta1 * cosPhi, -sinTheta1 * cosPhi, sinPhi); */
glVertex3f(cosTheta1 * dist, -sinTheta1 * dist, r * sinPhi);
glNormal3f(cosTheta * cosPhi, -sinTheta * cosPhi, sinPhi);
/* glNormal3f(cosTheta * cosPhi, -sinTheta * cosPhi, sinPhi); */
glVertex3f(cosTheta * dist, -sinTheta * dist, r * sinPhi);
}
glEnd();
@@ -222,10 +222,10 @@ void APIENTRY
glutWireTorus(GLdouble innerRadius, GLdouble outerRadius,
GLint nsides, GLint rings)
{
glPushAttrib(GL_POLYGON_BIT);
/* glPushAttrib(GL_POLYGON_BIT); */
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
doughnut(innerRadius, outerRadius, nsides, rings);
glPopAttrib();
/* glPopAttrib(); */
}
void APIENTRY
@@ -318,7 +318,7 @@ pentagon(int a, int b, int c, int d, int e, GLenum shadeType)
normalize(n0);
glBegin(shadeType);
glNormal3fv(n0);
/* glNormal3fv(n0); */
glVertex3fv(&dodec[a][0]);
glVertex3fv(&dodec[b][0]);
glVertex3fv(&dodec[c][0]);
@@ -377,7 +377,7 @@ recorditem(GLfloat * n1, GLfloat * n2, GLfloat * n3,
normalize(q1);
glBegin(shadeType);
glNormal3fv(q1);
/* glNormal3fv(q1); */
glVertex3fv(n1);
glVertex3fv(n2);
glVertex3fv(n3);

View File

@@ -143,6 +143,7 @@ teapot(GLint grid, GLdouble scale, GLenum type)
float p[4][4][3], q[4][4][3], r[4][4][3], s[4][4][3];
long i, j, k, l;
#if 0
glPushAttrib(GL_ENABLE_BIT | GL_EVAL_BIT);
glEnable(GL_AUTO_NORMAL);
glEnable(GL_NORMALIZE);
@@ -194,6 +195,7 @@ teapot(GLint grid, GLdouble scale, GLenum type)
}
glPopMatrix();
glPopAttrib();
#endif
}
/* CENTRY */

View File

@@ -218,3 +218,50 @@ void APIENTRY glutShowWindow (void)
void APIENTRY glutHideWindow (void)
{
}
void APIENTRY glutMainLoop (void)
{
GLboolean idle;
GLboolean have_event;
XEvent evt;
glutPostRedisplay();
if (reshape_func) reshape_func(g_width, g_height);
while (GL_TRUE) {
idle = GL_TRUE;
if (idle_func)
have_event = XCheckWindowEvent( dpy, win, ~0, &evt );
else
have_event = XNextEvent( dpy, &evt );
if (have_event) {
fprintf(stderr, "got event type %d\n", evt.type);
idle = GL_FALSE;
switch(evt.type) {
case MapNotify:
if (visibility_func) visibility_func(GLUT_VISIBLE);
break;
case UnmapNotify:
if (visibility_func) visibility_func(GLUT_NOT_VISIBLE);
break;
case Expose:
g_redisplay = 1;
break;
}
}
if (g_redisplay && display_func) {
idle = GL_FALSE;
g_redisplay = GL_FALSE;
display_func();
}
if (idle && idle_func) {
idle_func();
}
}
}

View File

@@ -0,0 +1,134 @@
# $Id: Makefile,v 1.1.2.1 2003/03/10 11:23:04 keithw Exp $
# Mesa 3-D graphics library
# Version: 5.0
# Copyright (C) 1995-2002 Brian Paul
MESA = ../../..
default: r200_dri.so
include $(MESA)/Makefile.include
SHARED_INCLUDES= -I$(MESABUILDDIR) -I$(MESA)/include -I. -I../common -Iserver
MINIGLX_INCLUDES = -I$(MESABUILDDIR)/miniglx
DRI_INCLUDES = -I$(MESABUILDDIR)/dri
ifeq ($(FULL_DRIVER),true)
DEFINES = \
-DGLX_DIRECT_RENDERING \
-Dlinux -D__i386__ -D_POSIX_C_SOURCE=199309L -D_POSIX_SOURCE -D_XOPEN_SOURCE -D_BSD_SOURCE -D_SVID_SOURCE -D_GNU_SOURCE -DFUNCPROTO=15 -DNARROWPROTO -DXTHREADS -D_REENTRANT -DXUSE_MTSAFE_API -DMALLOC_0_RETURNS_NULL -DGLXEXT -DXF86DRI -DGLX_DIRECT_RENDERING -DGLX_USE_DLOPEN -DGLX_USE_MESA -DX_BYTE_ORDER=X_LITTLE_ENDIAN \
-D_HAVE_SWRAST=1 \
-D_HAVE_SWTNL=1 \
-D_HAVE_SANITY=1 \
-D_HAVE_CODEGEN=1 \
-D_HAVE_LIGHTING=1 \
-D_HAVE_TEXGEN=1 \
-D_HAVE_USERCLIP=1 \
-D_HAVE_FULL_GL=1
else
DEFINES = \
-D_HAVE_SWRAST=0 \
-D_HAVE_SWTNL=0 \
-D_HAVE_SANITY=0 \
-D_HAVE_CODEGEN=0 \
-D_HAVE_LIGHTING=0 \
-D_HAVE_TEXGEN=0 \
-D_HAVE_USERCLIP=0 \
-D_HAVE_FULL_GL=0
endif
# The .a files for each mesa module required by this driver:
#
FULL_MESA = $(MESABUILDDIR)/swrast_setup/swrast_setup.a \
$(MESABUILDDIR)/tnl/tnl.a \
$(MESABUILDDIR)/math/math.a \
$(MESABUILDDIR)/array_cache/array_cache.a \
$(MESABUILDDIR)/swrast/swrast.a \
$(MESABUILDDIR)/mesa.a \
$(MESABUILDDIR)/math/math.a #kludge
SUBSET_MESA = $(MESABUILDDIR)/mesa.a \
$(MESABUILDDIR)/math/m_matrix.o
MINIGLX_SOURCES = server/radeon_dri.c
DRIVER_SOURCES = r200_context.c \
r200_ioctl.c \
r200_lock.c \
r200_screen.c \
r200_state.c \
r200_state_init.c \
../common/mm.c
SUBSET_DRIVER_SOURCES = \
r200_subset_bitmap.c \
r200_subset_readpix.c \
r200_subset_select.c \
r200_subset_tex.c \
r200_subset_vtx.c
FULL_DRIVER_SOURCES = \
r200_cmdbuf.c \
r200_pixel.c \
r200_tex.c \
r200_texmem.c \
r200_texstate.c \
r200_tcl.c \
r200_swtcl.c \
r200_span.c \
r200_maos.c \
r200_sanity.c \
r200_vtxfmt.c \
r200_vtxfmt_c.c \
r200_vtxfmt_sse.c \
r200_vtxfmt_x86.c
INCLUDES = $(MINIGLX_INCLUDES) \
$(SHARED_INCLUDES)
ifeq ($(FULL_DRIVER),true)
C_SOURCES = $(DRIVER_SOURCES) \
$(FULL_DRIVER_SOURCES) \
$(MINIGLX_SOURCES)
MESA_MODULES = $(FULL_MESA)
else
C_SOURCES = $(DRIVER_SOURCES) \
$(SUBSET_DRIVER_SOURCES) \
$(MINIGLX_SOURCES)
MESA_MODULES = $(SUBSET_MESA)
endif
ifeq ($(WINDOW_SYSTEM),dri)
WINOBJ=$(MESABUILDDIR)/dri/dri.a
WINLIB=
else
WINOBJ=
WINLIB=-L$(MESA)/src/miniglx
endif
ASM_SOURCES =
OBJECTS = $(C_SOURCES:.c=.o) \
$(ASM_SOURCES:.S=.o)
##### TARGETS #####
# Build the subset or full driver?
#
r200_dri.so: $(OBJECTS) $(MESA_MODULES) $(WINOBJ) Makefile
rm -f $@ && gcc -o $@ -shared $(OBJECTS) $(MESA_MODULES) $(WINOBJ) $(WINLIB) -lGL -lc -lm -Wl,-rpath,../../../lib
rm -f $(MESA)/lib/r200_dri.so && \
install r200_dri.so $(MESA)/lib/r200_dri.so
##### DEPENDENCIES #####
-include $(C_SOURCES:.c=.d)

View File

@@ -0,0 +1,344 @@
/* $XFree86$ */
/*
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
The Weather Channel (TM) funded Tungsten Graphics to develop the
initial release of the Radeon 8500 driver under the XFree86 license.
This notice must be preserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#include "glheader.h"
#include "imports.h"
#include "macros.h"
#include "context.h"
#include "swrast/swrast.h"
#include "simple_list.h"
#include "r200_context.h"
#include "r200_state.h"
#include "r200_ioctl.h"
#include "r200_tcl.h"
#include "r200_sanity.h"
#include "radeon_reg.h"
static void print_state_atom( struct r200_state_atom *state )
{
int i;
fprintf(stderr, "emit %s/%d\n", state->name, state->cmd_size);
if (0 & R200_DEBUG & DEBUG_VERBOSE)
for (i = 0 ; i < state->cmd_size ; i++)
fprintf(stderr, "\t%s[%d]: %x\n", state->name, i, state->cmd[i]);
}
static void r200_emit_state_list( r200ContextPtr rmesa,
struct r200_state_atom *list )
{
struct r200_state_atom *state, *tmp;
char *dest;
foreach_s( state, tmp, list ) {
if (state->check( rmesa->glCtx, state->idx )) {
dest = r200AllocCmdBuf( rmesa, state->cmd_size * 4, __FUNCTION__);
memcpy( dest, state->cmd, state->cmd_size * 4);
move_to_head( &(rmesa->hw.clean), state );
if (R200_DEBUG & DEBUG_STATE)
print_state_atom( state );
}
else if (R200_DEBUG & DEBUG_STATE)
fprintf(stderr, "skip state %s\n", state->name);
}
}
void r200EmitState( r200ContextPtr rmesa )
{
struct r200_state_atom *state, *tmp;
if (R200_DEBUG & (DEBUG_STATE|DEBUG_PRIMS))
fprintf(stderr, "%s\n", __FUNCTION__);
/* Somewhat overkill:
*/
if ( rmesa->lost_context) {
if (R200_DEBUG & (DEBUG_STATE|DEBUG_PRIMS|DEBUG_IOCTL))
fprintf(stderr, "%s - lost context\n", __FUNCTION__);
foreach_s( state, tmp, &(rmesa->hw.clean) )
move_to_tail(&(rmesa->hw.dirty), state );
rmesa->lost_context = 0;
}
else {
move_to_tail( &rmesa->hw.dirty, &rmesa->hw.mtl[0] );
/* odd bug? -- isosurf, cycle between reflect & lit */
}
r200_emit_state_list( rmesa, &rmesa->hw.dirty );
}
/* Fire a section of the retained (indexed_verts) buffer as a regular
* primtive.
*/
extern void r200EmitVbufPrim( r200ContextPtr rmesa,
GLuint primitive,
GLuint vertex_nr )
{
drmRadeonCmdHeader *cmd;
assert(!(primitive & R200_VF_PRIM_WALK_IND));
r200EmitState( rmesa );
if (R200_DEBUG & (DEBUG_IOCTL|DEBUG_PRIMS))
fprintf(stderr, "%s cmd_used/4: %d prim %x nr %d\n", __FUNCTION__,
rmesa->store.cmd_used/4, primitive, vertex_nr);
cmd = (drmRadeonCmdHeader *)r200AllocCmdBuf( rmesa, 3 * sizeof(*cmd),
__FUNCTION__ );
cmd[0].i = 0;
cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP;
cmd[1].i = R200_CP_CMD_3D_DRAW_VBUF_2;
cmd[2].i = (primitive |
R200_VF_PRIM_WALK_LIST |
R200_VF_COLOR_ORDER_RGBA |
(vertex_nr << R200_VF_VERTEX_NUMBER_SHIFT));
if (R200_DEBUG & DEBUG_SYNC) {
fprintf(stderr, "\nSyncing\n\n");
R200_FIREVERTICES( rmesa );
r200Finish( rmesa->glCtx );
}
}
void r200FlushElts( r200ContextPtr rmesa )
{
int *cmd = (int *)(rmesa->store.cmd_buf + rmesa->store.elts_start);
int dwords;
int nr = (rmesa->store.cmd_used - (rmesa->store.elts_start + 12)) / 2;
if (R200_DEBUG & (DEBUG_IOCTL|DEBUG_PRIMS))
fprintf(stderr, "%s\n", __FUNCTION__);
assert( rmesa->dma.flush == r200FlushElts );
rmesa->dma.flush = 0;
/* Cope with odd number of elts:
*/
rmesa->store.cmd_used = (rmesa->store.cmd_used + 2) & ~2;
dwords = (rmesa->store.cmd_used - rmesa->store.elts_start) / 4;
cmd[1] |= (dwords - 3) << 16;
cmd[2] |= nr << R200_VF_VERTEX_NUMBER_SHIFT;
if (R200_DEBUG & DEBUG_SYNC) {
fprintf(stderr, "\nSyncing in %s\n\n", __FUNCTION__);
R200_FIREVERTICES( rmesa );
r200Finish( rmesa->glCtx );
}
}
GLushort *r200AllocEltsOpenEnded( r200ContextPtr rmesa,
GLuint primitive,
GLuint min_nr )
{
drmRadeonCmdHeader *cmd;
GLushort *retval;
if (R200_DEBUG & DEBUG_IOCTL)
fprintf(stderr, "%s %d prim %x\n", __FUNCTION__, min_nr, primitive);
assert((primitive & R200_VF_PRIM_WALK_IND));
r200EmitState( rmesa );
cmd = (drmRadeonCmdHeader *)r200AllocCmdBuf( rmesa,
12 + min_nr*2,
__FUNCTION__ );
cmd[0].i = 0;
cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP;
cmd[1].i = R200_CP_CMD_3D_DRAW_INDX_2;
cmd[2].i = (primitive |
R200_VF_PRIM_WALK_IND |
R200_VF_COLOR_ORDER_RGBA);
retval = (GLushort *)(cmd+3);
if (R200_DEBUG & DEBUG_PRIMS)
fprintf(stderr, "%s: header 0x%x prim %x \n",
__FUNCTION__,
cmd[1].i, primitive);
assert(!rmesa->dma.flush);
rmesa->dma.flush = r200FlushElts;
rmesa->store.elts_start = ((char *)cmd) - rmesa->store.cmd_buf;
return retval;
}
void r200EmitVertexAOS( r200ContextPtr rmesa,
GLuint vertex_size,
GLuint offset )
{
drmRadeonCmdHeader *cmd;
if (R200_DEBUG & (DEBUG_PRIMS|DEBUG_IOCTL))
fprintf(stderr, "%s: vertex_size 0x%x offset 0x%x \n",
__FUNCTION__, vertex_size, offset);
cmd = (drmRadeonCmdHeader *)r200AllocCmdBuf( rmesa, 5 * sizeof(int),
__FUNCTION__ );
cmd[0].header.cmd_type = RADEON_CMD_PACKET3;
cmd[1].i = R200_CP_CMD_3D_LOAD_VBPNTR | (2 << 16);
cmd[2].i = 1;
cmd[3].i = vertex_size | (vertex_size << 8);
cmd[4].i = offset;
}
void r200EmitAOS( r200ContextPtr rmesa,
struct r200_dma_region **component,
GLuint nr,
GLuint offset )
{
drmRadeonCmdHeader *cmd;
int sz = 3 + ((nr/2)*3) + ((nr&1)*2);
int i;
int *tmp;
if (R200_DEBUG & DEBUG_IOCTL)
fprintf(stderr, "%s nr arrays: %d\n", __FUNCTION__, nr);
cmd = (drmRadeonCmdHeader *)r200AllocCmdBuf( rmesa, sz * sizeof(int),
__FUNCTION__ );
cmd[0].i = 0;
cmd[0].header.cmd_type = RADEON_CMD_PACKET3;
cmd[1].i = R200_CP_CMD_3D_LOAD_VBPNTR | ((sz-3) << 16);
cmd[2].i = nr;
tmp = &cmd[0].i;
cmd += 3;
for (i = 0 ; i < nr ; i++) {
if (i & 1) {
cmd[0].i |= ((component[i]->aos_stride << 24) |
(component[i]->aos_size << 16));
cmd[2].i = (component[i]->aos_start +
offset * component[i]->aos_stride * 4);
cmd += 3;
}
else {
cmd[0].i = ((component[i]->aos_stride << 8) |
(component[i]->aos_size << 0));
cmd[1].i = (component[i]->aos_start +
offset * component[i]->aos_stride * 4);
}
}
if (R200_DEBUG & DEBUG_VERTS) {
fprintf(stderr, "%s:\n", __FUNCTION__);
for (i = 0 ; i < sz ; i++)
fprintf(stderr, " %d: %x\n", i, tmp[i]);
}
}
void r200EmitBlit( r200ContextPtr rmesa,
GLuint color_fmt,
GLuint src_pitch,
GLuint src_offset,
GLuint dst_pitch,
GLuint dst_offset,
GLint srcx, GLint srcy,
GLint dstx, GLint dsty,
GLuint w, GLuint h )
{
drmRadeonCmdHeader *cmd;
if (R200_DEBUG & DEBUG_IOCTL)
fprintf(stderr, "%s src %x/%x %d,%d dst: %x/%x %d,%d sz: %dx%d\n",
__FUNCTION__,
src_pitch, src_offset, srcx, srcy,
dst_pitch, dst_offset, dstx, dsty,
w, h);
assert( (src_pitch & 63) == 0 );
assert( (dst_pitch & 63) == 0 );
assert( (src_offset & 1023) == 0 );
assert( (dst_offset & 1023) == 0 );
assert( w < (1<<16) );
assert( h < (1<<16) );
cmd = (drmRadeonCmdHeader *)r200AllocCmdBuf( rmesa, 8 * sizeof(int),
__FUNCTION__ );
cmd[0].header.cmd_type = RADEON_CMD_PACKET3;
cmd[1].i = R200_CP_CMD_BITBLT_MULTI | (5 << 16);
cmd[2].i = (RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
RADEON_GMC_DST_PITCH_OFFSET_CNTL |
RADEON_GMC_BRUSH_NONE |
(color_fmt << 8) |
RADEON_GMC_SRC_DATATYPE_COLOR |
RADEON_ROP3_S |
RADEON_DP_SRC_SOURCE_MEMORY |
RADEON_GMC_CLR_CMP_CNTL_DIS |
RADEON_GMC_WR_MSK_DIS );
cmd[3].i = ((src_pitch/64)<<22) | (src_offset >> 10);
cmd[4].i = ((dst_pitch/64)<<22) | (dst_offset >> 10);
cmd[5].i = (srcx << 16) | srcy;
cmd[6].i = (dstx << 16) | dsty; /* dst */
cmd[7].i = (w << 16) | h;
}
void r200EmitWait( r200ContextPtr rmesa, GLuint flags )
{
if (rmesa->dri.drmMinor >= 6) {
drmRadeonCmdHeader *cmd;
assert( !(flags & ~(RADEON_WAIT_2D|RADEON_WAIT_3D)) );
cmd = (drmRadeonCmdHeader *)r200AllocCmdBuf( rmesa, 1 * sizeof(int),
__FUNCTION__ );
cmd[0].i = 0;
cmd[0].wait.cmd_type = RADEON_CMD_WAIT;
cmd[0].wait.flags = flags;
}
}

View File

@@ -0,0 +1,673 @@
/* $XFree86$ */
/*
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
The Weather Channel (TM) funded Tungsten Graphics to develop the
initial release of the Radeon 8500 driver under the XFree86 license.
This notice must be preserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#include "glheader.h"
#include "api_arrayelt.h"
#include "context.h"
#include "simple_list.h"
#include "imports.h"
#include "matrix.h"
#include "state.h"
#include "extensions.h"
#include "state.h"
#include "swrast/swrast.h"
#include "swrast_setup/swrast_setup.h"
#include "array_cache/acache.h"
#include "tnl/tnl.h"
#include "tnl/t_pipeline.h"
#include "r200_context.h"
#include "r200_ioctl.h"
#include "r200_state.h"
#include "r200_span.h"
#include "r200_pixel.h"
#include "r200_tex.h"
#include "r200_swtcl.h"
#include "r200_tcl.h"
#include "r200_vtxfmt.h"
#include "r200_maos.h"
#if defined(USE_X86_ASM)
#include "X86/common_x86_asm.h"
#endif
#define R200_DATE "20021125"
#ifndef R200_DEBUG
int R200_DEBUG = (0);
#endif
/* Return the width and height of the given buffer.
*/
static void r200GetBufferSize( GLframebuffer *buffer,
GLuint *width, GLuint *height )
{
GET_CURRENT_CONTEXT(ctx);
r200ContextPtr rmesa = R200_CONTEXT(ctx);
LOCK_HARDWARE( rmesa );
*width = rmesa->dri.drawable->w;
*height = rmesa->dri.drawable->h;
UNLOCK_HARDWARE( rmesa );
}
/* Return various strings for glGetString().
*/
static const GLubyte *r200GetString( GLcontext *ctx, GLenum name )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
static char buffer[128];
switch ( name ) {
case GL_VENDOR:
return (GLubyte *)"Tungsten Graphics, Inc.";
case GL_RENDERER:
sprintf( buffer, "Mesa DRI R200 " R200_DATE);
/* Append any chipset-specific information. None yet.
*/
/* Append any AGP-specific information.
*/
switch ( rmesa->r200Screen->AGPMode ) {
case 1:
strncat( buffer, " AGP 1x", 7 );
break;
case 2:
strncat( buffer, " AGP 2x", 7 );
break;
case 4:
strncat( buffer, " AGP 4x", 7 );
break;
}
/* Append any CPU-specific information.
*/
#ifdef USE_X86_ASM
if ( _mesa_x86_cpu_features ) {
strncat( buffer, " x86", 4 );
}
#ifdef USE_MMX_ASM
if ( cpu_has_mmx ) {
strncat( buffer, "/MMX", 4 );
}
#endif
#ifdef USE_3DNOW_ASM
if ( cpu_has_3dnow ) {
strncat( buffer, "/3DNow!", 7 );
}
#endif
#ifdef USE_SSE_ASM
if ( cpu_has_xmm ) {
strncat( buffer, "/SSE", 4 );
}
#endif
#endif
if ( !(rmesa->TclFallback & R200_TCL_FALLBACK_TCL_DISABLE) ) {
strncat( buffer, " TCL", 4 );
}
else {
strncat( buffer, " NO-TCL", 7 );
}
return (GLubyte *)buffer;
default:
return NULL;
}
}
/* Initialize the extensions supported by this driver.
*/
static void r200InitExtensions( GLcontext *ctx, r200ScreenPtr r200Screen )
{
_mesa_enable_imaging_extensions( ctx );
_mesa_enable_extension( ctx, "GL_ARB_multitexture" );
if (r200Screen->drmSupportsCubeMaps)
_mesa_enable_extension( ctx, "GL_ARB_texture_cube_map" );
_mesa_enable_extension( ctx, "GL_ARB_texture_env_add" );
_mesa_enable_extension( ctx, "GL_ARB_texture_env_combine" );
_mesa_enable_extension( ctx, "GL_ARB_texture_env_dot3" );
_mesa_enable_extension( ctx, "GL_ARB_texture_mirrored_repeat" );
_mesa_enable_extension( ctx, "GL_ARB_texture_border_clamp" );
_mesa_enable_extension( ctx, "GL_ATI_texture_env_combine3" );
_mesa_enable_extension( ctx, "GL_ATI_texture_mirror_once" );
_mesa_enable_extension( ctx, "GL_EXT_blend_logic_op" );
/*_mesa_enable_extension( ctx, "GL_EXT_fog_coord" );*/
_mesa_enable_extension( ctx, "GL_EXT_stencil_wrap" );
_mesa_enable_extension( ctx, "GL_EXT_texture_edge_clamp" );
_mesa_enable_extension( ctx, "GL_EXT_texture_env_add" );
_mesa_enable_extension( ctx, "GL_EXT_texture_env_combine" );
_mesa_enable_extension( ctx, "GL_EXT_texture_env_dot3" );
_mesa_enable_extension( ctx, "GL_EXT_texture_filter_anisotropic" );
_mesa_enable_extension( ctx, "GL_EXT_texture_lod_bias" );
_mesa_enable_extension( ctx, "GL_EXT_secondary_color" );
_mesa_enable_extension( ctx, "GL_EXT_blend_subtract" );
_mesa_enable_extension( ctx, "GL_EXT_blend_minmax" );
/* _mesa_enable_extension( ctx, "GL_EXT_fog_coord" ); */
_mesa_enable_extension( ctx, "GL_MESA_pack_invert" );
_mesa_enable_extension( ctx, "GL_MESA_ycbcr_texture" );
_mesa_enable_extension( ctx, "GL_NV_texture_rectangle" );
}
extern const struct gl_pipeline_stage _r200_render_stage;
extern const struct gl_pipeline_stage _r200_tcl_stage;
static const struct gl_pipeline_stage *r200_pipeline[] = {
/* Try and go straight to t&l
*/
&_r200_tcl_stage,
/* Catch any t&l fallbacks
*/
&_tnl_vertex_transform_stage,
&_tnl_normal_transform_stage,
&_tnl_lighting_stage,
&_tnl_fog_coordinate_stage,
&_tnl_texgen_stage,
&_tnl_texture_transform_stage,
/* Try again to go to tcl?
* - no good for asymmetric-twoside (do with multipass)
* - no good for asymmetric-unfilled (do with multipass)
* - good for material
* - good for texgen
* - need to manipulate a bit of state
*
* - worth it/not worth it?
*/
/* Else do them here.
*/
&_r200_render_stage,
&_tnl_render_stage, /* FALLBACK: */
0,
};
/* Initialize the driver's misc functions.
*/
static void r200InitDriverFuncs( GLcontext *ctx )
{
ctx->Driver.GetBufferSize = r200GetBufferSize;
ctx->Driver.ResizeBuffers = _swrast_alloc_buffers;
ctx->Driver.GetString = r200GetString;
ctx->Driver.Error = NULL;
ctx->Driver.DrawPixels = NULL;
ctx->Driver.Bitmap = NULL;
}
static void add_debug_flags( const char *debug )
{
if (strstr(debug, "fall"))
R200_DEBUG |= DEBUG_FALLBACKS;
if (strstr(debug, "tex"))
R200_DEBUG |= DEBUG_TEXTURE;
if (strstr(debug, "ioctl"))
R200_DEBUG |= DEBUG_IOCTL;
if (strstr(debug, "prim"))
R200_DEBUG |= DEBUG_PRIMS;
if (strstr(debug, "vert"))
R200_DEBUG |= DEBUG_VERTS;
if (strstr(debug, "state"))
R200_DEBUG |= DEBUG_STATE;
if (strstr(debug, "code"))
R200_DEBUG |= DEBUG_CODEGEN;
if (strstr(debug, "vfmt") || strstr(debug, "vtxf"))
R200_DEBUG |= DEBUG_VFMT;
if (strstr(debug, "verb"))
R200_DEBUG |= DEBUG_VERBOSE;
if (strstr(debug, "dri"))
R200_DEBUG |= DEBUG_DRI;
if (strstr(debug, "dma"))
R200_DEBUG |= DEBUG_DMA;
if (strstr(debug, "san"))
R200_DEBUG |= DEBUG_SANITY;
if (strstr(debug, "sync"))
R200_DEBUG |= DEBUG_SYNC;
if (strstr(debug, "pix"))
R200_DEBUG |= DEBUG_PIXEL;
if (strstr(debug, "mem"))
R200_DEBUG |= DEBUG_MEMORY;
}
/* Create the device specific context.
*/
GLboolean r200CreateContext( const __GLcontextModes *glVisual,
__DRIcontextPrivate *driContextPriv,
void *sharedContextPrivate)
{
__DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
r200ScreenPtr r200Screen = (r200ScreenPtr)(sPriv->private);
r200ContextPtr rmesa;
GLcontext *ctx, *shareCtx;
int i, memPerUnit;
assert(glVisual);
assert(driContextPriv);
assert(r200Screen);
/* Allocate the R200 context */
rmesa = (r200ContextPtr) CALLOC( sizeof(*rmesa) );
if ( !rmesa )
return GL_FALSE;
/* Allocate the Mesa context */
if (sharedContextPrivate)
shareCtx = ((r200ContextPtr) sharedContextPrivate)->glCtx;
else
shareCtx = NULL;
rmesa->glCtx = _mesa_create_context(glVisual, shareCtx, (void *) rmesa, GL_TRUE);
if (!rmesa->glCtx) {
FREE(rmesa);
return GL_FALSE;
}
driContextPriv->driverPrivate = rmesa;
/* Init r200 context data */
rmesa->dri.context = driContextPriv;
rmesa->dri.screen = sPriv;
rmesa->dri.drawable = NULL; /* Set by XMesaMakeCurrent */
rmesa->dri.hwContext = driContextPriv->hHWContext;
rmesa->dri.hwLock = &sPriv->pSAREA->lock;
rmesa->dri.fd = sPriv->fd;
rmesa->dri.drmMinor = sPriv->drmMinor;
rmesa->r200Screen = r200Screen;
rmesa->sarea = (RADEONSAREAPrivPtr)((GLubyte *)sPriv->pSAREA +
r200Screen->sarea_priv_offset);
rmesa->dma.buf0_address = rmesa->r200Screen->buffers->list[0].address;
for ( i = 0 ; i < r200Screen->numTexHeaps ; i++ ) {
make_empty_list( &rmesa->texture.objects[i] );
rmesa->texture.heap[i] = mmInit( 0, r200Screen->texSize[i] );
rmesa->texture.age[i] = -1;
}
rmesa->texture.numHeaps = r200Screen->numTexHeaps;
make_empty_list( &rmesa->texture.swapped );
rmesa->swtcl.RenderIndex = ~0;
rmesa->lost_context = 1;
/* KW: Set the maximum texture size small enough that we can
* guarentee that both texture units can bind a maximal texture
* and have them both in on-card memory at once.
* Test for 2 textures * 4 bytes/texel * size * size.
*/
ctx = rmesa->glCtx;
memPerUnit = r200Screen->texSize[RADEON_CARD_HEAP] / 2;
/* XXX the following code could go into a utility file */
if (memPerUnit >= 4 * 2048 * 2048) {
ctx->Const.MaxTextureLevels = 12; /* 2048x2048 */
}
else if (memPerUnit >= 4 * 1024 * 1024) {
ctx->Const.MaxTextureLevels = 11; /* 1024x1024 */
}
else if (memPerUnit >= 4 * 512 * 512) {
ctx->Const.MaxTextureLevels = 10; /* 512x512 */
}
else {
ctx->Const.MaxTextureLevels = 9; /* 256x256 */
}
#if ENABLE_HW_3D_TEXTURE
if (memPerUnit >= 4 * 256 * 256 * 256) {
ctx->Const.Max3DTextureLevels = 9; /* 256x256x256 */
}
else if (memPerUnit >= 4 * 64 * 64 * 64) {
ctx->Const.Max3DTextureLevels = 8; /* 128x128x128 */
}
else if (memPerUnit >= 4 * 32 * 32 * 32) {
ctx->Const.Max3DTextureLevels = 7; /* 64x64x64 */
}
else { /* 256KBytes */
ctx->Const.Max3DTextureLevels = 6; /* 32x32x32 */
}
#endif
if (memPerUnit >= 4 * 6 * 2048 * 2048) {
ctx->Const.MaxCubeTextureLevels = 12; /* 2048x2048 */
}
if (memPerUnit >= 4 * 6 * 1024 * 1024) {
ctx->Const.MaxCubeTextureLevels = 11; /* 1024x1024 */
}
else if (memPerUnit >= 4 * 6 * 512 * 512) {
ctx->Const.MaxCubeTextureLevels = 10; /* 512x512 */
}
else if (memPerUnit >= 4 * 6 * 256 * 256) {
ctx->Const.MaxCubeTextureLevels = 9; /* 256x256 */
}
else { /* 393216 bytes */
ctx->Const.MaxCubeTextureLevels = 8; /* 128x128 */
}
ctx->Const.MaxTextureUnits = 2;
ctx->Const.MaxTextureMaxAnisotropy = 16.0;
/* No wide points.
*/
ctx->Const.MinPointSize = 1.0;
ctx->Const.MinPointSizeAA = 1.0;
ctx->Const.MaxPointSize = 1.0;
ctx->Const.MaxPointSizeAA = 1.0;
ctx->Const.MinLineWidth = 1.0;
ctx->Const.MinLineWidthAA = 1.0;
ctx->Const.MaxLineWidth = 10.0;
ctx->Const.MaxLineWidthAA = 10.0;
ctx->Const.LineWidthGranularity = 0.0625;
/* Initialize the software rasterizer and helper modules.
*/
_swrast_CreateContext( ctx );
_ac_CreateContext( ctx );
_tnl_CreateContext( ctx );
_swsetup_CreateContext( ctx );
_ae_create_context( ctx );
/* Install the customized pipeline:
*/
_tnl_destroy_pipeline( ctx );
_tnl_install_pipeline( ctx, r200_pipeline );
ctx->Driver.FlushVertices = r200FlushVertices;
/* Try and keep materials and vertices separate:
*/
_tnl_isolate_materials( ctx, GL_TRUE );
/* Configure swrast to match hardware characteristics:
*/
_swrast_allow_pixel_fog( ctx, GL_FALSE );
_swrast_allow_vertex_fog( ctx, GL_TRUE );
_math_matrix_ctr( &rmesa->TexGenMatrix[0] );
_math_matrix_ctr( &rmesa->TexGenMatrix[1] );
_math_matrix_ctr( &rmesa->tmpmat );
_math_matrix_set_identity( &rmesa->TexGenMatrix[0] );
_math_matrix_set_identity( &rmesa->TexGenMatrix[1] );
_math_matrix_set_identity( &rmesa->tmpmat );
r200InitExtensions( ctx, r200Screen );
r200InitDriverFuncs( ctx );
r200InitIoctlFuncs( ctx );
r200InitStateFuncs( ctx );
r200InitSpanFuncs( ctx );
r200InitPixelFuncs( ctx );
r200InitTextureFuncs( ctx );
r200InitState( rmesa );
r200InitSwtcl( ctx );
rmesa->iw.irq_seq = -1;
rmesa->irqsEmitted = 0;
rmesa->do_irqs = (rmesa->dri.drmMinor >= 6 &&
!getenv("R200_NO_IRQS") &&
rmesa->r200Screen->irq);
if (!rmesa->do_irqs)
fprintf(stderr,
"IRQ's not enabled, falling back to busy waits: %d %d %d\n",
rmesa->dri.drmMinor,
!!getenv("R200_NO_IRQS"),
rmesa->r200Screen->irq);
rmesa->do_usleeps = !getenv("R200_NO_USLEEPS");
rmesa->prefer_agp_client_texturing =
(getenv("R200_AGP_CLIENT_TEXTURES") != 0);
#if DO_DEBUG
if (getenv("R200_DEBUG"))
add_debug_flags( getenv("R200_DEBUG") );
if (getenv("RADEON_DEBUG"))
add_debug_flags( getenv("RADEON_DEBUG") );
#endif
if (getenv("R200_NO_RAST")) {
fprintf(stderr, "disabling 3D acceleration\n");
FALLBACK(rmesa, R200_FALLBACK_DISABLE, 1);
}
else if (getenv("R200_NO_TCL")) {
fprintf(stderr, "disabling TCL support\n");
TCL_FALLBACK(rmesa->glCtx, R200_TCL_FALLBACK_TCL_DISABLE, 1);
}
else {
if (!getenv("R200_NO_VTXFMT")) {
r200VtxfmtInit( ctx );
}
_tnl_need_dlist_norm_lengths( ctx, GL_FALSE );
}
return GL_TRUE;
}
/* Destroy the device specific context.
*/
/* Destroy the Mesa and driver specific context data.
*/
void r200DestroyContext( __DRIcontextPrivate *driContextPriv )
{
GET_CURRENT_CONTEXT(ctx);
r200ContextPtr rmesa = (r200ContextPtr) driContextPriv->driverPrivate;
r200ContextPtr current = ctx ? R200_CONTEXT(ctx) : NULL;
/* check if we're deleting the currently bound context */
if (rmesa == current) {
R200_FIREVERTICES( rmesa );
_mesa_make_current2(NULL, NULL, NULL);
}
/* Free r200 context resources */
assert(rmesa); /* should never be null */
if ( rmesa ) {
if (rmesa->glCtx->Shared->RefCount == 1) {
/* This share group is about to go away, free our private
* texture object data.
*/
r200TexObjPtr t, next_t;
int i;
for ( i = 0 ; i < rmesa->texture.numHeaps ; i++ ) {
foreach_s ( t, next_t, &rmesa->texture.objects[i] ) {
r200DestroyTexObj( rmesa, t );
}
mmDestroy( rmesa->texture.heap[i] );
rmesa->texture.heap[i] = NULL;
}
foreach_s ( t, next_t, &rmesa->texture.swapped ) {
r200DestroyTexObj( rmesa, t );
}
}
_swsetup_DestroyContext( rmesa->glCtx );
_tnl_DestroyContext( rmesa->glCtx );
_ac_DestroyContext( rmesa->glCtx );
_swrast_DestroyContext( rmesa->glCtx );
r200DestroySwtcl( rmesa->glCtx );
r200ReleaseArrays( rmesa->glCtx, ~0 );
if (rmesa->dma.current.buf) {
r200ReleaseDmaRegion( rmesa, &rmesa->dma.current, __FUNCTION__ );
r200FlushCmdBuf( rmesa, __FUNCTION__ );
}
if (!rmesa->TclFallback & R200_TCL_FALLBACK_TCL_DISABLE)
if (!getenv("R200_NO_VTXFMT"))
r200VtxfmtDestroy( rmesa->glCtx );
/* free the Mesa context */
rmesa->glCtx->DriverCtx = NULL;
_mesa_destroy_context( rmesa->glCtx );
if (rmesa->state.scissor.pClipRects) {
FREE(rmesa->state.scissor.pClipRects);
rmesa->state.scissor.pClipRects = 0;
}
FREE( rmesa );
}
}
void
r200SwapBuffers( __DRIdrawablePrivate *dPriv )
{
if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
r200ContextPtr rmesa;
GLcontext *ctx;
rmesa = (r200ContextPtr) dPriv->driContextPriv->driverPrivate;
ctx = rmesa->glCtx;
if (ctx->Visual.doubleBufferMode) {
_mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
if ( rmesa->doPageFlip ) {
r200PageFlip( dPriv );
}
else {
r200CopyBuffer( dPriv );
}
}
}
else {
/* XXX this shouldn't be an error but we can't handle it for now */
_mesa_problem(NULL, "r200SwapBuffers: drawable has no context!\n");
}
}
/* Force the context `c' to be the current context and associate with it
* buffer `b'.
*/
GLboolean
r200MakeCurrent( __DRIcontextPrivate *driContextPriv,
__DRIdrawablePrivate *driDrawPriv,
__DRIdrawablePrivate *driReadPriv )
{
if ( driContextPriv ) {
r200ContextPtr newR200Ctx =
(r200ContextPtr) driContextPriv->driverPrivate;
if (R200_DEBUG & DEBUG_DRI)
fprintf(stderr, "%s ctx %p\n", __FUNCTION__, newR200Ctx->glCtx);
if ( newR200Ctx->dri.drawable != driDrawPriv ) {
newR200Ctx->dri.drawable = driDrawPriv;
r200UpdateWindow( newR200Ctx->glCtx );
r200UpdateViewportOffset( newR200Ctx->glCtx );
}
_mesa_make_current2( newR200Ctx->glCtx,
(GLframebuffer *) driDrawPriv->driverPrivate,
(GLframebuffer *) driReadPriv->driverPrivate );
if ( !newR200Ctx->glCtx->Viewport.Width ) {
_mesa_set_viewport( newR200Ctx->glCtx, 0, 0,
driDrawPriv->w, driDrawPriv->h );
}
if (newR200Ctx->vb.enabled)
r200VtxfmtMakeCurrent( newR200Ctx->glCtx );
_mesa_update_state( newR200Ctx->glCtx );
r200ValidateState( newR200Ctx->glCtx );
} else {
if (R200_DEBUG & DEBUG_DRI)
fprintf(stderr, "%s ctx is null\n", __FUNCTION__);
_mesa_make_current( 0, 0 );
}
if (R200_DEBUG & DEBUG_DRI)
fprintf(stderr, "End %s\n", __FUNCTION__);
return GL_TRUE;
}
/* Force the context `c' to be unbound from its buffer.
*/
GLboolean
r200UnbindContext( __DRIcontextPrivate *driContextPriv )
{
r200ContextPtr rmesa = (r200ContextPtr) driContextPriv->driverPrivate;
if (R200_DEBUG & DEBUG_DRI)
fprintf(stderr, "%s ctx %p\n", __FUNCTION__, rmesa->glCtx);
r200VtxfmtUnbindContext( rmesa->glCtx );
return GL_TRUE;
}

View File

@@ -0,0 +1,944 @@
/* $XFree86$ */
/*
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
The Weather Channel (TM) funded Tungsten Graphics to develop the
initial release of the Radeon 8500 driver under the XFree86 license.
This notice must be preserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#ifndef __R200_CONTEXT_H__
#define __R200_CONTEXT_H__
#ifdef GLX_DIRECT_RENDERING
#include "dri_util.h"
#include "radeon_common.h"
#include "macros.h"
#include "mtypes.h"
#include "r200_reg.h"
#define ENABLE_HW_3D_TEXTURE 0 /* XXX this is temporary! */
struct r200_context;
typedef struct r200_context r200ContextRec;
typedef struct r200_context *r200ContextPtr;
#include "r200_lock.h"
#include "r200_screen.h"
#include "mm.h"
/* Flags for software fallback cases */
/* See correponding strings in r200_swtcl.c */
#define R200_FALLBACK_TEXTURE 0x1
#define R200_FALLBACK_DRAW_BUFFER 0x2
#define R200_FALLBACK_STENCIL 0x4
#define R200_FALLBACK_RENDER_MODE 0x8
#define R200_FALLBACK_BLEND_EQ 0x10
#define R200_FALLBACK_BLEND_FUNC 0x20
#define R200_FALLBACK_DISABLE 0x40
/* The blit width for texture uploads
*/
#define BLIT_WIDTH_BYTES 1024
/* Use the templated vertex format:
*/
#define COLOR_IS_RGBA
#define TAG(x) r200##x
#include "tnl_dd/t_dd_vertex.h"
#undef TAG
typedef void (*r200_tri_func)( r200ContextPtr,
r200Vertex *,
r200Vertex *,
r200Vertex * );
typedef void (*r200_line_func)( r200ContextPtr,
r200Vertex *,
r200Vertex * );
typedef void (*r200_point_func)( r200ContextPtr,
r200Vertex * );
struct r200_colorbuffer_state {
GLuint clear;
GLint drawOffset, drawPitch;
};
struct r200_depthbuffer_state {
GLfloat scale;
};
struct r200_pixel_state {
GLint readOffset, readPitch;
};
struct r200_scissor_state {
XF86DRIClipRectRec rect;
GLboolean enabled;
GLuint numClipRects; /* Cliprects active */
GLuint numAllocedClipRects; /* Cliprects available */
XF86DRIClipRectPtr pClipRects;
};
struct r200_stencilbuffer_state {
GLboolean hwBuffer;
GLuint clear; /* rb3d_stencilrefmask value */
};
struct r200_stipple_state {
GLuint mask[32];
};
#define TEX_0 0x1
#define TEX_1 0x2
#define TEX_ALL 0x3
typedef struct r200_tex_obj r200TexObj, *r200TexObjPtr;
/* Texture object in locally shared texture space.
*/
struct r200_tex_obj {
r200TexObjPtr next, prev;
struct gl_texture_object *tObj; /* Mesa texture object */
PMemBlock memBlock; /* Memory block containing texture */
GLuint bufAddr; /* Offset to start of locally
shared texture block */
GLuint dirty_images[6]; /* Flags for whether or not
images need to be uploaded to
local or AGP texture space.
Six cube faces. */
GLuint dirty_state; /* Flags (1 per texunit) for
whether or not this texobj
has dirty hardware state
(pp_*) that needs to be
brought into the
texunit. */
GLint heap; /* Texture heap currently stored in */
drmRadeonTexImage image[6][RADEON_MAX_TEXTURE_LEVELS];
/* Six, for the cube faces */
GLint totalSize; /* Total size of the texture
including all mipmap levels,
and all six cube faces */
GLuint pp_txfilter; /* hardware register values */
GLuint pp_txformat;
GLuint pp_txformat_x;
GLuint pp_txoffset; /* Image location in texmem.
All cube faces follow. */
GLuint pp_txsize; /* npot only */
GLuint pp_txpitch; /* npot only */
GLuint pp_border_color;
GLuint pp_cubic_faces; /* cube face 1,2,3,4 log2 sizes */
/* texObj->Image[firstLevel] through texObj->Image[lastLevel] are the
* images to upload.
*/
GLint firstLevel;
GLint lastLevel;
};
struct r200_texture_env_state {
r200TexObjPtr texobj;
GLenum format;
GLenum envMode;
};
#define R200_MAX_TEXTURE_UNITS 3
struct r200_texture_state {
struct r200_texture_env_state unit[R200_MAX_TEXTURE_UNITS];
};
struct r200_state_atom {
struct r200_state_atom *next, *prev;
const char *name; /* for debug */
int cmd_size; /* size in bytes */
GLuint idx;
int *cmd; /* one or more cmd's */
int *lastcmd; /* one or more cmd's */
GLboolean (*check)( GLcontext *, int ); /* is this state active? */
};
/* Trying to keep these relatively short as the variables are becoming
* extravagently long. Drop the R200_ off the front of everything -
* I think we know we're in the r200 driver by now, and keep the
* prefix to 3 letters unless absolutely impossible.
*/
#define CTX_CMD_0 0
#define CTX_PP_MISC 1
#define CTX_PP_FOG_COLOR 2
#define CTX_RE_SOLID_COLOR 3
#define CTX_RB3D_BLENDCNTL 4
#define CTX_RB3D_DEPTHOFFSET 5
#define CTX_RB3D_DEPTHPITCH 6
#define CTX_RB3D_ZSTENCILCNTL 7
#define CTX_CMD_1 8
#define CTX_PP_CNTL 9
#define CTX_RB3D_CNTL 10
#define CTX_RB3D_COLOROFFSET 11
#define CTX_CMD_2 12 /* why */
#define CTX_RB3D_COLORPITCH 13 /* why */
#define CTX_STATE_SIZE 14
#define SET_CMD_0 0
#define SET_SE_CNTL 1
#define SET_RE_CNTL 2 /* replace se_coord_fmt */
#define SET_STATE_SIZE 3
#define VTE_CMD_0 0
#define VTE_SE_VTE_CNTL 1
#define VTE_STATE_SIZE 2
#define LIN_CMD_0 0
#define LIN_RE_LINE_PATTERN 1
#define LIN_RE_LINE_STATE 2
#define LIN_CMD_1 3
#define LIN_SE_LINE_WIDTH 4
#define LIN_STATE_SIZE 5
#define MSK_CMD_0 0
#define MSK_RB3D_STENCILREFMASK 1
#define MSK_RB3D_ROPCNTL 2
#define MSK_RB3D_PLANEMASK 3
#define MSK_STATE_SIZE 4
#define VPT_CMD_0 0
#define VPT_SE_VPORT_XSCALE 1
#define VPT_SE_VPORT_XOFFSET 2
#define VPT_SE_VPORT_YSCALE 3
#define VPT_SE_VPORT_YOFFSET 4
#define VPT_SE_VPORT_ZSCALE 5
#define VPT_SE_VPORT_ZOFFSET 6
#define VPT_STATE_SIZE 7
#define ZBS_CMD_0 0
#define ZBS_SE_ZBIAS_FACTOR 1
#define ZBS_SE_ZBIAS_CONSTANT 2
#define ZBS_STATE_SIZE 3
#define MSC_CMD_0 0
#define MSC_RE_MISC 1
#define MSC_STATE_SIZE 2
#define TAM_CMD_0 0
#define TAM_DEBUG3 1
#define TAM_STATE_SIZE 2
#define TEX_CMD_0 0
#define TEX_PP_TXFILTER 1 /*2c00*/
#define TEX_PP_TXFORMAT 2 /*2c04*/
#define TEX_PP_TXFORMAT_X 3 /*2c08*/
#define TEX_PP_TXSIZE 4 /*2c0c*/
#define TEX_PP_TXPITCH 5 /*2c10*/
#define TEX_PP_BORDER_COLOR 6 /*2c14*/
#define TEX_CMD_1 7
#define TEX_PP_TXOFFSET 8 /*2d00 */
#define TEX_STATE_SIZE 9
#define CUBE_CMD_0 0 /* 1 register follows */
#define CUBE_PP_CUBIC_FACES 1 /* 0x2c18 */
#define CUBE_CMD_1 2 /* 5 registers follow */
#define CUBE_PP_CUBIC_OFFSET_F1 3 /* 0x2d04 */
#define CUBE_PP_CUBIC_OFFSET_F2 4 /* 0x2d08 */
#define CUBE_PP_CUBIC_OFFSET_F3 5 /* 0x2d0c */
#define CUBE_PP_CUBIC_OFFSET_F4 6 /* 0x2d10 */
#define CUBE_PP_CUBIC_OFFSET_F5 7 /* 0x2d14 */
#define CUBE_STATE_SIZE 8
#define PIX_CMD_0 0
#define PIX_PP_TXCBLEND 1
#define PIX_PP_TXCBLEND2 2
#define PIX_PP_TXABLEND 3
#define PIX_PP_TXABLEND2 4
#define PIX_STATE_SIZE 5
#define TF_CMD_0 0
#define TF_TFACTOR_0 1
#define TF_TFACTOR_1 2
#define TF_TFACTOR_2 3
#define TF_TFACTOR_3 4
#define TF_TFACTOR_4 5
#define TF_TFACTOR_5 6
#define TF_STATE_SIZE 7
#define TCL_CMD_0 0
#define TCL_LIGHT_MODEL_CTL_0 1
#define TCL_LIGHT_MODEL_CTL_1 2
#define TCL_PER_LIGHT_CTL_0 3
#define TCL_PER_LIGHT_CTL_1 4
#define TCL_PER_LIGHT_CTL_2 5
#define TCL_PER_LIGHT_CTL_3 6
#define TCL_CMD_1 7
#define TCL_UCP_VERT_BLEND_CTL 8
#define TCL_STATE_SIZE 9
#define MSL_CMD_0 0
#define MSL_MATRIX_SELECT_0 1
#define MSL_MATRIX_SELECT_1 2
#define MSL_MATRIX_SELECT_2 3
#define MSL_MATRIX_SELECT_3 4
#define MSL_MATRIX_SELECT_4 5
#define MSL_STATE_SIZE 6
#define TCG_CMD_0 0
#define TCG_TEX_PROC_CTL_2 1
#define TCG_TEX_PROC_CTL_3 2
#define TCG_TEX_PROC_CTL_0 3
#define TCG_TEX_PROC_CTL_1 4
#define TCG_TEX_CYL_WRAP_CTL 5
#define TCG_STATE_SIZE 6
#define MTL_CMD_0 0
#define MTL_EMMISSIVE_RED 1
#define MTL_EMMISSIVE_GREEN 2
#define MTL_EMMISSIVE_BLUE 3
#define MTL_EMMISSIVE_ALPHA 4
#define MTL_AMBIENT_RED 5
#define MTL_AMBIENT_GREEN 6
#define MTL_AMBIENT_BLUE 7
#define MTL_AMBIENT_ALPHA 8
#define MTL_DIFFUSE_RED 9
#define MTL_DIFFUSE_GREEN 10
#define MTL_DIFFUSE_BLUE 11
#define MTL_DIFFUSE_ALPHA 12
#define MTL_SPECULAR_RED 13
#define MTL_SPECULAR_GREEN 14
#define MTL_SPECULAR_BLUE 15
#define MTL_SPECULAR_ALPHA 16
#define MTL_CMD_1 17
#define MTL_SHININESS 18
#define MTL_STATE_SIZE 19
#define VAP_CMD_0 0
#define VAP_SE_VAP_CNTL 1
#define VAP_STATE_SIZE 2
/* Replaces a lot of packet info from radeon
*/
#define VTX_CMD_0 0
#define VTX_VTXFMT_0 1
#define VTX_VTXFMT_1 2
#define VTX_TCL_OUTPUT_VTXFMT_0 3
#define VTX_TCL_OUTPUT_VTXFMT_1 4
#define VTX_CMD_1 5
#define VTX_TCL_OUTPUT_COMPSEL 6
#define VTX_CMD_2 7
#define VTX_STATE_CNTL 8
#define VTX_STATE_SIZE 9
#define VTX_COLOR(v,n) (((v)>>(R200_VTX_COLOR_0_SHIFT+(n)*2))&\
R200_VTX_COLOR_MASK)
#define MAT_CMD_0 0
#define MAT_ELT_0 1
#define MAT_STATE_SIZE 17
#define GRD_CMD_0 0
#define GRD_VERT_GUARD_CLIP_ADJ 1
#define GRD_VERT_GUARD_DISCARD_ADJ 2
#define GRD_HORZ_GUARD_CLIP_ADJ 3
#define GRD_HORZ_GUARD_DISCARD_ADJ 4
#define GRD_STATE_SIZE 5
/* position changes frequently when lighting in modelpos - separate
* out to new state item?
*/
#define LIT_CMD_0 0
#define LIT_AMBIENT_RED 1
#define LIT_AMBIENT_GREEN 2
#define LIT_AMBIENT_BLUE 3
#define LIT_AMBIENT_ALPHA 4
#define LIT_DIFFUSE_RED 5
#define LIT_DIFFUSE_GREEN 6
#define LIT_DIFFUSE_BLUE 7
#define LIT_DIFFUSE_ALPHA 8
#define LIT_SPECULAR_RED 9
#define LIT_SPECULAR_GREEN 10
#define LIT_SPECULAR_BLUE 11
#define LIT_SPECULAR_ALPHA 12
#define LIT_POSITION_X 13
#define LIT_POSITION_Y 14
#define LIT_POSITION_Z 15
#define LIT_POSITION_W 16
#define LIT_DIRECTION_X 17
#define LIT_DIRECTION_Y 18
#define LIT_DIRECTION_Z 19
#define LIT_DIRECTION_W 20
#define LIT_ATTEN_CONST 21
#define LIT_ATTEN_LINEAR 22
#define LIT_ATTEN_QUADRATIC 23
#define LIT_ATTEN_XXX 24
#define LIT_CMD_1 25
#define LIT_SPOT_DCD 26
#define LIT_SPOT_DCM 27
#define LIT_SPOT_EXPONENT 28
#define LIT_SPOT_CUTOFF 29
#define LIT_SPECULAR_THRESH 30
#define LIT_RANGE_CUTOFF 31 /* ? */
#define LIT_RANGE_ATTEN 32 /* ? */
#define LIT_STATE_SIZE 33
/* Fog
*/
#define FOG_CMD_0 0
#define FOG_R 1
#define FOG_C 2
#define FOG_D 3
#define FOG_PAD 4
#define FOG_STATE_SIZE 5
/* UCP
*/
#define UCP_CMD_0 0
#define UCP_X 1
#define UCP_Y 2
#define UCP_Z 3
#define UCP_W 4
#define UCP_STATE_SIZE 5
/* GLT - Global ambient
*/
#define GLT_CMD_0 0
#define GLT_RED 1
#define GLT_GREEN 2
#define GLT_BLUE 3
#define GLT_ALPHA 4
#define GLT_STATE_SIZE 5
/* EYE
*/
#define EYE_CMD_0 0
#define EYE_X 1
#define EYE_Y 2
#define EYE_Z 3
#define EYE_RESCALE_FACTOR 4
#define EYE_STATE_SIZE 5
/* CST - constant state
*/
#define CST_CMD_0 0
#define CST_PP_CNTL_X 1
#define CST_CMD_1 2
#define CST_RB3D_DEPTHXY_OFFSET 3
#define CST_CMD_2 4
#define CST_RE_AUX_SCISSOR_CNTL 5
#define CST_CMD_3 6
#define CST_RE_SCISSOR_TL_0 7
#define CST_RE_SCISSOR_BR_0 8
#define CST_CMD_4 9
#define CST_SE_VAP_CNTL_STATUS 10
#define CST_CMD_5 11
#define CST_RE_POINTSIZE 12
#define CST_CMD_6 13
#define CST_SE_TCL_INPUT_VTX_0 14
#define CST_SE_TCL_INPUT_VTX_1 15
#define CST_SE_TCL_INPUT_VTX_2 16
#define CST_SE_TCL_INPUT_VTX_3 17
#define CST_STATE_SIZE 18
struct r200_hw_state {
/* All state should be on one of these lists:
*/
struct r200_state_atom dirty; /* dirty list head placeholder */
struct r200_state_atom clean; /* clean list head placeholder */
/* Hardware state, stored as cmdbuf commands:
* -- Need to doublebuffer for
* - reviving state after loss of context
* - eliding noop statechange loops? (except line stipple count)
*/
struct r200_state_atom ctx;
struct r200_state_atom set;
struct r200_state_atom vte;
struct r200_state_atom lin;
struct r200_state_atom msk;
struct r200_state_atom vpt;
struct r200_state_atom vap;
struct r200_state_atom vtx;
struct r200_state_atom tcl;
struct r200_state_atom msl;
struct r200_state_atom tcg;
struct r200_state_atom msc;
struct r200_state_atom cst;
struct r200_state_atom tam;
struct r200_state_atom tf;
struct r200_state_atom tex[2];
struct r200_state_atom cube[2];
struct r200_state_atom zbs;
struct r200_state_atom mtl[2];
struct r200_state_atom mat[5];
struct r200_state_atom lit[8]; /* includes vec, scl commands */
struct r200_state_atom ucp[6];
struct r200_state_atom pix[6]; /* pixshader stages */
struct r200_state_atom eye; /* eye pos */
struct r200_state_atom grd; /* guard band clipping */
struct r200_state_atom fog;
struct r200_state_atom glt;
};
struct r200_state {
/* Derived state for internal purposes:
*/
struct r200_colorbuffer_state color;
struct r200_depthbuffer_state depth;
struct r200_pixel_state pixel;
struct r200_scissor_state scissor;
struct r200_stencilbuffer_state stencil;
struct r200_stipple_state stipple;
struct r200_texture_state texture;
};
struct r200_texture {
r200TexObj objects[R200_NR_TEX_HEAPS];
r200TexObj swapped;
memHeap_t *heap[R200_NR_TEX_HEAPS];
GLint age[R200_NR_TEX_HEAPS];
GLint numHeaps;
};
/* Need refcounting on dma buffers:
*/
struct r200_dma_buffer {
int refcount; /* the number of retained regions in buf */
drmBufPtr buf;
};
#define GET_START(rvb) (rmesa->r200Screen->agp_buffer_offset + \
(rvb)->address - rmesa->dma.buf0_address + \
(rvb)->start)
/* A retained region, eg vertices for indexed vertices.
*/
struct r200_dma_region {
struct r200_dma_buffer *buf;
char *address; /* == buf->address */
int start, end, ptr; /* offsets from start of buf */
int aos_start;
int aos_stride;
int aos_size;
};
struct r200_dma {
/* Active dma region. Allocations for vertices and retained
* regions come from here. Also used for emitting random vertices,
* these may be flushed by calling flush_current();
*/
struct r200_dma_region current;
void (*flush)( r200ContextPtr );
char *buf0_address; /* start of buf[0], for index calcs */
GLuint nr_released_bufs; /* flush after so many buffers released */
};
struct r200_dri_mirror {
__DRIcontextPrivate *context; /* DRI context */
__DRIscreenPrivate *screen; /* DRI screen */
__DRIdrawablePrivate *drawable; /* DRI drawable bound to this ctx */
drmContext hwContext;
drmLock *hwLock;
int fd;
int drmMinor;
};
#define R200_CMD_BUF_SZ (8*1024)
struct r200_store {
GLuint statenr;
GLuint primnr;
char cmd_buf[R200_CMD_BUF_SZ];
int cmd_used;
int elts_start;
};
/* r200_tcl.c
*/
struct r200_tcl_info {
GLuint vertex_format;
GLint last_offset;
GLuint hw_primitive;
struct r200_dma_region *aos_components[8];
GLuint nr_aos_components;
GLuint *Elts;
struct r200_dma_region indexed_verts;
struct r200_dma_region obj;
struct r200_dma_region rgba;
struct r200_dma_region spec;
struct r200_dma_region fog;
struct r200_dma_region tex[R200_MAX_TEXTURE_UNITS];
struct r200_dma_region norm;
};
/* r200_swtcl.c
*/
struct r200_swtcl_info {
GLuint SetupIndex;
GLuint SetupNewInputs;
GLuint RenderIndex;
GLuint vertex_size;
GLuint vertex_stride_shift;
GLuint vertex_format;
char *verts;
/* Fallback rasterization functions
*/
r200_point_func draw_point;
r200_line_func draw_line;
r200_tri_func draw_tri;
GLuint hw_primitive;
GLenum render_primitive;
GLuint numverts;
struct r200_dma_region indexed_verts;
};
struct r200_ioctl {
GLuint vertex_offset;
GLuint vertex_size;
};
#define R200_MAX_PRIMS 64
/* Want to keep a cache of these around. Each is parameterized by
* only a single value which has only a small range. Only expect a
* few, so just rescan the list each time?
*/
struct dynfn {
struct dynfn *next, *prev;
int key[2];
char *code;
};
struct dfn_lists {
struct dynfn Vertex2f;
struct dynfn Vertex2fv;
struct dynfn Vertex3f;
struct dynfn Vertex3fv;
struct dynfn Color4ub;
struct dynfn Color4ubv;
struct dynfn Color3ub;
struct dynfn Color3ubv;
struct dynfn Color4f;
struct dynfn Color4fv;
struct dynfn Color3f;
struct dynfn Color3fv;
struct dynfn SecondaryColor3ubEXT;
struct dynfn SecondaryColor3ubvEXT;
struct dynfn SecondaryColor3fEXT;
struct dynfn SecondaryColor3fvEXT;
struct dynfn Normal3f;
struct dynfn Normal3fv;
struct dynfn TexCoord2f;
struct dynfn TexCoord2fv;
struct dynfn TexCoord1f;
struct dynfn TexCoord1fv;
struct dynfn MultiTexCoord2fARB;
struct dynfn MultiTexCoord2fvARB;
struct dynfn MultiTexCoord1fARB;
struct dynfn MultiTexCoord1fvARB;
};
struct _vb;
struct dfn_generators {
struct dynfn *(*Vertex2f)( GLcontext *, const int * );
struct dynfn *(*Vertex2fv)( GLcontext *, const int * );
struct dynfn *(*Vertex3f)( GLcontext *, const int * );
struct dynfn *(*Vertex3fv)( GLcontext *, const int * );
struct dynfn *(*Color4ub)( GLcontext *, const int * );
struct dynfn *(*Color4ubv)( GLcontext *, const int * );
struct dynfn *(*Color3ub)( GLcontext *, const int * );
struct dynfn *(*Color3ubv)( GLcontext *, const int * );
struct dynfn *(*Color4f)( GLcontext *, const int * );
struct dynfn *(*Color4fv)( GLcontext *, const int * );
struct dynfn *(*Color3f)( GLcontext *, const int * );
struct dynfn *(*Color3fv)( GLcontext *, const int * );
struct dynfn *(*SecondaryColor3ubEXT)( GLcontext *, const int * );
struct dynfn *(*SecondaryColor3ubvEXT)( GLcontext *, const int * );
struct dynfn *(*SecondaryColor3fEXT)( GLcontext *, const int * );
struct dynfn *(*SecondaryColor3fvEXT)( GLcontext *, const int * );
struct dynfn *(*Normal3f)( GLcontext *, const int * );
struct dynfn *(*Normal3fv)( GLcontext *, const int * );
struct dynfn *(*TexCoord2f)( GLcontext *, const int * );
struct dynfn *(*TexCoord2fv)( GLcontext *, const int * );
struct dynfn *(*TexCoord1f)( GLcontext *, const int * );
struct dynfn *(*TexCoord1fv)( GLcontext *, const int * );
struct dynfn *(*MultiTexCoord2fARB)( GLcontext *, const int * );
struct dynfn *(*MultiTexCoord2fvARB)( GLcontext *, const int * );
struct dynfn *(*MultiTexCoord1fARB)( GLcontext *, const int * );
struct dynfn *(*MultiTexCoord1fvARB)( GLcontext *, const int * );
};
struct r200_vb {
/* Keep these first: referenced from codegen templates:
*/
GLint counter, initial_counter;
GLint *dmaptr;
void (*notify)( void );
GLint vertex_size;
/* A maximum total of 15 elements per vertex: 3 floats for position, 3
* floats for normal, 4 floats for color, 4 bytes for secondary color,
* 2 floats for each texture unit (4 floats total).
*
* As soon as the 3rd TMU is supported or cube maps (or 3D textures) are
* supported, this value will grow.
*
* The position data is never actually stored here, so 3 elements could be
* trimmed out of the buffer.
*/
union { float f; int i; r200_color_t color; } vertex[15];
GLfloat *normalptr;
GLfloat *floatcolorptr;
r200_color_t *colorptr;
GLfloat *floatspecptr;
r200_color_t *specptr;
GLfloat *texcoordptr[2];
GLcontext *context; /* current context : Single thread only! */
};
struct r200_prim {
GLuint start;
GLuint end;
GLuint prim;
};
struct r200_vbinfo {
GLenum *prim; /* &ctx->Driver.CurrentExecPrimitive */
GLuint primflags;
GLboolean enabled; /* R200_NO_VTXFMT//R200_NO_TCL env vars */
GLboolean installed;
GLboolean fell_back;
GLboolean recheck;
GLint initial_counter;
GLint nrverts;
GLuint vtxfmt_0, vtxfmt_1;
GLuint installed_vertex_format;
GLuint installed_color_3f_sz;
struct r200_prim primlist[R200_MAX_PRIMS];
int nrprims;
struct dfn_lists dfn_cache;
struct dfn_generators codegen;
GLvertexformat vtxfmt;
};
struct r200_context {
GLcontext *glCtx; /* Mesa context */
/* Driver and hardware state management
*/
struct r200_hw_state hw;
struct r200_state state;
/* Texture object bookkeeping
*/
struct r200_texture texture;
/* Rasterization and vertex state:
*/
GLuint TclFallback;
GLuint Fallback;
GLuint NewGLState;
/* Temporaries for translating away float colors:
*/
struct gl_client_array UbyteColor;
struct gl_client_array UbyteSecondaryColor;
/* Vertex buffers
*/
struct r200_ioctl ioctl;
struct r200_dma dma;
struct r200_store store;
/* Page flipping
*/
GLuint doPageFlip;
/* Busy waiting
*/
GLuint do_usleeps;
GLuint do_irqs;
GLuint irqsEmitted;
drmRadeonIrqWait iw;
/* Clientdata textures;
*/
GLuint prefer_agp_client_texturing;
/* Drawable, cliprect and scissor information
*/
GLuint numClipRects; /* Cliprects for the draw buffer */
XF86DRIClipRectPtr pClipRects;
unsigned int lastStamp;
GLboolean lost_context;
r200ScreenPtr r200Screen; /* Screen private DRI data */
RADEONSAREAPrivPtr sarea; /* Private SAREA data */
/* TCL stuff
*/
GLmatrix TexGenMatrix[R200_MAX_TEXTURE_UNITS];
GLboolean recheck_texgen[R200_MAX_TEXTURE_UNITS];
GLboolean TexGenNeedNormals[R200_MAX_TEXTURE_UNITS];
GLuint TexMatEnabled;
GLuint TexMatCompSel;
GLuint TexGenEnabled;
GLuint TexGenInputs;
GLuint TexGenCompSel;
GLmatrix tmpmat;
/* VBI
*/
GLuint vbl_seq;
/* r200_tcl.c
*/
struct r200_tcl_info tcl;
/* r200_swtcl.c
*/
struct r200_swtcl_info swtcl;
/* r200_vtxfmt.c
*/
struct r200_vbinfo vb;
/* Mirrors of some DRI state
*/
struct r200_dri_mirror dri;
};
#define R200_CONTEXT(ctx) ((r200ContextPtr)(ctx->DriverCtx))
static __inline GLuint r200PackColor( GLuint cpp,
GLubyte r, GLubyte g,
GLubyte b, GLubyte a )
{
switch ( cpp ) {
case 2:
return PACK_COLOR_565( r, g, b );
case 4:
return PACK_COLOR_8888( a, r, g, b );
default:
return 0;
}
}
#define R200_OLD_PACKETS 0
extern void r200DestroyContext( __DRIcontextPrivate *driContextPriv );
extern GLboolean r200CreateContext( const __GLcontextModes *glVisual,
__DRIcontextPrivate *driContextPriv,
void *sharedContextPrivate);
extern void r200SwapBuffers( __DRIdrawablePrivate *dPriv );
extern GLboolean r200MakeCurrent( __DRIcontextPrivate *driContextPriv,
__DRIdrawablePrivate *driDrawPriv,
__DRIdrawablePrivate *driReadPriv );
extern GLboolean r200UnbindContext( __DRIcontextPrivate *driContextPriv );
/* ================================================================
* Debugging:
*/
#define DO_DEBUG 1
#if DO_DEBUG
extern int R200_DEBUG;
#else
#define R200_DEBUG 0
#endif
#define DEBUG_TEXTURE 0x001
#define DEBUG_STATE 0x002
#define DEBUG_IOCTL 0x004
#define DEBUG_PRIMS 0x008
#define DEBUG_VERTS 0x010
#define DEBUG_FALLBACKS 0x020
#define DEBUG_VFMT 0x040
#define DEBUG_CODEGEN 0x080
#define DEBUG_VERBOSE 0x100
#define DEBUG_DRI 0x200
#define DEBUG_DMA 0x400
#define DEBUG_SANITY 0x800
#define DEBUG_SYNC 0x1000
#define DEBUG_PIXEL 0x2000
#define DEBUG_MEMORY 0x4000
#endif
#endif /* __R200_CONTEXT_H__ */

View File

@@ -0,0 +1,934 @@
/* $XFree86$ */
/*
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
The Weather Channel (TM) funded Tungsten Graphics to develop the
initial release of the Radeon 8500 driver under the XFree86 license.
This notice must be preserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#include "glheader.h"
#include "imports.h"
#include "macros.h"
#include "context.h"
#include "swrast/swrast.h"
#include "r200_context.h"
#include "r200_state.h"
#include "r200_ioctl.h"
#include "r200_tcl.h"
#include "r200_sanity.h"
#include "radeon_reg.h"
#include <unistd.h> /* for usleep() */
#include <errno.h>
#define R200_TIMEOUT 512
#define R200_IDLE_RETRY 16
static void do_usleep( int nr, const char *caller )
{
//if (1) fprintf(stderr, "usleep %d in %s\n", nr, caller );
if (1) usleep( nr );
}
static void r200WaitForIdle( r200ContextPtr rmesa );
int r200FlushCmdBufLocked( r200ContextPtr rmesa, const char * caller )
{
int ret, i;
drmRadeonCmdBuffer cmd;
if (R200_DEBUG & DEBUG_IOCTL) {
fprintf(stderr, "%s from %s\n", __FUNCTION__, caller);
if (0 & R200_DEBUG & DEBUG_VERBOSE)
for (i = 0 ; i < rmesa->store.cmd_used ; i += 4 )
fprintf(stderr, "%d: %x\n", i/4,
*(int *)(&rmesa->store.cmd_buf[i]));
}
if (R200_DEBUG & DEBUG_DMA)
fprintf(stderr, "%s: Releasing %d buffers\n", __FUNCTION__,
rmesa->dma.nr_released_bufs);
if (R200_DEBUG & DEBUG_SANITY) {
if (rmesa->state.scissor.enabled)
ret = r200SanityCmdBuffer( rmesa,
rmesa->state.scissor.numClipRects,
rmesa->state.scissor.pClipRects);
else
ret = r200SanityCmdBuffer( rmesa,
rmesa->numClipRects,
rmesa->pClipRects);
if (ret) {
fprintf(stderr, "drmSanityCommandWrite: %d\n", ret);
goto out;
}
}
if (R200_DEBUG & DEBUG_MEMORY) {
if (!r200ValidateTexObjs( rmesa )) {
fprintf(stderr, " -- tex memory is inconsistent - expect mangled textures\n");
}
}
cmd.bufsz = rmesa->store.cmd_used;
cmd.buf = rmesa->store.cmd_buf;
if (rmesa->state.scissor.enabled) {
cmd.nbox = rmesa->state.scissor.numClipRects;
cmd.boxes = (drmClipRect *)rmesa->state.scissor.pClipRects;
} else {
cmd.nbox = rmesa->numClipRects;
cmd.boxes = (drmClipRect *)rmesa->pClipRects;
}
ret = drmCommandWrite( rmesa->dri.fd,
DRM_RADEON_CMDBUF,
&cmd, sizeof(cmd) );
if (ret)
fprintf(stderr, "drmCommandWrite: %d\n", ret);
if (R200_DEBUG & DEBUG_SYNC) {
fprintf(stderr, "\nSyncing in %s\n\n", __FUNCTION__);
r200WaitForIdleLocked( rmesa );
}
out:
rmesa->store.primnr = 0;
rmesa->store.statenr = 0;
rmesa->store.cmd_used = 0;
rmesa->dma.nr_released_bufs = 0;
/* rmesa->lost_context = 0; */
rmesa->lost_context = 1;
return ret;
}
/* Note: does not emit any commands to avoid recursion on
* r200AllocCmdBuf.
*/
void r200FlushCmdBuf( r200ContextPtr rmesa, const char *caller )
{
int ret;
LOCK_HARDWARE( rmesa );
ret = r200FlushCmdBufLocked( rmesa, caller );
UNLOCK_HARDWARE( rmesa );
if (ret) {
fprintf(stderr, "drmRadeonCmdBuffer: %d (exiting)\n", ret);
exit(ret);
}
}
/* =============================================================
* Hardware vertex buffer handling
*/
void r200RefillCurrentDmaRegion( r200ContextPtr rmesa )
{
struct r200_dma_buffer *dmabuf;
int fd = rmesa->dri.fd;
int index = 0;
int size = 0;
drmDMAReq dma;
int ret;
if (R200_DEBUG & (DEBUG_IOCTL|DEBUG_DMA))
fprintf(stderr, "%s\n", __FUNCTION__);
if (rmesa->dma.flush) {
rmesa->dma.flush( rmesa );
}
if (rmesa->dma.current.buf)
r200ReleaseDmaRegion( rmesa, &rmesa->dma.current, __FUNCTION__ );
if (rmesa->dma.nr_released_bufs > 4)
r200FlushCmdBuf( rmesa, __FUNCTION__ );
dma.context = rmesa->dri.hwContext;
dma.send_count = 0;
dma.send_list = NULL;
dma.send_sizes = NULL;
dma.flags = 0;
dma.request_count = 1;
dma.request_size = RADEON_BUFFER_SIZE;
dma.request_list = &index;
dma.request_sizes = &size;
dma.granted_count = 0;
LOCK_HARDWARE(rmesa); /* no need to validate */
while (1) {
ret = drmDMA( fd, &dma );
if (ret == 0)
break;
if (rmesa->dma.nr_released_bufs) {
r200FlushCmdBufLocked( rmesa, __FUNCTION__ );
}
if (rmesa->do_usleeps) {
UNLOCK_HARDWARE( rmesa );
do_usleep(1, __FUNCTION__);
LOCK_HARDWARE( rmesa );
}
}
UNLOCK_HARDWARE(rmesa);
if (R200_DEBUG & DEBUG_DMA)
fprintf(stderr, "Allocated buffer %d\n", index);
dmabuf = CALLOC_STRUCT( r200_dma_buffer );
dmabuf->buf = &rmesa->r200Screen->buffers->list[index];
dmabuf->refcount = 1;
rmesa->dma.current.buf = dmabuf;
rmesa->dma.current.address = dmabuf->buf->address;
rmesa->dma.current.end = dmabuf->buf->total;
rmesa->dma.current.start = 0;
rmesa->dma.current.ptr = 0;
}
void r200ReleaseDmaRegion( r200ContextPtr rmesa,
struct r200_dma_region *region,
const char *caller )
{
if (R200_DEBUG & DEBUG_IOCTL)
fprintf(stderr, "%s from %s\n", __FUNCTION__, caller);
if (!region->buf)
return;
if (rmesa->dma.flush)
rmesa->dma.flush( rmesa );
if (--region->buf->refcount == 0) {
drmRadeonCmdHeader *cmd;
if (R200_DEBUG & (DEBUG_IOCTL|DEBUG_DMA))
fprintf(stderr, "%s -- DISCARD BUF %d\n", __FUNCTION__,
region->buf->buf->idx);
cmd = (drmRadeonCmdHeader *)r200AllocCmdBuf( rmesa, sizeof(*cmd),
__FUNCTION__ );
cmd->dma.cmd_type = RADEON_CMD_DMA_DISCARD;
cmd->dma.buf_idx = region->buf->buf->idx;
FREE(region->buf);
rmesa->dma.nr_released_bufs++;
}
region->buf = 0;
region->start = 0;
}
/* Allocates a region from rmesa->dma.current. If there isn't enough
* space in current, grab a new buffer (and discard what was left of current)
*/
void r200AllocDmaRegion( r200ContextPtr rmesa,
struct r200_dma_region *region,
int bytes,
int alignment )
{
if (R200_DEBUG & DEBUG_IOCTL)
fprintf(stderr, "%s %d\n", __FUNCTION__, bytes);
if (rmesa->dma.flush)
rmesa->dma.flush( rmesa );
if (region->buf)
r200ReleaseDmaRegion( rmesa, region, __FUNCTION__ );
alignment--;
rmesa->dma.current.start = rmesa->dma.current.ptr =
(rmesa->dma.current.ptr + alignment) & ~alignment;
if ( rmesa->dma.current.ptr + bytes > rmesa->dma.current.end )
r200RefillCurrentDmaRegion( rmesa );
region->start = rmesa->dma.current.start;
region->ptr = rmesa->dma.current.start;
region->end = rmesa->dma.current.start + bytes;
region->address = rmesa->dma.current.address;
region->buf = rmesa->dma.current.buf;
region->buf->refcount++;
rmesa->dma.current.ptr += bytes; /* bug - if alignment > 7 */
rmesa->dma.current.start =
rmesa->dma.current.ptr = (rmesa->dma.current.ptr + 0x7) & ~0x7;
}
void r200AllocDmaRegionVerts( r200ContextPtr rmesa,
struct r200_dma_region *region,
int numverts,
int vertsize,
int alignment )
{
r200AllocDmaRegion( rmesa, region, vertsize * numverts, alignment );
}
/* ================================================================
* SwapBuffers with client-side throttling
*/
static GLuint r200GetLastFrame(r200ContextPtr rmesa)
{
drmRadeonGetParam gp;
int ret;
GLuint frame;
gp.param = RADEON_PARAM_LAST_FRAME;
gp.value = (int *)&frame;
ret = drmCommandWriteRead( rmesa->dri.fd, DRM_RADEON_GETPARAM,
&gp, sizeof(gp) );
if ( ret ) {
fprintf( stderr, "%s: drmRadeonGetParam: %d\n", __FUNCTION__, ret );
exit(1);
}
return frame;
}
static void r200EmitIrqLocked( r200ContextPtr rmesa )
{
drmRadeonIrqEmit ie;
int ret;
ie.irq_seq = &rmesa->iw.irq_seq;
ret = drmCommandWriteRead( rmesa->dri.fd, DRM_RADEON_IRQ_EMIT,
&ie, sizeof(ie) );
if ( ret ) {
fprintf( stderr, "%s: drmRadeonIrqEmit: %d\n", __FUNCTION__, ret );
exit(1);
}
}
static void r200WaitIrq( r200ContextPtr rmesa )
{
int ret;
do {
ret = drmCommandWrite( rmesa->dri.fd, DRM_RADEON_IRQ_WAIT,
&rmesa->iw, sizeof(rmesa->iw) );
} while (ret && (errno == EINTR || errno == EAGAIN));
if ( ret ) {
fprintf( stderr, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__, ret );
exit(1);
}
}
static void r200WaitForFrameCompletion( r200ContextPtr rmesa )
{
RADEONSAREAPrivPtr sarea = rmesa->sarea;
if (rmesa->do_irqs) {
if (r200GetLastFrame(rmesa) < sarea->last_frame) {
if (!rmesa->irqsEmitted) {
while (r200GetLastFrame (rmesa) < sarea->last_frame)
;
}
else {
UNLOCK_HARDWARE( rmesa );
r200WaitIrq( rmesa );
LOCK_HARDWARE( rmesa );
}
rmesa->irqsEmitted = 10;
}
if (rmesa->irqsEmitted) {
r200EmitIrqLocked( rmesa );
rmesa->irqsEmitted--;
}
}
else {
while (r200GetLastFrame (rmesa) < sarea->last_frame) {
UNLOCK_HARDWARE( rmesa );
if (rmesa->do_usleeps)
do_usleep(1, __FUNCTION__);
LOCK_HARDWARE( rmesa );
}
}
}
/* Copy the back color buffer to the front color buffer.
*/
void r200CopyBuffer( const __DRIdrawablePrivate *dPriv )
{
r200ContextPtr rmesa;
GLint nbox, i, ret;
assert(dPriv);
assert(dPriv->driContextPriv);
assert(dPriv->driContextPriv->driverPrivate);
rmesa = (r200ContextPtr) dPriv->driContextPriv->driverPrivate;
if ( R200_DEBUG & DEBUG_IOCTL ) {
fprintf( stderr, "\n%s( %p )\n\n", __FUNCTION__, rmesa->glCtx );
}
R200_FIREVERTICES( rmesa );
LOCK_HARDWARE( rmesa );
/* Throttle the frame rate -- only allow one pending swap buffers
* request at a time.
*/
r200WaitForFrameCompletion( rmesa );
r200WaitForVBlank( rmesa );
nbox = rmesa->dri.drawable->numClipRects; /* must be in locked region */
for ( i = 0 ; i < nbox ; ) {
GLint nr = MIN2( i + RADEON_NR_SAREA_CLIPRECTS , nbox );
XF86DRIClipRectPtr box = rmesa->dri.drawable->pClipRects;
XF86DRIClipRectPtr b = rmesa->sarea->boxes;
GLint n = 0;
for ( ; i < nr ; i++ ) {
*b++ = box[i];
n++;
}
rmesa->sarea->nbox = n;
ret = drmCommandNone( rmesa->dri.fd, DRM_RADEON_SWAP );
if ( ret ) {
fprintf( stderr, "DRM_R200_SWAP_BUFFERS: return = %d\n", ret );
UNLOCK_HARDWARE( rmesa );
exit( 1 );
}
}
UNLOCK_HARDWARE( rmesa );
rmesa->lost_context = 1;
}
void r200PageFlip( const __DRIdrawablePrivate *dPriv )
{
r200ContextPtr rmesa;
GLint ret;
assert(dPriv);
assert(dPriv->driContextPriv);
assert(dPriv->driContextPriv->driverPrivate);
rmesa = (r200ContextPtr) dPriv->driContextPriv->driverPrivate;
if ( R200_DEBUG & DEBUG_IOCTL ) {
fprintf(stderr, "%s: pfCurrentPage: %d\n", __FUNCTION__,
rmesa->sarea->pfCurrentPage);
}
R200_FIREVERTICES( rmesa );
LOCK_HARDWARE( rmesa );
if (!rmesa->dri.drawable->numClipRects) {
UNLOCK_HARDWARE( rmesa );
usleep( 10000 ); /* throttle invisible client 10ms */
return;
}
/* Need to do this for the perf box placement:
*/
{
XF86DRIClipRectPtr box = rmesa->dri.drawable->pClipRects;
XF86DRIClipRectPtr b = rmesa->sarea->boxes;
b[0] = box[0];
rmesa->sarea->nbox = 1;
}
/* Throttle the frame rate -- only allow a few pending swap buffers
* request at a time.
*/
r200WaitForFrameCompletion( rmesa );
r200WaitForVBlank( rmesa );
ret = drmCommandNone( rmesa->dri.fd, DRM_RADEON_FLIP );
UNLOCK_HARDWARE( rmesa );
if ( ret ) {
fprintf( stderr, "DRM_R200_FLIP: return = %d\n", ret );
exit( 1 );
}
if ( rmesa->sarea->pfCurrentPage == 1 ) {
rmesa->state.color.drawOffset = rmesa->r200Screen->frontOffset;
rmesa->state.color.drawPitch = rmesa->r200Screen->frontPitch;
} else {
rmesa->state.color.drawOffset = rmesa->r200Screen->backOffset;
rmesa->state.color.drawPitch = rmesa->r200Screen->backPitch;
}
R200_STATECHANGE( rmesa, ctx );
rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = rmesa->state.color.drawOffset;
rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = rmesa->state.color.drawPitch;
}
/* ================================================================
* Buffer clear
*/
static void r200Clear( GLcontext *ctx, GLbitfield mask, GLboolean all,
GLint cx, GLint cy, GLint cw, GLint ch )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
__DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
GLuint flags = 0;
GLuint color_mask = 0;
GLint ret, i;
if ( R200_DEBUG & DEBUG_IOCTL ) {
fprintf( stderr, "%s: all=%d cx=%d cy=%d cw=%d ch=%d\n",
__FUNCTION__, all, cx, cy, cw, ch );
}
{
LOCK_HARDWARE( rmesa );
UNLOCK_HARDWARE( rmesa );
if ( dPriv->numClipRects == 0 )
return;
}
r200EmitState( rmesa );
/* Need to cope with lostcontext here as kernel relies on
* some residual state:
*/
R200_FIREVERTICES( rmesa );
if ( mask & DD_FRONT_LEFT_BIT ) {
flags |= RADEON_FRONT;
color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
mask &= ~DD_FRONT_LEFT_BIT;
}
if ( mask & DD_BACK_LEFT_BIT ) {
flags |= RADEON_BACK;
color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
mask &= ~DD_BACK_LEFT_BIT;
}
if ( mask & DD_DEPTH_BIT ) {
if ( ctx->Depth.Mask ) flags |= RADEON_DEPTH; /* FIXME: ??? */
mask &= ~DD_DEPTH_BIT;
}
if ( (mask & DD_STENCIL_BIT) && rmesa->state.stencil.hwBuffer ) {
flags |= RADEON_STENCIL;
mask &= ~DD_STENCIL_BIT;
}
if ( mask )
_swrast_Clear( ctx, mask, all, cx, cy, cw, ch );
if ( !flags )
return;
/* Flip top to bottom */
cx += dPriv->x;
cy = dPriv->y + dPriv->h - cy - ch;
LOCK_HARDWARE( rmesa );
/* Throttle the number of clear ioctls we do.
*/
while ( 1 ) {
drmRadeonGetParam gp;
int ret;
int clear;
gp.param = RADEON_PARAM_LAST_CLEAR;
gp.value = (int *)&clear;
ret = drmCommandWriteRead( rmesa->dri.fd,
DRM_RADEON_GETPARAM, &gp, sizeof(gp) );
if ( ret ) {
fprintf( stderr, "%s: drmRadeonGetParam: %d\n", __FUNCTION__, ret );
exit(1);
}
/* Clear throttling needs more thought.
*/
if ( rmesa->sarea->last_clear - clear <= 25 ) {
break;
}
if (rmesa->do_usleeps) {
UNLOCK_HARDWARE( rmesa );
do_usleep(1, __FUNCTION__);
LOCK_HARDWARE( rmesa );
}
}
for ( i = 0 ; i < dPriv->numClipRects ; ) {
GLint nr = MIN2( i + RADEON_NR_SAREA_CLIPRECTS, dPriv->numClipRects );
XF86DRIClipRectPtr box = dPriv->pClipRects;
XF86DRIClipRectPtr b = rmesa->sarea->boxes;
drmRadeonClearType clear;
drmRadeonClearRect depth_boxes[RADEON_NR_SAREA_CLIPRECTS];
GLint n = 0;
if ( !all ) {
for ( ; i < nr ; i++ ) {
GLint x = box[i].x1;
GLint y = box[i].y1;
GLint w = box[i].x2 - x;
GLint h = box[i].y2 - y;
if ( x < cx ) w -= cx - x, x = cx;
if ( y < cy ) h -= cy - y, y = cy;
if ( x + w > cx + cw ) w = cx + cw - x;
if ( y + h > cy + ch ) h = cy + ch - y;
if ( w <= 0 ) continue;
if ( h <= 0 ) continue;
b->x1 = x;
b->y1 = y;
b->x2 = x + w;
b->y2 = y + h;
b++;
n++;
}
} else {
for ( ; i < nr ; i++ ) {
*b++ = box[i];
n++;
}
}
rmesa->sarea->nbox = n;
clear.flags = flags;
clear.clear_color = rmesa->state.color.clear;
clear.clear_depth = 0; /* not used */
clear.color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
clear.depth_mask = rmesa->state.stencil.clear;
clear.depth_boxes = depth_boxes;
n--;
b = rmesa->sarea->boxes;
for ( ; n >= 0 ; n-- ) {
depth_boxes[n].f[RADEON_CLEAR_X1] = (float)b[n].x1;
depth_boxes[n].f[RADEON_CLEAR_Y1] = (float)b[n].y1;
depth_boxes[n].f[RADEON_CLEAR_X2] = (float)b[n].x2;
depth_boxes[n].f[RADEON_CLEAR_Y2] = (float)b[n].y2;
depth_boxes[n].f[RADEON_CLEAR_DEPTH] = ctx->Depth.Clear;
}
ret = drmCommandWrite( rmesa->dri.fd, DRM_RADEON_CLEAR,
&clear, sizeof(drmRadeonClearType));
if ( ret ) {
UNLOCK_HARDWARE( rmesa );
fprintf( stderr, "DRM_RADEON_CLEAR: return = %d\n", ret );
exit( 1 );
}
}
UNLOCK_HARDWARE( rmesa );
rmesa->lost_context = 1;
}
void r200WaitForIdleLocked( r200ContextPtr rmesa )
{
int ret;
int i = 0;
do {
ret = drmCommandNone( rmesa->dri.fd, DRM_RADEON_CP_IDLE);
if (ret)
do_usleep( 1, __FUNCTION__ );
} while (ret && ++i < 100);
if ( ret < 0 ) {
UNLOCK_HARDWARE( rmesa );
fprintf( stderr, "Error: R200 timed out... exiting\n" );
exit( -1 );
}
}
static void r200WaitForIdle( r200ContextPtr rmesa )
{
LOCK_HARDWARE(rmesa);
r200WaitForIdleLocked( rmesa );
UNLOCK_HARDWARE(rmesa);
}
void r200WaitForVBlank( r200ContextPtr rmesa )
{
#if 0
drmVBlank vbl;
int ret;
if ( !rmesa->r200Screen->irq )
return;
if ( getenv("LIBGL_SYNC_REFRESH") ) {
/* Wait for until the next vertical blank */
vbl.request.type = DRM_VBLANK_RELATIVE;
vbl.request.sequence = 1;
} else if ( getenv("LIBGL_THROTTLE_REFRESH") ) {
/* Wait for at least one vertical blank since the last call */
vbl.request.type = DRM_VBLANK_ABSOLUTE;
vbl.request.sequence = rmesa->vbl_seq + 1;
} else {
return;
}
UNLOCK_HARDWARE( rmesa );
if ((ret = drmWaitVBlank( rmesa->dri.fd, &vbl ))) {
fprintf(stderr, "%s: drmWaitVBlank returned %d, IRQs don't seem to be"
" working correctly.\nTry running with LIBGL_THROTTLE_REFRESH"
" and LIBL_SYNC_REFRESH unset.\n", __FUNCTION__, ret);
exit(1);
} else if (R200_DEBUG & DEBUG_IOCTL)
fprintf(stderr, "%s: drmWaitVBlank returned %d\n", __FUNCTION__, ret);
rmesa->vbl_seq = vbl.reply.sequence;
LOCK_HARDWARE( rmesa );
#endif
}
void r200Flush( GLcontext *ctx )
{
r200ContextPtr rmesa = R200_CONTEXT( ctx );
if (R200_DEBUG & DEBUG_IOCTL)
fprintf(stderr, "%s\n", __FUNCTION__);
if (rmesa->dma.flush)
rmesa->dma.flush( rmesa );
if (!is_empty_list(&rmesa->hw.dirty))
r200EmitState( rmesa );
if (rmesa->store.cmd_used)
r200FlushCmdBuf( rmesa, __FUNCTION__ );
}
/* Make sure all commands have been sent to the hardware and have
* completed processing.
*/
void r200Finish( GLcontext *ctx )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
r200Flush( ctx );
if (rmesa->do_irqs) {
LOCK_HARDWARE( rmesa );
r200EmitIrqLocked( rmesa );
UNLOCK_HARDWARE( rmesa );
r200WaitIrq( rmesa );
}
else
r200WaitForIdle( rmesa );
}
/* This version of AllocateMemoryNV allocates only agp memory, and
* only does so after the point at which the driver has been
* initialized.
*
* Theoretically a valid context isn't required. However, in this
* implementation, it is, as I'm using the hardware lock to protect
* the kernel data structures, and the current context to get the
* device fd.
*/
void *r200AllocateMemoryNV(GLsizei size, GLfloat readfreq,
GLfloat writefreq, GLfloat priority)
{
GET_CURRENT_CONTEXT(ctx);
r200ContextPtr rmesa;
int region_offset;
drmRadeonMemAlloc alloc;
int ret;
if (R200_DEBUG & DEBUG_IOCTL)
fprintf(stderr, "%s sz %d %f/%f/%f\n", __FUNCTION__, size, readfreq,
writefreq, priority);
if (!ctx || !(rmesa = R200_CONTEXT(ctx)) || rmesa->r200Screen->IsPCI )
return NULL;
if (getenv("R200_NO_ALLOC"))
return NULL;
if (rmesa->dri.drmMinor < 6)
return NULL;
alloc.region = RADEON_MEM_REGION_AGP;
alloc.alignment = 0;
alloc.size = size;
alloc.region_offset = &region_offset;
ret = drmCommandWriteRead( rmesa->r200Screen->driScreen->fd,
DRM_RADEON_ALLOC,
&alloc, sizeof(alloc));
if (ret) {
fprintf(stderr, "%s: DRM_RADEON_ALLOC ret %d\n", __FUNCTION__, ret);
return NULL;
}
{
char *region_start = (char *)rmesa->r200Screen->agpTextures.map;
return (void *)(region_start + region_offset);
}
}
/* Called via glXFreeMemoryNV() */
void r200FreeMemoryNV(GLvoid *pointer)
{
GET_CURRENT_CONTEXT(ctx);
r200ContextPtr rmesa;
int region_offset;
drmRadeonMemFree memfree;
int ret;
if (R200_DEBUG & DEBUG_IOCTL)
fprintf(stderr, "%s %p\n", __FUNCTION__, pointer);
if (!ctx || !(rmesa = R200_CONTEXT(ctx)) || rmesa->r200Screen->IsPCI ) {
fprintf(stderr, "%s: no context\n", __FUNCTION__);
return;
}
if (rmesa->dri.drmMinor < 6)
return;
region_offset = (char *)pointer - (char *)rmesa->r200Screen->agpTextures.map;
if (region_offset < 0 ||
region_offset > rmesa->r200Screen->agpTextures.size) {
fprintf(stderr, "offset %d outside range 0..%d\n", region_offset,
rmesa->r200Screen->agpTextures.size);
return;
}
memfree.region = RADEON_MEM_REGION_AGP;
memfree.region_offset = region_offset;
ret = drmCommandWrite( rmesa->r200Screen->driScreen->fd,
DRM_RADEON_FREE,
&memfree, sizeof(memfree));
if (ret)
fprintf(stderr, "%s: DRM_RADEON_FREE ret %d\n", __FUNCTION__, ret);
}
/* Called via glXGetAGPOffsetMESA() */
GLuint r200GetAGPOffset(const GLvoid *pointer)
{
GET_CURRENT_CONTEXT(ctx);
r200ContextPtr rmesa;
GLuint card_offset;
if (!ctx || !(rmesa = R200_CONTEXT(ctx)) ) {
fprintf(stderr, "%s: no context\n", __FUNCTION__);
return ~0;
}
if (!r200IsAgpMemory( rmesa, pointer, 0 ))
return ~0;
if (rmesa->dri.drmMinor < 6)
return ~0;
card_offset = r200AgpOffsetFromVirtual( rmesa, pointer );
return card_offset - rmesa->r200Screen->agp_base;
}
GLboolean r200IsAgpMemory( r200ContextPtr rmesa, const GLvoid *pointer,
GLint size )
{
int offset = (char *)pointer - (char *)rmesa->r200Screen->agpTextures.map;
int valid = (size >= 0 &&
offset >= 0 &&
offset + size < rmesa->r200Screen->agpTextures.size);
if (R200_DEBUG & DEBUG_IOCTL)
fprintf(stderr, "r200IsAgpMemory( %p ) : %d\n", pointer, valid );
return valid;
}
GLuint r200AgpOffsetFromVirtual( r200ContextPtr rmesa, const GLvoid *pointer )
{
int offset = (char *)pointer - (char *)rmesa->r200Screen->agpTextures.map;
if (offset < 0 || offset > rmesa->r200Screen->agpTextures.size)
return ~0;
else
return rmesa->r200Screen->agp_texture_offset + offset;
}
void r200InitIoctlFuncs( GLcontext *ctx )
{
ctx->Driver.Clear = r200Clear;
ctx->Driver.Finish = r200Finish;
ctx->Driver.Flush = r200Flush;
}

View File

@@ -0,0 +1,188 @@
/* $XFree86$ */
/*
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
The Weather Channel (TM) funded Tungsten Graphics to develop the
initial release of the Radeon 8500 driver under the XFree86 license.
This notice must be preserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#ifndef __R200_IOCTL_H__
#define __R200_IOCTL_H__
#ifdef GLX_DIRECT_RENDERING
#include "simple_list.h"
#include "radeon_dri.h"
#include "r200_lock.h"
#include "xf86drm.h"
#include "radeon_common.h"
extern void r200EmitState( r200ContextPtr rmesa );
extern void r200EmitVertexAOS( r200ContextPtr rmesa,
GLuint vertex_size,
GLuint offset );
extern void r200EmitVbufPrim( r200ContextPtr rmesa,
GLuint primitive,
GLuint vertex_nr );
extern void r200FlushElts( r200ContextPtr rmesa );
extern GLushort *r200AllocEltsOpenEnded( r200ContextPtr rmesa,
GLuint primitive,
GLuint min_nr );
extern void r200EmitAOS( r200ContextPtr rmesa,
struct r200_dma_region **regions,
GLuint n,
GLuint offset );
extern void r200EmitBlit( r200ContextPtr rmesa,
GLuint color_fmt,
GLuint src_pitch,
GLuint src_offset,
GLuint dst_pitch,
GLuint dst_offset,
GLint srcx, GLint srcy,
GLint dstx, GLint dsty,
GLuint w, GLuint h );
extern void r200EmitWait( r200ContextPtr rmesa, GLuint flags );
extern void r200FlushCmdBuf( r200ContextPtr rmesa, const char * );
extern int r200FlushCmdBufLocked( r200ContextPtr rmesa, const char * caller );
extern void r200RefillCurrentDmaRegion( r200ContextPtr rmesa );
extern void r200AllocDmaRegion( r200ContextPtr rmesa,
struct r200_dma_region *region,
int bytes,
int alignment );
extern void r200AllocDmaRegionVerts( r200ContextPtr rmesa,
struct r200_dma_region *region,
int numverts,
int vertsize,
int alignment );
extern void r200ReleaseDmaRegion( r200ContextPtr rmesa,
struct r200_dma_region *region,
const char *caller );
extern void r200CopyBuffer( const __DRIdrawablePrivate *drawable );
extern void r200PageFlip( const __DRIdrawablePrivate *drawable );
extern void r200Flush( GLcontext *ctx );
extern void r200Finish( GLcontext *ctx );
extern void r200WaitForIdleLocked( r200ContextPtr rmesa );
extern void r200WaitForVBlank( r200ContextPtr rmesa );
extern void r200InitIoctlFuncs( GLcontext *ctx );
extern void *r200AllocateMemoryNV( GLsizei size, GLfloat readfreq,
GLfloat writefreq, GLfloat priority );
extern void r200FreeMemoryNV( GLvoid *pointer );
extern GLuint r200GetAGPOffset( const GLvoid *pointer );
extern GLboolean r200IsAgpMemory( r200ContextPtr rmesa, const GLvoid *pointer,
GLint size );
extern GLuint r200AgpOffsetFromVirtual( r200ContextPtr rmesa,
const GLvoid *pointer );
/* ================================================================
* Helper macros:
*/
/* Close off the last primitive, if it exists.
*/
#define R200_NEWPRIM( rmesa ) \
do { \
if ( rmesa->dma.flush ) \
rmesa->dma.flush( rmesa ); \
} while (0)
/* Can accomodate several state changes and primitive changes without
* actually firing the buffer.
*/
#define R200_STATECHANGE( rmesa, ATOM ) \
do { \
R200_NEWPRIM( rmesa ); \
move_to_head( &(rmesa->hw.dirty), &(rmesa->hw.ATOM)); \
} while (0)
#define R200_DB_STATE( ATOM ) \
memcpy( rmesa->hw.ATOM.lastcmd, rmesa->hw.ATOM.cmd, \
rmesa->hw.ATOM.cmd_size * 4)
static __inline int R200_DB_STATECHANGE(
r200ContextPtr rmesa,
struct r200_state_atom *atom )
{
if (memcmp(atom->cmd, atom->lastcmd, atom->cmd_size*4)) {
int *tmp;
R200_NEWPRIM( rmesa );
move_to_head( &(rmesa->hw.dirty), atom );
tmp = atom->cmd;
atom->cmd = atom->lastcmd;
atom->lastcmd = tmp;
return 1;
}
else
return 0;
}
/* Fire the buffered vertices no matter what.
*/
#define R200_FIREVERTICES( rmesa ) \
do { \
if ( rmesa->store.cmd_used || rmesa->dma.flush ) { \
r200Flush( rmesa->glCtx ); \
} \
} while (0)
/* Alloc space in the command buffer
*/
static __inline char *r200AllocCmdBuf( r200ContextPtr rmesa,
int bytes, const char *where )
{
if (rmesa->store.cmd_used + bytes > R200_CMD_BUF_SZ)
r200FlushCmdBuf( rmesa, __FUNCTION__ );
{
char *head = rmesa->store.cmd_buf + rmesa->store.cmd_used;
rmesa->store.cmd_used += bytes;
return head;
}
}
#endif
#endif /* __R200_IOCTL_H__ */

View File

@@ -0,0 +1,118 @@
/* $XFree86$ */
/*
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
The Weather Channel (TM) funded Tungsten Graphics to develop the
initial release of the Radeon 8500 driver under the XFree86 license.
This notice must be preserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#include "r200_context.h"
#include "r200_lock.h"
#include "r200_tex.h"
#include "r200_state.h"
#include "r200_ioctl.h"
#if DEBUG_LOCKING
char *prevLockFile = NULL;
int prevLockLine = 0;
#endif
/* Turn on/off page flipping according to the flags in the sarea:
*/
static void
r200UpdatePageFlipping( r200ContextPtr rmesa )
{
int use_back;
rmesa->doPageFlip = rmesa->sarea->pfAllowPageFlip;
use_back = (rmesa->glCtx->Color._DrawDestMask == BACK_LEFT_BIT);
use_back ^= (rmesa->sarea->pfCurrentPage == 1);
if (use_back) {
rmesa->state.color.drawOffset = rmesa->r200Screen->backOffset;
rmesa->state.color.drawPitch = rmesa->r200Screen->backPitch;
} else {
rmesa->state.color.drawOffset = rmesa->r200Screen->frontOffset;
rmesa->state.color.drawPitch = rmesa->r200Screen->frontPitch;
}
R200_STATECHANGE( rmesa, ctx );
rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = rmesa->state.color.drawOffset;
rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = rmesa->state.color.drawPitch;
}
/* Update the hardware state. This is called if another context has
* grabbed the hardware lock, which includes the X server. This
* function also updates the driver's window state after the X server
* moves, resizes or restacks a window -- the change will be reflected
* in the drawable position and clip rects. Since the X server grabs
* the hardware lock when it changes the window state, this routine will
* automatically be called after such a change.
*/
void r200GetLock( r200ContextPtr rmesa, GLuint flags )
{
__DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
__DRIscreenPrivate *sPriv = rmesa->dri.screen;
RADEONSAREAPrivPtr sarea = rmesa->sarea;
int i;
drmGetLock( rmesa->dri.fd, rmesa->dri.hwContext, flags );
/* The window might have moved, so we might need to get new clip
* rects.
*
* NOTE: This releases and regrabs the hw lock to allow the X server
* to respond to the DRI protocol request for new drawable info.
* Since the hardware state depends on having the latest drawable
* clip rects, all state checking must be done _after_ this call.
*/
DRI_VALIDATE_DRAWABLE_INFO( sPriv, dPriv );
if ( rmesa->lastStamp != dPriv->lastStamp ) {
r200UpdatePageFlipping( rmesa );
if (rmesa->glCtx->Color._DrawDestMask == BACK_LEFT_BIT)
r200SetCliprects( rmesa, GL_BACK_LEFT );
else
r200SetCliprects( rmesa, GL_FRONT_LEFT );
r200UpdateViewportOffset( rmesa->glCtx );
rmesa->lastStamp = dPriv->lastStamp;
}
if ( sarea->ctxOwner != rmesa->dri.hwContext ) {
sarea->ctxOwner = rmesa->dri.hwContext;
}
for ( i = 0 ; i < rmesa->texture.numHeaps ; i++ ) {
if ( sarea->texAge[i] != rmesa->texture.age[i] ) {
r200AgeTextures( rmesa, i );
}
}
}

View File

@@ -0,0 +1,111 @@
/* $XFree86$ */
/*
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
The Weather Channel (TM) funded Tungsten Graphics to develop the
initial release of the Radeon 8500 driver under the XFree86 license.
This notice must be preserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#ifndef __R200_LOCK_H__
#define __R200_LOCK_H__
#ifdef GLX_DIRECT_RENDERING
extern void r200GetLock( r200ContextPtr rmesa, GLuint flags );
/* Turn DEBUG_LOCKING on to find locking conflicts.
*/
#define DEBUG_LOCKING 0
#if DEBUG_LOCKING
extern char *prevLockFile;
extern int prevLockLine;
#define DEBUG_LOCK() \
do { \
prevLockFile = (__FILE__); \
prevLockLine = (__LINE__); \
} while (0)
#define DEBUG_RESET() \
do { \
prevLockFile = 0; \
prevLockLine = 0; \
} while (0)
#define DEBUG_CHECK_LOCK() \
do { \
if ( prevLockFile ) { \
fprintf( stderr, \
"LOCK SET!\n\tPrevious %s:%d\n\tCurrent: %s:%d\n", \
prevLockFile, prevLockLine, __FILE__, __LINE__ ); \
exit( 1 ); \
} \
} while (0)
#else
#define DEBUG_LOCK()
#define DEBUG_RESET()
#define DEBUG_CHECK_LOCK()
#endif
/*
* !!! We may want to separate locks from locks with validation. This
* could be used to improve performance for those things commands that
* do not do any drawing !!!
*/
/* Lock the hardware and validate our state.
*/
#define LOCK_HARDWARE( rmesa ) \
do { \
char __ret = 0; \
DEBUG_CHECK_LOCK(); \
DRM_CAS( rmesa->dri.hwLock, rmesa->dri.hwContext, \
(DRM_LOCK_HELD | rmesa->dri.hwContext), __ret ); \
if ( __ret ) \
r200GetLock( rmesa, 0 ); \
DEBUG_LOCK(); \
} while (0)
/* Unlock the hardware.
*/
#define UNLOCK_HARDWARE( rmesa ) \
do { \
DRM_UNLOCK( rmesa->dri.fd, \
rmesa->dri.hwLock, \
rmesa->dri.hwContext ); \
DEBUG_RESET(); \
} while (0)
#endif
#endif /* __R200_LOCK_H__ */

View File

@@ -0,0 +1,12 @@
/* If using new packets, can choose either verts or arrays.
* Otherwise, must use verts.
*/
#include "r200_context.h"
#define R200_MAOS_VERTS 0
#if (R200_MAOS_VERTS) || (R200_OLD_PACKETS)
#include "r200_maos_verts.c"
#else
#include "r200_maos_arrays.c"
#endif

View File

@@ -0,0 +1,46 @@
/* $XFree86$ */
/*
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
The Weather Channel (TM) funded Tungsten Graphics to develop the
initial release of the Radeon 8500 driver under the XFree86 license.
This notice must be preserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#ifndef __R200_MAOS_H__
#define __R200_MAOS_H__
#ifdef GLX_DIRECT_RENDERING
#include "r200_context.h"
extern void r200EmitArrays( GLcontext *ctx, GLuint inputs );
extern void r200ReleaseArrays( GLcontext *ctx, GLuint newinputs );
#endif
#endif

View File

@@ -0,0 +1,481 @@
/* $XFree86$ */
/*
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
The Weather Channel (TM) funded Tungsten Graphics to develop the
initial release of the Radeon 8500 driver under the XFree86 license.
This notice must be preserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#include "glheader.h"
#include "mtypes.h"
#include "colormac.h"
#include "imports.h"
#include "mmath.h"
#include "macros.h"
#include "swrast_setup/swrast_setup.h"
#include "math/m_translate.h"
#include "tnl/tnl.h"
#include "tnl/t_context.h"
#include "tnl/t_imm_debug.h"
#include "r200_context.h"
#include "r200_ioctl.h"
#include "r200_state.h"
#include "r200_swtcl.h"
#include "r200_maos.h"
/* Usage:
* - from r200_tcl_render
* - call r200EmitArrays to ensure uptodate arrays in dma
* - emit primitives (new type?) which reference the data
* -- need to use elts for lineloop, quads, quadstrip/flat
* -- other primitives are all well-formed (need tristrip-1,fake-poly)
*
*/
static void emit_ubyte_rgba3( GLcontext *ctx,
struct r200_dma_region *rvb,
char *data,
int stride,
int count )
{
int i;
r200_color_t *out = (r200_color_t *)(rvb->start + rvb->address);
if (R200_DEBUG & DEBUG_VERTS)
fprintf(stderr, "%s count %d stride %d out %p\n",
__FUNCTION__, count, stride, out);
for (i = 0; i < count; i++) {
out->red = *data;
out->green = *(data+1);
out->blue = *(data+2);
out->alpha = 0xFF;
out++;
data += stride;
}
}
#if defined(USE_X86_ASM)
#define COPY_DWORDS( dst, src, nr ) \
do { \
int __tmp; \
__asm__ __volatile__( "rep ; movsl" \
: "=%c" (__tmp), "=D" (dst), "=S" (__tmp) \
: "0" (nr), \
"D" ((long)dst), \
"S" ((long)src) ); \
} while (0)
#else
#define COPY_DWORDS( dst, src, nr ) \
do { \
int j; \
for ( j = 0 ; j < nr ; j++ ) \
dst[j] = ((int *)src)[j]; \
dst += nr; \
} while (0)
#endif
static void emit_ubyte_rgba4( GLcontext *ctx,
struct r200_dma_region *rvb,
char *data,
int stride,
int count )
{
int i;
int *out = (int *)(rvb->address + rvb->start);
if (R200_DEBUG & DEBUG_VERTS)
fprintf(stderr, "%s count %d stride %d\n",
__FUNCTION__, count, stride);
if (stride == 4) {
for (i = 0; i < count; i++)
((int *)out)[i] = LE32_TO_CPU(((int *)data)[i]);
} else {
for (i = 0; i < count; i++) {
*(int *)out++ = LE32_TO_CPU(*(int *)data);
data += stride;
}
}
}
static void emit_ubyte_rgba( GLcontext *ctx,
struct r200_dma_region *rvb,
char *data,
int size,
int stride,
int count )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
if (R200_DEBUG & DEBUG_VERTS)
fprintf(stderr, "%s %d/%d\n", __FUNCTION__, count, size);
assert (!rvb->buf);
if (stride == 0) {
r200AllocDmaRegion( rmesa, rvb, 4, 4 );
count = 1;
rvb->aos_start = GET_START(rvb);
rvb->aos_stride = 0;
rvb->aos_size = 1;
}
else {
r200AllocDmaRegion( rmesa, rvb, 4 * count, 4 ); /* alignment? */
rvb->aos_start = GET_START(rvb);
rvb->aos_stride = 1;
rvb->aos_size = 1;
}
/* Emit the data
*/
switch (size) {
case 3:
emit_ubyte_rgba3( ctx, rvb, data, stride, count );
break;
case 4:
emit_ubyte_rgba4( ctx, rvb, data, stride, count );
break;
default:
assert(0);
exit(1);
break;
}
}
static void emit_vec8( GLcontext *ctx,
struct r200_dma_region *rvb,
char *data,
int stride,
int count )
{
int i;
int *out = (int *)(rvb->address + rvb->start);
if (R200_DEBUG & DEBUG_VERTS)
fprintf(stderr, "%s count %d stride %d\n",
__FUNCTION__, count, stride);
if (stride == 8)
COPY_DWORDS( out, data, count*2 );
else
for (i = 0; i < count; i++) {
out[0] = *(int *)data;
out[1] = *(int *)(data+4);
out += 2;
data += stride;
}
}
static void emit_vec12( GLcontext *ctx,
struct r200_dma_region *rvb,
char *data,
int stride,
int count )
{
int i;
int *out = (int *)(rvb->address + rvb->start);
if (R200_DEBUG & DEBUG_VERTS)
fprintf(stderr, "%s count %d stride %d out %p data %p\n",
__FUNCTION__, count, stride, out, data);
if (stride == 12)
COPY_DWORDS( out, data, count*3 );
else
for (i = 0; i < count; i++) {
out[0] = *(int *)data;
out[1] = *(int *)(data+4);
out[2] = *(int *)(data+8);
out += 3;
data += stride;
}
}
static void emit_vec16( GLcontext *ctx,
struct r200_dma_region *rvb,
char *data,
int stride,
int count )
{
int i;
int *out = (int *)(rvb->address + rvb->start);
if (R200_DEBUG & DEBUG_VERTS)
fprintf(stderr, "%s count %d stride %d\n",
__FUNCTION__, count, stride);
if (stride == 16)
COPY_DWORDS( out, data, count*4 );
else
for (i = 0; i < count; i++) {
out[0] = *(int *)data;
out[1] = *(int *)(data+4);
out[2] = *(int *)(data+8);
out[3] = *(int *)(data+12);
out += 4;
data += stride;
}
}
static void emit_vector( GLcontext *ctx,
struct r200_dma_region *rvb,
char *data,
int size,
int stride,
int count )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
if (R200_DEBUG & DEBUG_VERTS)
fprintf(stderr, "%s count %d size %d stride %d\n",
__FUNCTION__, count, size, stride);
assert (!rvb->buf);
if (stride == 0) {
r200AllocDmaRegion( rmesa, rvb, size * 4, 4 );
count = 1;
rvb->aos_start = GET_START(rvb);
rvb->aos_stride = 0;
rvb->aos_size = size;
}
else {
r200AllocDmaRegion( rmesa, rvb, size * count * 4, 4 ); /* alignment? */
rvb->aos_start = GET_START(rvb);
rvb->aos_stride = size;
rvb->aos_size = size;
}
/* Emit the data
*/
switch (size) {
case 2:
emit_vec8( ctx, rvb, data, stride, count );
break;
case 3:
emit_vec12( ctx, rvb, data, stride, count );
break;
case 4:
emit_vec16( ctx, rvb, data, stride, count );
break;
default:
assert(0);
exit(1);
break;
}
}
/* Emit any changed arrays to new agp memory, re-emit a packet to
* update the arrays.
*/
void r200EmitArrays( GLcontext *ctx, GLuint inputs )
{
r200ContextPtr rmesa = R200_CONTEXT( ctx );
struct vertex_buffer *VB = &TNL_CONTEXT( ctx )->vb;
struct r200_dma_region **component = rmesa->tcl.aos_components;
GLuint nr = 0;
GLuint vfmt0 = 0, vfmt1 = 0;
GLuint count = VB->Count;
if (R200_DEBUG & DEBUG_VERTS)
_tnl_print_vert_flags( __FUNCTION__, inputs );
if (1) {
if (!rmesa->tcl.obj.buf)
emit_vector( ctx,
&rmesa->tcl.obj,
(char *)VB->ObjPtr->data,
VB->ObjPtr->size,
VB->ObjPtr->stride,
count);
switch( VB->ObjPtr->size ) {
case 4: vfmt0 |= R200_VTX_W0;
case 3: vfmt0 |= R200_VTX_Z0;
case 2:
default:
break;
}
component[nr++] = &rmesa->tcl.obj;
}
if (inputs & VERT_BIT_NORMAL) {
if (!rmesa->tcl.norm.buf)
emit_vector( ctx,
&(rmesa->tcl.norm),
(char *)VB->NormalPtr->data,
3,
VB->NormalPtr->stride,
count);
vfmt0 |= R200_VTX_N0;
component[nr++] = &rmesa->tcl.norm;
}
if (inputs & VERT_BIT_COLOR0) {
if (VB->ColorPtr[0]->Type == GL_UNSIGNED_BYTE) {
if (!rmesa->tcl.rgba.buf)
emit_ubyte_rgba( ctx,
&rmesa->tcl.rgba,
(char *)VB->ColorPtr[0]->Ptr,
VB->ColorPtr[0]->Size,
VB->ColorPtr[0]->StrideB,
count);
vfmt0 |= R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT;
}
else {
int emitsize;
if (VB->ColorPtr[0]->Size == 4 &&
(VB->ColorPtr[0]->StrideB != 0 ||
((GLfloat *)VB->ColorPtr[0]->Ptr)[3] != 1.0)) {
vfmt0 |= R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT;
emitsize = 4;
}
else {
vfmt0 |= R200_VTX_FP_RGB << R200_VTX_COLOR_0_SHIFT;
emitsize = 3;
}
if (!rmesa->tcl.rgba.buf)
emit_vector( ctx,
&(rmesa->tcl.rgba),
(char *)VB->ColorPtr[0]->Ptr,
emitsize,
VB->ColorPtr[0]->StrideB,
count);
}
component[nr++] = &rmesa->tcl.rgba;
}
if (inputs & VERT_BIT_COLOR1) {
if (!rmesa->tcl.spec.buf) {
if (VB->SecondaryColorPtr[0]->Type != GL_UNSIGNED_BYTE)
r200_import_float_spec_colors( ctx );
emit_ubyte_rgba( ctx,
&rmesa->tcl.spec,
(char *)VB->SecondaryColorPtr[0]->Ptr,
3,
VB->SecondaryColorPtr[0]->StrideB,
count);
}
/* How does this work?
*/
vfmt0 |= R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT;
component[nr++] = &rmesa->tcl.spec;
}
/* vtx = (rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] & */
/* ~(R200_TCL_VTX_Q0|R200_TCL_VTX_Q1)); */
if (inputs & VERT_BIT_TEX0) {
if (!rmesa->tcl.tex[0].buf)
emit_vector( ctx,
&(rmesa->tcl.tex[0]),
(char *)VB->TexCoordPtr[0]->data,
VB->TexCoordPtr[0]->size,
VB->TexCoordPtr[0]->stride,
count );
vfmt1 |= VB->TexCoordPtr[0]->size << R200_VTX_TEX0_COMP_CNT_SHIFT;
component[nr++] = &rmesa->tcl.tex[0];
}
if (inputs & VERT_BIT_TEX1) {
if (!rmesa->tcl.tex[1].buf)
emit_vector( ctx,
&(rmesa->tcl.tex[1]),
(char *)VB->TexCoordPtr[1]->data,
VB->TexCoordPtr[1]->size,
VB->TexCoordPtr[1]->stride,
count );
vfmt1 |= VB->TexCoordPtr[1]->size << R200_VTX_TEX1_COMP_CNT_SHIFT;
component[nr++] = &rmesa->tcl.tex[1];
}
if (vfmt0 != rmesa->hw.vtx.cmd[VTX_VTXFMT_0] ||
vfmt1 != rmesa->hw.vtx.cmd[VTX_VTXFMT_1]) {
R200_STATECHANGE( rmesa, vtx );
rmesa->hw.vtx.cmd[VTX_VTXFMT_0] = vfmt0;
rmesa->hw.vtx.cmd[VTX_VTXFMT_1] = vfmt1;
}
/* fprintf(stderr, "VTXFMT_0: %x VTXFMT_1: %x\n", vfmt0, vfmt1); */
rmesa->tcl.nr_aos_components = nr;
rmesa->tcl.vertex_format = vfmt0;
}
void r200ReleaseArrays( GLcontext *ctx, GLuint newinputs )
{
r200ContextPtr rmesa = R200_CONTEXT( ctx );
if (R200_DEBUG & DEBUG_VERTS)
_tnl_print_vert_flags( __FUNCTION__, newinputs );
if (newinputs & VERT_BIT_POS)
r200ReleaseDmaRegion( rmesa, &rmesa->tcl.obj, __FUNCTION__ );
if (newinputs & VERT_BIT_NORMAL)
r200ReleaseDmaRegion( rmesa, &rmesa->tcl.norm, __FUNCTION__ );
if (newinputs & VERT_BIT_COLOR0)
r200ReleaseDmaRegion( rmesa, &rmesa->tcl.rgba, __FUNCTION__ );
if (newinputs & VERT_BIT_COLOR1)
r200ReleaseDmaRegion( rmesa, &rmesa->tcl.spec, __FUNCTION__ );
if (newinputs & VERT_BIT_TEX0)
r200ReleaseDmaRegion( rmesa, &rmesa->tcl.tex[0], __FUNCTION__ );
if (newinputs & VERT_BIT_TEX1)
r200ReleaseDmaRegion( rmesa, &rmesa->tcl.tex[1], __FUNCTION__ );
}

View File

@@ -0,0 +1,378 @@
/* $XFree86$ */
/*
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
The Weather Channel (TM) funded Tungsten Graphics to develop the
initial release of the Radeon 8500 driver under the XFree86 license.
This notice must be preserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#ifndef LOCALVARS
#define LOCALVARS
#endif
#undef TCL_DEBUG
#ifndef TCL_DEBUG
#define TCL_DEBUG 0
#endif
static void TAG(emit)( GLcontext *ctx,
GLuint start, GLuint end,
void *dest )
{
LOCALVARS
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
GLuint (*tc0)[4], (*tc1)[4];
GLfloat *fog;
GLuint (*tc2)[4], (*norm)[3];
GLubyte (*col)[4], (*spec)[4];
GLuint tc0_stride, tc1_stride, col_stride, spec_stride, fog_stride;
GLuint tc2_stride, norm_stride;
GLuint (*coord)[4];
GLuint coord_stride;
GLubyte dummy[4];
int i;
union emit_union *v = (union emit_union *)dest;
if (R200_DEBUG & DEBUG_VERTS)
fprintf(stderr, "%s\n", __FUNCTION__);
/* The vertex code expects Obj to be clean to element 3. To fix
* this, add more vertex code (for obj-2, obj-3) or preferably move
* to maos.
*/
if (VB->ObjPtr->size < 3) {
if (VB->ObjPtr->flags & VEC_NOT_WRITEABLE) {
VB->import_data( ctx, VERT_OBJ, VEC_NOT_WRITEABLE );
}
_mesa_vector4f_clean_elem( VB->ObjPtr, VB->Count, 2 );
}
if (DO_W && VB->ObjPtr->size < 4) {
if (VB->ObjPtr->flags & VEC_NOT_WRITEABLE) {
VB->import_data( ctx, VERT_OBJ, VEC_NOT_WRITEABLE );
}
_mesa_vector4f_clean_elem( VB->ObjPtr, VB->Count, 3 );
}
coord = (GLuint (*)[4])VB->ObjPtr->data;
coord_stride = VB->ObjPtr->stride;
if (DO_TEX2) {
const GLuint t2 = GET_TEXSOURCE(2);
tc2 = (GLuint (*)[4])VB->TexCoordPtr[t2]->data;
tc2_stride = VB->TexCoordPtr[t2]->stride;
if (DO_PTEX && VB->TexCoordPtr[t2]->size < 4) {
if (VB->TexCoordPtr[t2]->flags & VEC_NOT_WRITEABLE) {
VB->import_data( ctx, VERT_TEX2, VEC_NOT_WRITEABLE );
}
_mesa_vector4f_clean_elem( VB->TexCoordPtr[t2], VB->Count, 3 );
}
}
if (DO_TEX1) {
if (VB->TexCoordPtr[1]) {
const GLuint t1 = GET_TEXSOURCE(1);
tc1 = (GLuint (*)[4])VB->TexCoordPtr[t1]->data;
tc1_stride = VB->TexCoordPtr[t1]->stride;
if (DO_PTEX && VB->TexCoordPtr[t1]->size < 4) {
if (VB->TexCoordPtr[t1]->flags & VEC_NOT_WRITEABLE) {
VB->import_data( ctx, VERT_TEX1, VEC_NOT_WRITEABLE );
}
_mesa_vector4f_clean_elem( VB->TexCoordPtr[t1], VB->Count, 3 );
}
} else {
tc1 = (GLuint (*)[4])&ctx->Current.Texcoord[1]; /* could be anything, really */
tc1_stride = 0;
}
}
if (DO_TEX0) {
if (VB->TexCoordPtr[0]) {
const GLuint t0 = GET_TEXSOURCE(0);
tc0_stride = VB->TexCoordPtr[t0]->stride;
tc0 = (GLuint (*)[4])VB->TexCoordPtr[t0]->data;
if (DO_PTEX && VB->TexCoordPtr[t0]->size < 4) {
if (VB->TexCoordPtr[t0]->flags & VEC_NOT_WRITEABLE) {
VB->import_data( ctx, VERT_TEX0, VEC_NOT_WRITEABLE );
}
_mesa_vector4f_clean_elem( VB->TexCoordPtr[t0], VB->Count, 3 );
}
} else {
tc0 = (GLuint (*)[4])&ctx->Current.Texcoord[0]; /* could be anything, really */
tc0_stride = 0;
}
}
if (DO_NORM) {
if (VB->NormalPtr) {
norm_stride = VB->NormalPtr->stride;
norm = (GLuint (*)[3])VB->NormalPtr->data;
} else {
norm_stride = 0;
norm = (GLuint (*)[3])&ctx->Current.Normal;
}
}
if (DO_RGBA) {
if (VB->ColorPtr[0]) {
/* This is incorrect when colormaterial is enabled:
*/
if (VB->ColorPtr[0]->Type != GL_UNSIGNED_BYTE) {
if (0) fprintf(stderr, "IMPORTING FLOAT COLORS\n");
IMPORT_FLOAT_COLORS( ctx );
}
col = (GLubyte (*)[4])VB->ColorPtr[0]->Ptr;
col_stride = VB->ColorPtr[0]->StrideB;
} else {
col = &dummy; /* any old memory is fine */
col_stride = 0;
}
}
if (DO_SPEC) {
if (VB->SecondaryColorPtr[0]) {
if (VB->SecondaryColorPtr[0]->Type != GL_UNSIGNED_BYTE)
IMPORT_FLOAT_SPEC_COLORS( ctx );
spec = (GLubyte (*)[4])VB->SecondaryColorPtr[0]->Ptr;
spec_stride = VB->SecondaryColorPtr[0]->StrideB;
} else {
spec = &dummy;
spec_stride = 0;
}
}
if (DO_FOG) {
if (VB->FogCoordPtr) {
fog = VB->FogCoordPtr->data;
fog_stride = VB->FogCoordPtr->stride;
} else {
fog = (GLfloat *)&dummy; *fog = 0;
fog_stride = 0;
}
}
if (VB->importable_data) {
if (start) {
coord = (GLuint (*)[4])((GLubyte *)coord + start * coord_stride);
if (DO_TEX0)
tc0 = (GLuint (*)[4])((GLubyte *)tc0 + start * tc0_stride);
if (DO_TEX1)
tc1 = (GLuint (*)[4])((GLubyte *)tc1 + start * tc1_stride);
if (DO_TEX2)
tc2 = (GLuint (*)[4])((GLubyte *)tc2 + start * tc2_stride);
if (DO_NORM)
norm = (GLuint (*)[3])((GLubyte *)norm + start * norm_stride);
if (DO_RGBA)
STRIDE_4UB(col, start * col_stride);
if (DO_SPEC)
STRIDE_4UB(spec, start * spec_stride);
if (DO_FOG)
STRIDE_F(fog, start * fog_stride);
}
for (i=start; i < end; i++) {
v[0].ui = coord[0][0];
v[1].ui = coord[0][1];
v[2].ui = coord[0][2];
if (TCL_DEBUG) fprintf(stderr, "%d: %.2f %.2f %.2f ", i, v[0].f, v[1].f, v[2].f);
if (DO_W) {
v[3].ui = coord[0][3];
if (TCL_DEBUG) fprintf(stderr, "%.2f ", v[3].f);
v += 4;
}
else
v += 3;
coord = (GLuint (*)[4])((GLubyte *)coord + coord_stride);
if (DO_NORM) {
v[0].ui = norm[0][0];
v[1].ui = norm[0][1];
v[2].ui = norm[0][2];
if (TCL_DEBUG) fprintf(stderr, "norm: %.2f %.2f %.2f ", v[0].f, v[1].f, v[2].f);
v += 3;
norm = (GLuint (*)[3])((GLubyte *)norm + norm_stride);
}
if (DO_RGBA) {
v[0].ui = LE32_TO_CPU(*(GLuint *)&col[0]);
STRIDE_4UB(col, col_stride);
if (TCL_DEBUG) fprintf(stderr, "%x ", v[0].ui);
v++;
}
if (DO_SPEC || DO_FOG) {
if (DO_SPEC) {
v[0].ub[0] = spec[0][0];
v[0].ub[1] = spec[0][1];
v[0].ub[2] = spec[0][2];
STRIDE_4UB(spec, spec_stride);
}
if (DO_FOG) {
v[0].ub[3] = fog[0] * 255.0;
STRIDE_F(fog, fog_stride);
}
if (TCL_DEBUG) fprintf(stderr, "%x ", v[0].ui);
v++;
}
if (DO_TEX0) {
v[0].ui = tc0[0][0];
v[1].ui = tc0[0][1];
if (TCL_DEBUG) fprintf(stderr, "t0: %.2f %.2f ", v[0].f, v[1].f);
if (DO_PTEX) {
v[2].ui = tc0[0][3];
if (TCL_DEBUG) fprintf(stderr, "%.2f ", v[2].f);
v += 3;
}
else
v += 2;
tc0 = (GLuint (*)[4])((GLubyte *)tc0 + tc0_stride);
}
if (DO_TEX1) {
v[0].ui = tc1[0][0];
v[1].ui = tc1[0][1];
if (TCL_DEBUG) fprintf(stderr, "t1: %.2f %.2f ", v[0].f, v[1].f);
if (DO_PTEX) {
v[2].ui = tc1[0][3];
if (TCL_DEBUG) fprintf(stderr, "%.2f ", v[2].f);
v += 3;
}
else
v += 2;
tc1 = (GLuint (*)[4])((GLubyte *)tc1 + tc1_stride);
}
if (DO_TEX2) {
v[0].ui = tc2[0][0];
v[1].ui = tc2[0][1];
if (DO_PTEX) {
v[2].ui = tc2[0][3];
v += 3;
}
else
v += 2;
tc2 = (GLuint (*)[4])((GLubyte *)tc2 + tc2_stride);
}
if (TCL_DEBUG) fprintf(stderr, "\n");
}
} else {
for (i=start; i < end; i++) {
v[0].ui = coord[i][0];
v[1].ui = coord[i][1];
v[2].ui = coord[i][2];
if (DO_W) {
v[3].ui = coord[i][3];
v += 4;
}
else
v += 3;
if (DO_NORM) {
v[0].ui = norm[i][0];
v[1].ui = norm[i][1];
v[2].ui = norm[i][2];
v += 3;
}
if (DO_RGBA) {
v[0].ui = LE32_TO_CPU(*(GLuint *)&col[i]);
v++;
}
if (DO_SPEC || DO_FOG) {
if (DO_SPEC) {
v[0].ub[0] = spec[i][0];
v[0].ub[1] = spec[i][1];
v[0].ub[2] = spec[i][2];
}
if (DO_FOG) {
v[0].ub[3] = fog[i] * 255.0;
}
v++;
}
if (DO_TEX0) {
v[0].ui = tc0[i][0];
v[1].ui = tc0[i][1];
if (DO_PTEX) {
v[2].ui = tc0[i][3];
v += 3;
}
else
v += 2;
}
if (DO_TEX1) {
v[0].ui = tc1[i][0];
v[1].ui = tc1[i][1];
if (DO_PTEX) {
v[2].ui = tc1[i][3];
v += 3;
}
else
v += 2;
}
if (DO_TEX2) {
v[0].ui = tc2[i][0];
v[1].ui = tc2[i][1];
if (DO_PTEX) {
v[2].ui = tc2[i][3];
v += 3;
}
else
v += 2;
}
}
}
}
static void TAG(init)( void )
{
int sz = 3;
if (DO_W) sz++;
if (DO_NORM) sz += 3;
if (DO_RGBA) sz++;
if (DO_SPEC || DO_FOG) sz++;
if (DO_TEX0) sz += 2;
if (DO_TEX0 && DO_PTEX) sz++;
if (DO_TEX1) sz += 2;
if (DO_TEX1 && DO_PTEX) sz++;
if (DO_TEX2) sz += 2;
if (DO_TEX2 && DO_PTEX) sz++;
setup_tab[IDX].emit = TAG(emit);
setup_tab[IDX].vertex_format = IND;
setup_tab[IDX].vertex_size = sz;
}
#undef IND
#undef TAG
#undef IDX

View File

@@ -0,0 +1,338 @@
/* $XFree86$ */
/*
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
The Weather Channel (TM) funded Tungsten Graphics to develop the
initial release of the Radeon 8500 driver under the XFree86 license.
This notice must be preserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#include "glheader.h"
#include "imports.h"
#include "mmath.h"
#include "mtypes.h"
#include "enums.h"
#include "colormac.h"
#include "light.h"
#include "array_cache/acache.h"
#include "tnl/tnl.h"
#include "tnl/t_pipeline.h"
#include "tnl/t_imm_debug.h"
#include "r200_context.h"
#include "r200_state.h"
#include "r200_ioctl.h"
#include "r200_tex.h"
#include "r200_tcl.h"
#include "r200_swtcl.h"
#include "r200_maos.h"
#define R200_TCL_MAX_SETUP 13
union emit_union { float f; GLuint ui; GLubyte ub[4]; };
static struct {
void (*emit)( GLcontext *, GLuint, GLuint, void * );
GLuint vertex_size;
GLuint vertex_format;
} setup_tab[R200_TCL_MAX_SETUP];
#define DO_W (IND & R200_CP_VC_FRMT_W0)
#define DO_RGBA (IND & R200_CP_VC_FRMT_PKCOLOR)
#define DO_SPEC (IND & R200_CP_VC_FRMT_PKSPEC)
#define DO_FOG (IND & R200_CP_VC_FRMT_PKSPEC)
#define DO_TEX0 (IND & R200_CP_VC_FRMT_ST0)
#define DO_TEX1 (IND & R200_CP_VC_FRMT_ST1)
#define DO_PTEX (IND & R200_CP_VC_FRMT_Q0)
#define DO_NORM (IND & R200_CP_VC_FRMT_N0)
#define DO_TEX2 0
#define DO_TEX3 0
#define GET_TEXSOURCE(n) n
#define GET_UBYTE_COLOR_STORE() &R200_CONTEXT(ctx)->UbyteColor
#define GET_UBYTE_SPEC_COLOR_STORE() &R200_CONTEXT(ctx)->UbyteSecondaryColor
#define IMPORT_FLOAT_COLORS r200_import_float_colors
#define IMPORT_FLOAT_SPEC_COLORS r200_import_float_spec_colors
/***********************************************************************
* Generate vertex emit functions *
***********************************************************************/
/* Defined in order of increasing vertex size:
*/
#define IDX 0
#define IND (R200_CP_VC_FRMT_XY| \
R200_CP_VC_FRMT_Z| \
R200_CP_VC_FRMT_PKCOLOR)
#define TAG(x) x##_rgba
#include "r200_maos_vbtmp.h"
#define IDX 1
#define IND (R200_CP_VC_FRMT_XY| \
R200_CP_VC_FRMT_Z| \
R200_CP_VC_FRMT_N0)
#define TAG(x) x##_n
#include "r200_maos_vbtmp.h"
#define IDX 2
#define IND (R200_CP_VC_FRMT_XY| \
R200_CP_VC_FRMT_Z| \
R200_CP_VC_FRMT_PKCOLOR| \
R200_CP_VC_FRMT_ST0)
#define TAG(x) x##_rgba_st
#include "r200_maos_vbtmp.h"
#define IDX 3
#define IND (R200_CP_VC_FRMT_XY| \
R200_CP_VC_FRMT_Z| \
R200_CP_VC_FRMT_PKCOLOR| \
R200_CP_VC_FRMT_N0)
#define TAG(x) x##_rgba_n
#include "r200_maos_vbtmp.h"
#define IDX 4
#define IND (R200_CP_VC_FRMT_XY| \
R200_CP_VC_FRMT_Z| \
R200_CP_VC_FRMT_ST0| \
R200_CP_VC_FRMT_N0)
#define TAG(x) x##_st_n
#include "r200_maos_vbtmp.h"
#define IDX 5
#define IND (R200_CP_VC_FRMT_XY| \
R200_CP_VC_FRMT_Z| \
R200_CP_VC_FRMT_PKCOLOR| \
R200_CP_VC_FRMT_ST0| \
R200_CP_VC_FRMT_ST1)
#define TAG(x) x##_rgba_st_st
#include "r200_maos_vbtmp.h"
#define IDX 6
#define IND (R200_CP_VC_FRMT_XY| \
R200_CP_VC_FRMT_Z| \
R200_CP_VC_FRMT_PKCOLOR| \
R200_CP_VC_FRMT_ST0| \
R200_CP_VC_FRMT_N0)
#define TAG(x) x##_rgba_st_n
#include "r200_maos_vbtmp.h"
#define IDX 7
#define IND (R200_CP_VC_FRMT_XY| \
R200_CP_VC_FRMT_Z| \
R200_CP_VC_FRMT_PKCOLOR| \
R200_CP_VC_FRMT_PKSPEC| \
R200_CP_VC_FRMT_ST0| \
R200_CP_VC_FRMT_ST1)
#define TAG(x) x##_rgba_spec_st_st
#include "r200_maos_vbtmp.h"
#define IDX 8
#define IND (R200_CP_VC_FRMT_XY| \
R200_CP_VC_FRMT_Z| \
R200_CP_VC_FRMT_ST0| \
R200_CP_VC_FRMT_ST1| \
R200_CP_VC_FRMT_N0)
#define TAG(x) x##_st_st_n
#include "r200_maos_vbtmp.h"
#define IDX 9
#define IND (R200_CP_VC_FRMT_XY| \
R200_CP_VC_FRMT_Z| \
R200_CP_VC_FRMT_PKCOLOR| \
R200_CP_VC_FRMT_PKSPEC| \
R200_CP_VC_FRMT_ST0| \
R200_CP_VC_FRMT_ST1| \
R200_CP_VC_FRMT_N0)
#define TAG(x) x##_rgpa_spec_st_st_n
#include "r200_maos_vbtmp.h"
#define IDX 10
#define IND (R200_CP_VC_FRMT_XY| \
R200_CP_VC_FRMT_Z| \
R200_CP_VC_FRMT_PKCOLOR| \
R200_CP_VC_FRMT_ST0| \
R200_CP_VC_FRMT_Q0)
#define TAG(x) x##_rgba_stq
#include "r200_maos_vbtmp.h"
#define IDX 11
#define IND (R200_CP_VC_FRMT_XY| \
R200_CP_VC_FRMT_Z| \
R200_CP_VC_FRMT_PKCOLOR| \
R200_CP_VC_FRMT_ST1| \
R200_CP_VC_FRMT_Q1| \
R200_CP_VC_FRMT_ST0| \
R200_CP_VC_FRMT_Q0)
#define TAG(x) x##_rgba_stq_stq
#include "r200_maos_vbtmp.h"
#define IDX 12
#define IND (R200_CP_VC_FRMT_XY| \
R200_CP_VC_FRMT_Z| \
R200_CP_VC_FRMT_W0| \
R200_CP_VC_FRMT_PKCOLOR| \
R200_CP_VC_FRMT_PKSPEC| \
R200_CP_VC_FRMT_ST0| \
R200_CP_VC_FRMT_Q0| \
R200_CP_VC_FRMT_ST1| \
R200_CP_VC_FRMT_Q1| \
R200_CP_VC_FRMT_N0)
#define TAG(x) x##_w_rgpa_spec_stq_stq_n
#include "r200_maos_vbtmp.h"
/***********************************************************************
* Initialization
***********************************************************************/
static void init_tcl_verts( void )
{
init_rgba();
init_n();
init_rgba_n();
init_rgba_st();
init_st_n();
init_rgba_st_st();
init_rgba_st_n();
init_rgba_spec_st_st();
init_st_st_n();
init_rgpa_spec_st_st_n();
init_rgba_stq();
init_rgba_stq_stq();
init_w_rgpa_spec_stq_stq_n();
}
void r200EmitArrays( GLcontext *ctx, GLuint inputs )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
GLuint req = 0;
GLuint vtx = (rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &
~(R200_TCL_VTX_Q0|R200_TCL_VTX_Q1));
int i;
static int firsttime = 1;
if (firsttime) {
init_tcl_verts();
firsttime = 0;
}
if (1) {
req |= R200_CP_VC_FRMT_Z;
if (VB->ObjPtr->size == 4) {
req |= R200_CP_VC_FRMT_W0;
}
}
if (inputs & VERT_BIT_NORMAL) {
req |= R200_CP_VC_FRMT_N0;
}
if (inputs & VERT_BIT_COLOR0) {
req |= R200_CP_VC_FRMT_PKCOLOR;
}
if (inputs & VERT_BIT_COLOR1) {
req |= R200_CP_VC_FRMT_PKSPEC;
}
if (inputs & VERT_BIT_TEX0) {
req |= R200_CP_VC_FRMT_ST0;
if (VB->TexCoordPtr[0]->size == 4) {
req |= R200_CP_VC_FRMT_Q0;
vtx |= R200_TCL_VTX_Q0;
}
}
if (inputs & VERT_BIT_TEX1) {
req |= R200_CP_VC_FRMT_ST1;
if (VB->TexCoordPtr[1]->size == 4) {
req |= R200_CP_VC_FRMT_Q1;
vtx |= R200_TCL_VTX_Q1;
}
}
if (vtx != rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT]) {
R200_STATECHANGE( rmesa, tcl );
rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] = vtx;
}
for (i = 0 ; i < R200_TCL_MAX_SETUP ; i++)
if ((setup_tab[i].vertex_format & req) == req)
break;
if (rmesa->tcl.vertex_format == setup_tab[i].vertex_format &&
rmesa->tcl.indexed_verts.buf)
return;
if (rmesa->tcl.indexed_verts.buf)
r200ReleaseArrays( ctx, ~0 );
r200AllocDmaRegionVerts( rmesa,
&rmesa->tcl.indexed_verts,
VB->Count,
setup_tab[i].vertex_size * 4,
4);
setup_tab[i].emit( ctx, 0, VB->Count,
rmesa->tcl.indexed_verts.address +
rmesa->tcl.indexed_verts.start );
rmesa->tcl.vertex_format = setup_tab[i].vertex_format;
rmesa->tcl.indexed_verts.aos_start = GET_START( &rmesa->tcl.indexed_verts );
rmesa->tcl.indexed_verts.aos_size = setup_tab[i].vertex_size;
rmesa->tcl.indexed_verts.aos_stride = setup_tab[i].vertex_size;
rmesa->tcl.aos_components[0] = &rmesa->tcl.indexed_verts;
rmesa->tcl.nr_aos_components = 1;
}
void r200ReleaseArrays( GLcontext *ctx, GLuint newinputs )
{
r200ContextPtr rmesa = R200_CONTEXT( ctx );
if (R200_DEBUG & DEBUG_VERTS)
_tnl_print_vert_flags( __FUNCTION__, newinputs );
if (newinputs)
r200ReleaseDmaRegion( rmesa, &rmesa->tcl.indexed_verts, __FUNCTION__ );
}

View File

@@ -0,0 +1,494 @@
/* $XFree86$ */
/*
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
The Weather Channel (TM) funded Tungsten Graphics to develop the
initial release of the Radeon 8500 driver under the XFree86 license.
This notice must be preserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#include "glheader.h"
#include "enums.h"
#include "mtypes.h"
#include "macros.h"
#include "texutil.h"
#include "swrast/swrast.h"
#include "r200_context.h"
#include "r200_ioctl.h"
#include "r200_pixel.h"
#include "r200_swtcl.h"
static GLboolean
check_color( const GLcontext *ctx, GLenum type, GLenum format,
const struct gl_pixelstore_attrib *packing,
const void *pixels, GLint sz, GLint pitch )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
GLuint cpp = rmesa->r200Screen->cpp;
if (R200_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
if ( (pitch & 63) ||
ctx->_ImageTransferState ||
packing->SwapBytes ||
packing->LsbFirst) {
if (R200_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s: failed 1\n", __FUNCTION__);
return GL_FALSE;
}
if ( type == GL_UNSIGNED_INT_8_8_8_8_REV &&
cpp == 4 &&
format == GL_BGRA ) {
if (R200_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s: passed 2\n", __FUNCTION__);
return GL_TRUE;
}
if (R200_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s: failed\n", __FUNCTION__);
return GL_FALSE;
}
static GLboolean
check_color_per_fragment_ops( const GLcontext *ctx )
{
int result;
result = (!( 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->Depth.OcclusionTest
) &&
ctx->Current.RasterPosValid);
return result;
}
static GLboolean
clip_pixelrect( const GLcontext *ctx,
const GLframebuffer *buffer,
GLint *x, GLint *y,
GLsizei *width, GLsizei *height,
GLint *size )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
/* left clipping */
if (*x < buffer->_Xmin) {
*width -= (buffer->_Xmin - *x);
*x = buffer->_Xmin;
}
/* right clipping */
if (*x + *width > buffer->_Xmax)
*width -= (*x + *width - buffer->_Xmax - 1);
if (*width <= 0)
return GL_FALSE;
/* bottom clipping */
if (*y < buffer->_Ymin) {
*height -= (buffer->_Ymin - *y);
*y = buffer->_Ymin;
}
/* top clipping */
if (*y + *height > buffer->_Ymax)
*height -= (*y + *height - buffer->_Ymax - 1);
if (*height <= 0)
return GL_FALSE;
*size = ((*y + *height - 1) * rmesa->r200Screen->frontPitch +
(*x + *width - 1) * rmesa->r200Screen->cpp);
return GL_TRUE;
}
static GLboolean
r200TryReadPixels( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *pack,
GLvoid *pixels )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
GLint size;
GLint pitch = pack->RowLength ? pack->RowLength : width;
GLint blit_format;
if (R200_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
/* Only accelerate reading to agp buffers.
*/
if ( !r200IsAgpMemory(rmesa, pixels,
pitch * height * rmesa->r200Screen->cpp ) ) {
if (R200_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s: dest not agp\n", __FUNCTION__);
return GL_FALSE;
}
/* Need GL_PACK_INVERT_MESA to cope with upsidedown results from
* blitter:
*/
if (!pack->Invert) {
if (R200_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s: MESA_PACK_INVERT not set\n", __FUNCTION__);
return GL_FALSE;
}
if (!check_color(ctx, type, format, pack, pixels, size, pitch))
return GL_FALSE;
switch ( rmesa->r200Screen->cpp ) {
case 4:
blit_format = R200_CP_COLOR_FORMAT_ARGB8888;
break;
default:
return GL_FALSE;
}
/* Although the blits go on the command buffer, need to do this and
* fire with lock held to guarentee cliprects and drawOffset are
* correct.
*
* This is an unusual situation however, as the code which flushes
* a full command buffer expects to be called unlocked. As a
* workaround, immediately flush the buffer on aquiring the lock.
*/
LOCK_HARDWARE( rmesa );
if (rmesa->store.cmd_used)
r200FlushCmdBufLocked( rmesa, __FUNCTION__ );
if (!clip_pixelrect(ctx, ctx->ReadBuffer, &x, &y, &width, &height,
&size)) {
UNLOCK_HARDWARE( rmesa );
if (R200_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s totally clipped -- nothing to do\n",
__FUNCTION__);
return GL_TRUE;
}
{
__DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
int nbox = dPriv->numClipRects;
int src_offset = rmesa->state.color.drawOffset;
int src_pitch = rmesa->state.color.drawPitch * rmesa->r200Screen->cpp;
int dst_offset = r200AgpOffsetFromVirtual( rmesa, pixels);
int dst_pitch = pitch * rmesa->r200Screen->cpp;
XF86DRIClipRectRec *box = dPriv->pClipRects;
int i;
r200EmitWait( rmesa, RADEON_WAIT_3D );
y = dPriv->h - y - height;
x += dPriv->x;
y += dPriv->y;
if (R200_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "readpixel blit src_pitch %d dst_pitch %d\n",
src_pitch, dst_pitch);
for (i = 0 ; i < nbox ; 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;
r200EmitBlit( rmesa,
blit_format,
src_pitch, src_offset,
dst_pitch, dst_offset,
bx, by,
bx - x, by - y,
bw, bh );
}
r200FlushCmdBufLocked( rmesa, __FUNCTION__ );
}
UNLOCK_HARDWARE( rmesa );
r200Finish( ctx ); /* required by GL */
return GL_TRUE;
}
static void
r200ReadPixels( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *pack,
GLvoid *pixels )
{
if (R200_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
if (!r200TryReadPixels( 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)
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
__DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
XF86DRIClipRectPtr box = dPriv->pClipRects;
int nbox = dPriv->numClipRects;
int i;
int blit_format;
int size;
int src_offset = r200AgpOffsetFromVirtual( rmesa, pixels);
int src_pitch = pitch * rmesa->r200Screen->cpp;
if (R200_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
switch ( rmesa->r200Screen->cpp ) {
case 2:
blit_format = R200_CP_COLOR_FORMAT_RGB565;
break;
case 4:
blit_format = R200_CP_COLOR_FORMAT_ARGB8888;
break;
default:
return;
}
LOCK_HARDWARE( rmesa );
if (rmesa->store.cmd_used)
r200FlushCmdBufLocked( rmesa, __FUNCTION__ );
y -= height; /* cope with pixel zoom */
if (!clip_pixelrect(ctx, ctx->DrawBuffer,
&x, &y, &width, &height,
&size)) {
UNLOCK_HARDWARE( rmesa );
return;
}
y = dPriv->h - y - height; /* convert from gl to hardware coords */
x += dPriv->x;
y += dPriv->y;
r200EmitWait( rmesa, RADEON_WAIT_3D );
for (i = 0 ; i < nbox ; 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;
r200EmitBlit( rmesa,
blit_format,
src_pitch, src_offset,
rmesa->state.color.drawPitch * rmesa->r200Screen->cpp,
rmesa->state.color.drawOffset,
bx - x, by - y,
bx, by,
bw, bh );
}
r200FlushCmdBufLocked( rmesa, __FUNCTION__ );
r200WaitForIdleLocked( rmesa ); /* required by GL */
UNLOCK_HARDWARE( rmesa );
}
static GLboolean
r200TryDrawPixels( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
GLint pitch = unpack->RowLength ? unpack->RowLength : width;
GLuint dest, planemask;
GLuint cpp = rmesa->r200Screen->cpp;
GLint size = width * pitch * cpp;
if (R200_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
switch (format) {
case GL_RGB:
case GL_RGBA:
case GL_BGRA:
dest = rmesa->state.color.drawOffset;
planemask = r200PackColor(cpp,
ctx->Color.ColorMask[RCOMP],
ctx->Color.ColorMask[GCOMP],
ctx->Color.ColorMask[BCOMP],
ctx->Color.ColorMask[ACOMP]);
if (cpp == 2)
planemask |= planemask << 16;
if (planemask != ~0)
return GL_FALSE; /* fix me -- should be possible */
/* Can't do conversions on agp reads/draws.
*/
if ( !r200IsAgpMemory( rmesa, pixels, size ) ) {
if (R200_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s: not agp memory\n", __FUNCTION__);
return GL_FALSE;
}
if (!check_color(ctx, type, format, unpack, pixels, size, pitch)) {
return GL_FALSE;
}
if (!check_color_per_fragment_ops(ctx)) {
return GL_FALSE;
}
if (ctx->Pixel.ZoomX != 1.0F ||
ctx->Pixel.ZoomY != -1.0F)
return GL_FALSE;
break;
default:
return GL_FALSE;
}
if ( r200IsAgpMemory(rmesa, pixels, size) )
{
do_draw_pix( ctx, x, y, width, height, pitch, pixels,
dest, planemask );
return GL_TRUE;
}
else if (0)
{
/* Pixels is in regular memory -- get dma buffers and perform
* upload through them.
*/
}
else
return GL_FALSE;
}
static void
r200DrawPixels( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels )
{
if (R200_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
if (!r200TryDrawPixels( ctx, x, y, width, height, format, type,
unpack, pixels ))
_swrast_DrawPixels( ctx, x, y, width, height, format, type,
unpack, pixels );
}
static void
r200Bitmap( GLcontext *ctx, GLint px, GLint py,
GLsizei width, GLsizei height,
const struct gl_pixelstore_attrib *unpack,
const GLubyte *bitmap )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
if (rmesa->Fallback)
_swrast_Bitmap( ctx, px, py, width, height, unpack, bitmap );
else
r200PointsBitmap( ctx, px, py, width, height, unpack, bitmap );
}
void r200InitPixelFuncs( GLcontext *ctx )
{
/* Pixel path fallbacks.
*/
ctx->Driver.Accum = _swrast_Accum;
ctx->Driver.Bitmap = _swrast_Bitmap;
ctx->Driver.CopyPixels = _swrast_CopyPixels;
ctx->Driver.DrawPixels = _swrast_DrawPixels;
ctx->Driver.ReadPixels = _swrast_ReadPixels;
if (!getenv("R200_NO_BLITS") && R200_CONTEXT(ctx)->dri.drmMinor >= 6) {
ctx->Driver.ReadPixels = r200ReadPixels;
ctx->Driver.DrawPixels = r200DrawPixels;
if (getenv("R200_HW_BITMAP"))
ctx->Driver.Bitmap = r200Bitmap;
}
}

View File

@@ -0,0 +1,43 @@
/* $XFree86$ */
/*
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
The Weather Channel (TM) funded Tungsten Graphics to develop the
initial release of the Radeon 8500 driver under the XFree86 license.
This notice must be preserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#ifndef __R200_PIXEL_H__
#define __R200_PIXEL_H__
#ifdef GLX_DIRECT_RENDERING
extern void r200InitPixelFuncs( GLcontext *ctx );
#endif
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
#ifndef R200_SANITY_H
#define R200_SANITY_H
extern int r200SanityCmdBuffer( r200ContextPtr rmesa,
int nbox,
XF86DRIClipRectRec *boxes );
extern int r200ValidateTexObjs( r200ContextPtr rmesa );
#endif

View File

@@ -0,0 +1,434 @@
/* $XFree86$ */
/*
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
The Weather Channel (TM) funded Tungsten Graphics to develop the
initial release of the Radeon 8500 driver under the XFree86 license.
This notice must be preserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#include <dlfcn.h>
#include "glheader.h"
#include "imports.h"
#include "context.h"
#include "r200_screen.h"
#include "r200_context.h"
#include "r200_ioctl.h"
#if 1
/* Including xf86PciInfo.h introduces a bunch of errors...
*/
#define PCI_CHIP_R200_QD 0x5144
#define PCI_CHIP_R200_QE 0x5145
#define PCI_CHIP_R200_QF 0x5146
#define PCI_CHIP_R200_QG 0x5147
#define PCI_CHIP_R200_QY 0x5159
#define PCI_CHIP_R200_QZ 0x515A
#define PCI_CHIP_R200_LW 0x4C57
#define PCI_CHIP_R200_LY 0x4C59
#define PCI_CHIP_R200_LZ 0x4C5A
#define PCI_CHIP_RV200_QW 0x5157
#endif
static r200ScreenPtr __r200Screen;
/* Create the device specific screen private data struct.
*/
static r200ScreenPtr
r200CreateScreen( __DRIscreenPrivate *sPriv )
{
r200ScreenPtr r200Screen;
RADEONDRIPtr r200DRIPriv = (RADEONDRIPtr)sPriv->pDevPriv;
/* Check the DRI extension version */
if ( sPriv->driMajor != 4 || sPriv->driMinor < 0 ) {
__driUtilMessage( "R200 DRI driver expected DRI version 4.0.x "
"but got version %d.%d.%d",
sPriv->driMajor, sPriv->driMinor, sPriv->driPatch );
return NULL;
}
/* Check that the DDX driver version is compatible */
if ( sPriv->ddxMajor != 4 ||
sPriv->ddxMinor < 0 ) {
__driUtilMessage( "R200 DRI driver expected DDX driver version 4.0.x "
"but got version %d.%d.%d",
sPriv->ddxMajor, sPriv->ddxMinor, sPriv->ddxPatch );
return NULL;
}
/* Check that the DRM driver version is compatible
* -- R200 support added at 1.5.0.
*/
if ( sPriv->drmMajor != 1 ||
sPriv->drmMinor < 5) {
__driUtilMessage( "R200 DRI driver expected DRM driver version 1.5.x "
"but got version %d.%d.%d",
sPriv->drmMajor, sPriv->drmMinor, sPriv->drmPatch );
return NULL;
}
/* Allocate the private area */
r200Screen = (r200ScreenPtr) CALLOC( sizeof(*r200Screen) );
if ( !r200Screen ) {
__driUtilMessage("%s: CALLOC r200Screen struct failed",
__FUNCTION__);
return NULL;
}
/* Check if kernel module is new enough to support cube maps */
if (sPriv->drmMajor * 100 + sPriv->drmMinor >= 107)
r200Screen->drmSupportsCubeMaps = GL_TRUE;
else
r200Screen->drmSupportsCubeMaps = GL_FALSE;
switch ( r200DRIPriv->deviceID ) {
case PCI_CHIP_R200_QD:
case PCI_CHIP_R200_QE:
case PCI_CHIP_R200_QF:
case PCI_CHIP_R200_QG:
case PCI_CHIP_R200_QY:
case PCI_CHIP_R200_QZ:
case PCI_CHIP_RV200_QW:
case PCI_CHIP_R200_LW:
case PCI_CHIP_R200_LY:
case PCI_CHIP_R200_LZ:
__driUtilMessage("r200CreateScreen(): Device isn't an r200!\n");
FREE( r200Screen );
return NULL;
default:
r200Screen->chipset = R200_CHIPSET_R200;
break;
}
/* This is first since which regions we map depends on whether or
* not we are using a PCI card.
*/
r200Screen->IsPCI = r200DRIPriv->IsPCI;
{
int ret;
drmRadeonGetParam gp;
gp.param = RADEON_PARAM_AGP_BUFFER_OFFSET;
gp.value = &r200Screen->agp_buffer_offset;
ret = drmCommandWriteRead( sPriv->fd, DRM_RADEON_GETPARAM,
&gp, sizeof(gp));
if (ret) {
FREE( r200Screen );
fprintf(stderr, "drmR200GetParam: %d\n", ret);
return NULL;
}
r200Screen->agp_texture_offset =
r200Screen->agp_buffer_offset + 2*1024*1024;
if (sPriv->drmMinor >= 6) {
gp.param = RADEON_PARAM_AGP_BASE;
gp.value = &r200Screen->agp_base;
ret = drmCommandWriteRead( sPriv->fd, DRM_RADEON_GETPARAM,
&gp, sizeof(gp));
if (ret) {
FREE( r200Screen );
fprintf(stderr, "drmR200GetParam (RADEON_PARAM_AGP_BUFFER_OFFSET): %d\n", ret);
return NULL;
}
}
if (sPriv->drmMinor >= 6) {
gp.param = RADEON_PARAM_IRQ_NR;
gp.value = &r200Screen->irq;
ret = drmCommandWriteRead( sPriv->fd, DRM_RADEON_GETPARAM,
&gp, sizeof(gp));
if (ret) {
FREE( r200Screen );
fprintf(stderr, "drmR200GetParam (RADEON_PARAM_IRQ_NR): %d\n", ret);
return NULL;
}
}
}
r200Screen->mmio.handle = r200DRIPriv->registerHandle;
r200Screen->mmio.size = r200DRIPriv->registerSize;
if ( drmMap( sPriv->fd,
r200Screen->mmio.handle,
r200Screen->mmio.size,
&r200Screen->mmio.map ) ) {
FREE( r200Screen );
__driUtilMessage("r200CreateScreen(): drmMap failed\n");
return NULL;
}
r200Screen->status.handle = r200DRIPriv->statusHandle;
r200Screen->status.size = r200DRIPriv->statusSize;
if ( drmMap( sPriv->fd,
r200Screen->status.handle,
r200Screen->status.size,
&r200Screen->status.map ) ) {
drmUnmap( r200Screen->mmio.map, r200Screen->mmio.size );
FREE( r200Screen );
__driUtilMessage("r200CreateScreen(): drmMap (2) failed\n");
return NULL;
}
r200Screen->scratch = (__volatile__ GLuint *)
((GLubyte *)r200Screen->status.map + RADEON_SCRATCH_REG_OFFSET);
r200Screen->buffers = drmMapBufs( sPriv->fd );
if ( !r200Screen->buffers ) {
drmUnmap( r200Screen->status.map, r200Screen->status.size );
drmUnmap( r200Screen->mmio.map, r200Screen->mmio.size );
FREE( r200Screen );
__driUtilMessage("r200CreateScreen(): drmMapBufs failed\n");
return NULL;
}
if ( !r200Screen->IsPCI ) {
r200Screen->agpTextures.handle = r200DRIPriv->agpTexHandle;
r200Screen->agpTextures.size = r200DRIPriv->agpTexMapSize;
if ( drmMap( sPriv->fd,
r200Screen->agpTextures.handle,
r200Screen->agpTextures.size,
(drmAddressPtr)&r200Screen->agpTextures.map ) ) {
drmUnmapBufs( r200Screen->buffers );
drmUnmap( r200Screen->status.map, r200Screen->status.size );
drmUnmap( r200Screen->mmio.map, r200Screen->mmio.size );
FREE( r200Screen );
__driUtilMessage("r200CreateScreen(): IsPCI failed\n");
return NULL;
}
}
r200Screen->cpp = r200DRIPriv->bpp / 8;
r200Screen->AGPMode = r200DRIPriv->AGPMode;
r200Screen->frontOffset = r200DRIPriv->frontOffset;
r200Screen->frontPitch = r200DRIPriv->frontPitch;
r200Screen->backOffset = r200DRIPriv->backOffset;
r200Screen->backPitch = r200DRIPriv->backPitch;
r200Screen->depthOffset = r200DRIPriv->depthOffset;
r200Screen->depthPitch = r200DRIPriv->depthPitch;
r200Screen->texOffset[RADEON_CARD_HEAP] = r200DRIPriv->textureOffset;
r200Screen->texSize[RADEON_CARD_HEAP] = r200DRIPriv->textureSize;
r200Screen->logTexGranularity[RADEON_CARD_HEAP] =
r200DRIPriv->log2TexGran;
if ( r200Screen->IsPCI ) {
r200Screen->numTexHeaps = RADEON_NR_TEX_HEAPS - 1;
r200Screen->texOffset[RADEON_AGP_HEAP] = 0;
r200Screen->texSize[RADEON_AGP_HEAP] = 0;
r200Screen->logTexGranularity[RADEON_AGP_HEAP] = 0;
} else {
r200Screen->numTexHeaps = RADEON_NR_TEX_HEAPS;
r200Screen->texOffset[RADEON_AGP_HEAP] =
r200DRIPriv->agpTexOffset + R200_AGP_TEX_OFFSET;
r200Screen->texSize[RADEON_AGP_HEAP] = r200DRIPriv->agpTexMapSize;
r200Screen->logTexGranularity[RADEON_AGP_HEAP] =
r200DRIPriv->log2AGPTexGran;
}
r200Screen->driScreen = sPriv;
r200Screen->sarea_priv_offset = r200DRIPriv->sarea_priv_offset;
return r200Screen;
}
/* Destroy the device specific screen private data struct.
*/
static void
r200DestroyScreen( __DRIscreenPrivate *sPriv )
{
r200ScreenPtr r200Screen = (r200ScreenPtr)sPriv->private;
if (!r200Screen)
return;
if ( !r200Screen->IsPCI ) {
drmUnmap( r200Screen->agpTextures.map,
r200Screen->agpTextures.size );
}
drmUnmapBufs( r200Screen->buffers );
drmUnmap( r200Screen->status.map, r200Screen->status.size );
drmUnmap( r200Screen->mmio.map, r200Screen->mmio.size );
FREE( r200Screen );
sPriv->private = NULL;
}
/* Initialize the driver specific screen private data.
*/
static GLboolean
r200InitDriver( __DRIscreenPrivate *sPriv )
{
__r200Screen = r200CreateScreen( sPriv );
sPriv->private = (void *) __r200Screen;
return sPriv->private ? GL_TRUE : GL_FALSE;
}
/* Create and initialize the Mesa and driver specific pixmap buffer
* data.
*/
static GLboolean
r200CreateBuffer( __DRIscreenPrivate *driScrnPriv,
__DRIdrawablePrivate *driDrawPriv,
const __GLcontextModes *mesaVis,
GLboolean isPixmap )
{
if (isPixmap) {
return GL_FALSE; /* not implemented */
}
else {
const GLboolean swDepth = GL_FALSE;
const GLboolean swAlpha = GL_FALSE;
const GLboolean swAccum = mesaVis->accumRedBits > 0;
const GLboolean swStencil = mesaVis->stencilBits > 0 &&
mesaVis->depthBits != 24;
driDrawPriv->driverPrivate = (void *)
_mesa_create_framebuffer( mesaVis,
swDepth,
swStencil,
swAccum,
swAlpha );
return (driDrawPriv->driverPrivate != NULL);
}
}
static void
r200DestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
{
_mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
}
/* Fullscreen mode isn't used for much -- could be a way to shrink
* front/back buffers & get more texture memory if the client has
* changed the video resolution.
*
* Pageflipping is now done automatically whenever there is a single
* 3d client.
*/
static GLboolean
r200OpenCloseFullScreen( __DRIcontextPrivate *driContextPriv )
{
return GL_TRUE;
}
static struct __DriverAPIRec r200API = {
r200InitDriver,
r200DestroyScreen,
r200CreateContext,
r200DestroyContext,
r200CreateBuffer,
r200DestroyBuffer,
r200SwapBuffers,
r200MakeCurrent,
r200UnbindContext,
r200OpenCloseFullScreen,
r200OpenCloseFullScreen
};
/*
* This is the bootstrap function for the driver.
* The __driCreateScreen name is the symbol that libGL.so fetches.
* Return: pointer to a __DRIscreenPrivate.
*
*/
void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
int numConfigs, __GLXvisualConfig *config)
{
__DRIscreenPrivate *psp;
psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &r200API);
return (void *) psp;
}
/* This function is called by libGL.so to allow the driver to dynamically
* extend libGL. We can add new GLX functions and/or new GL functions.
* Note that _mesa_create_context() will probably add most of the newer
* OpenGL extension functions into the dispatcher.
*/
void
__driRegisterExtensions( void )
{
/* dlopen ourself */
void *dll = dlopen(NULL, RTLD_GLOBAL);
if (dll) {
typedef void *(*registerFunc)(const char *funcName, void *funcAddr);
typedef void (*registerString)(const char *extName);
/* Get pointers to libGL's __glXRegisterGLXFunction
* and __glXRegisterGLXExtensionString, if they exist.
*/
registerFunc regFunc = (registerFunc) dlsym(dll, "__glXRegisterGLXFunction");
registerString regString = (registerString) dlsym(dll, "__glXRegisterGLXExtensionString");
if (regFunc) {
/* register our GLX extensions with libGL */
void *p;
p = regFunc("glXAllocateMemoryNV", (void *) r200AllocateMemoryNV);
if (p)
; /* XXX already registered - what to do, wrap? */
p = regFunc("glXFreeMemoryNV", (void *) r200FreeMemoryNV);
if (p)
; /* XXX already registered - what to do, wrap? */
p = regFunc("glXGetAGPOffsetMESA", (void *) r200GetAGPOffset);
if (p)
; /* XXX already registered - what to do, wrap? */
}
if (regString) {
regString("GLX_NV_vertex_array_range");
regString("GLX_MESA_agp_offset");
}
dlclose(dll);
}
}

View File

@@ -0,0 +1,96 @@
/* $XFree86$ */
/*
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
The Weather Channel (TM) funded Tungsten Graphics to develop the
initial release of the Radeon 8500 driver under the XFree86 license.
This notice must be preserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#ifndef __R200_SCREEN_H__
#define __R200_SCREEN_H__
#ifdef GLX_DIRECT_RENDERING
#include "dri_util.h"
#include "radeon_common.h"
#include "radeon_sarea.h"
typedef struct {
drmHandle handle; /* Handle to the DRM region */
drmSize size; /* Size of the DRM region */
drmAddress map; /* Mapping of the DRM region */
} r200RegionRec, *r200RegionPtr;
#define R200_CHIPSET_R200 1
#define R200_CHIPSET_MOBILITY 2
#define R200_NR_TEX_HEAPS 2
typedef struct {
int chipset;
int cpp;
int IsPCI; /* Current card is a PCI card */
int AGPMode;
unsigned int irq; /* IRQ number (0 means none) */
unsigned int frontOffset;
unsigned int frontPitch;
unsigned int backOffset;
unsigned int backPitch;
unsigned int depthOffset;
unsigned int depthPitch;
/* Shared texture data */
int numTexHeaps;
int texOffset[R200_NR_TEX_HEAPS];
int texSize[R200_NR_TEX_HEAPS];
int logTexGranularity[R200_NR_TEX_HEAPS];
r200RegionRec mmio;
r200RegionRec status;
r200RegionRec agpTextures;
drmBufMapPtr buffers;
__volatile__ GLuint *scratch;
__DRIscreenPrivate *driScreen;
unsigned int sarea_priv_offset;
unsigned int agp_buffer_offset; /* offset in card memory space */
unsigned int agp_texture_offset; /* offset in card memory space */
unsigned int agp_base;
GLboolean drmSupportsCubeMaps; /* need radeon kernel module >=1.7 */
} r200ScreenRec, *r200ScreenPtr;
#endif
#endif /* __R200_SCREEN_H__ */

View File

@@ -0,0 +1,430 @@
/* $XFree86$ */
/*
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
The Weather Channel (TM) funded Tungsten Graphics to develop the
initial release of the Radeon 8500 driver under the XFree86 license.
This notice must be preserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#include "glheader.h"
#include "imports.h"
#include "swrast/swrast.h"
#include "r200_context.h"
#include "r200_ioctl.h"
#include "r200_state.h"
#include "r200_span.h"
#include "r200_tex.h"
#define DBG 0
#define LOCAL_VARS \
r200ContextPtr rmesa = R200_CONTEXT(ctx); \
r200ScreenPtr r200Screen = rmesa->r200Screen; \
__DRIscreenPrivate *sPriv = rmesa->dri.screen; \
__DRIdrawablePrivate *dPriv = rmesa->dri.drawable; \
GLuint pitch = r200Screen->frontPitch * r200Screen->cpp; \
GLuint height = dPriv->h; \
char *buf = (char *)(sPriv->pFB + \
rmesa->state.color.drawOffset + \
(dPriv->x * r200Screen->cpp) + \
(dPriv->y * pitch)); \
char *read_buf = (char *)(sPriv->pFB + \
rmesa->state.pixel.readOffset + \
(dPriv->x * r200Screen->cpp) + \
(dPriv->y * pitch)); \
GLuint p; \
(void) read_buf; (void) buf; (void) p
#define LOCAL_DEPTH_VARS \
r200ContextPtr rmesa = R200_CONTEXT(ctx); \
r200ScreenPtr r200Screen = rmesa->r200Screen; \
__DRIscreenPrivate *sPriv = rmesa->dri.screen; \
__DRIdrawablePrivate *dPriv = rmesa->dri.drawable; \
GLuint height = dPriv->h; \
GLuint xo = dPriv->x; \
GLuint yo = dPriv->y; \
char *buf = (char *)(sPriv->pFB + r200Screen->depthOffset); \
(void) buf
#define LOCAL_STENCIL_VARS LOCAL_DEPTH_VARS
#define CLIPPIXEL( _x, _y ) \
((_x >= minx) && (_x < maxx) && (_y >= miny) && (_y < maxy))
#define CLIPSPAN( _x, _y, _n, _x1, _n1, _i ) \
if ( _y < miny || _y >= maxy ) { \
_n1 = 0, _x1 = x; \
} else { \
_n1 = _n; \
_x1 = _x; \
if ( _x1 < minx ) _i += (minx-_x1), n1 -= (minx-_x1), _x1 = minx; \
if ( _x1 + _n1 >= maxx ) n1 -= (_x1 + n1 - maxx); \
}
#define Y_FLIP( _y ) (height - _y - 1)
#define HW_LOCK()
#define HW_CLIPLOOP() \
do { \
__DRIdrawablePrivate *dPriv = rmesa->dri.drawable; \
int _nc = dPriv->numClipRects; \
\
while ( _nc-- ) { \
int minx = dPriv->pClipRects[_nc].x1 - dPriv->x; \
int miny = dPriv->pClipRects[_nc].y1 - dPriv->y; \
int maxx = dPriv->pClipRects[_nc].x2 - dPriv->x; \
int maxy = dPriv->pClipRects[_nc].y2 - dPriv->y;
#define HW_ENDCLIPLOOP() \
} \
} while (0)
#define HW_UNLOCK()
/* ================================================================
* Color buffer
*/
/* 16 bit, RGB565 color spanline and pixel functions
*/
#define INIT_MONO_PIXEL(p, color) \
p = PACK_COLOR_565( color[0], color[1], color[2] )
#define WRITE_RGBA( _x, _y, r, g, b, a ) \
*(GLushort *)(buf + _x*2 + _y*pitch) = ((((int)r & 0xf8) << 8) | \
(((int)g & 0xfc) << 3) | \
(((int)b & 0xf8) >> 3))
#define WRITE_PIXEL( _x, _y, p ) \
*(GLushort *)(buf + _x*2 + _y*pitch) = p
#define READ_RGBA( rgba, _x, _y ) \
do { \
GLushort p = *(GLushort *)(read_buf + _x*2 + _y*pitch); \
rgba[0] = ((p >> 8) & 0xf8) * 255 / 0xf8; \
rgba[1] = ((p >> 3) & 0xfc) * 255 / 0xfc; \
rgba[2] = ((p << 3) & 0xf8) * 255 / 0xf8; \
rgba[3] = 0xff; \
} while (0)
#define TAG(x) r200##x##_RGB565
#include "spantmp.h"
/* 32 bit, ARGB8888 color spanline and pixel functions
*/
#undef INIT_MONO_PIXEL
#define INIT_MONO_PIXEL(p, color) \
p = PACK_COLOR_8888( color[3], color[0], color[1], color[2] )
#define WRITE_RGBA( _x, _y, r, g, b, a ) \
do { \
*(GLuint *)(buf + _x*4 + _y*pitch) = ((b << 0) | \
(g << 8) | \
(r << 16) | \
(a << 24) ); \
} while (0)
#define WRITE_PIXEL( _x, _y, p ) \
do { \
*(GLuint *)(buf + _x*4 + _y*pitch) = p; \
} while (0)
#define READ_RGBA( rgba, _x, _y ) \
do { \
volatile GLuint *ptr = (volatile GLuint *)(read_buf + _x*4 + _y*pitch); \
GLuint p = *ptr; \
rgba[0] = (p >> 16) & 0xff; \
rgba[1] = (p >> 8) & 0xff; \
rgba[2] = (p >> 0) & 0xff; \
rgba[3] = (p >> 24) & 0xff; \
} while (0)
#define TAG(x) r200##x##_ARGB8888
#include "spantmp.h"
/* ================================================================
* Depth buffer
*/
/* The R200 has depth tiling on all the time, so we have to convert
* the x,y coordinates into the memory bus address (mba) in the same
* manner as the engine. In each case, the linear block address (ba)
* is calculated, and then wired with x and y to produce the final
* memory address.
*/
#define BIT(x,b) ((x & (1<<b))>>b)
static GLuint r200_mba_z32( r200ContextPtr rmesa,
GLint x, GLint y )
{
GLuint pitch = rmesa->r200Screen->frontPitch;
GLuint b = ((y & 0x3FF) >> 4) * ((pitch & 0xFFF) >> 5) + ((x & 0x3FF) >> 5);
GLuint a =
(BIT(x,0) << 2) |
(BIT(y,0) << 3) |
(BIT(x,1) << 4) |
(BIT(y,1) << 5) |
(BIT(x,3) << 6) |
(BIT(x,4) << 7) |
(BIT(x,2) << 8) |
(BIT(y,2) << 9) |
(BIT(y,3) << 10) |
(((pitch & 0x20) ? (b & 0x01) : ((b & 0x01) ^ (BIT(y,4)))) << 11) |
((b >> 1) << 12);
return a;
}
static GLuint r200_mba_z16( r200ContextPtr rmesa, GLint x, GLint y )
{
GLuint pitch = rmesa->r200Screen->frontPitch;
GLuint b = ((y & 0x3FF) >> 4) * ((pitch & 0xFFF) >> 6) + ((x & 0x3FF) >> 6);
GLuint a =
(BIT(x,0) << 1) |
(BIT(y,0) << 2) |
(BIT(x,1) << 3) |
(BIT(y,1) << 4) |
(BIT(x,2) << 5) |
(BIT(x,4) << 6) |
(BIT(x,5) << 7) |
(BIT(x,3) << 8) |
(BIT(y,2) << 9) |
(BIT(y,3) << 10) |
(((pitch & 0x40) ? (b & 0x01) : ((b & 0x01) ^ (BIT(y,4)))) << 11) |
((b >> 1) << 12);
return a;
}
/* 16-bit depth buffer functions
*/
#define WRITE_DEPTH( _x, _y, d ) \
*(GLushort *)(buf + r200_mba_z16( rmesa, _x + xo, _y + yo )) = d;
#define READ_DEPTH( d, _x, _y ) \
d = *(GLushort *)(buf + r200_mba_z16( rmesa, _x + xo, _y + yo ));
#define TAG(x) r200##x##_16
#include "depthtmp.h"
/* 24 bit depth, 8 bit stencil depthbuffer functions
*/
#define WRITE_DEPTH( _x, _y, d ) \
do { \
GLuint offset = r200_mba_z32( rmesa, _x + xo, _y + yo ); \
GLuint tmp = *(GLuint *)(buf + offset); \
tmp &= 0xff000000; \
tmp |= ((d) & 0x00ffffff); \
*(GLuint *)(buf + offset) = tmp; \
} while (0)
#define READ_DEPTH( d, _x, _y ) \
d = *(GLuint *)(buf + r200_mba_z32( rmesa, _x + xo, \
_y + yo )) & 0x00ffffff;
#define TAG(x) r200##x##_24_8
#include "depthtmp.h"
/* ================================================================
* Stencil buffer
*/
/* 24 bit depth, 8 bit stencil depthbuffer functions
*/
#define WRITE_STENCIL( _x, _y, d ) \
do { \
GLuint offset = r200_mba_z32( rmesa, _x + xo, _y + yo ); \
GLuint tmp = *(GLuint *)(buf + offset); \
tmp &= 0x00ffffff; \
tmp |= (((d) & 0xff) << 24); \
*(GLuint *)(buf + offset) = tmp; \
} while (0)
#define READ_STENCIL( d, _x, _y ) \
do { \
GLuint offset = r200_mba_z32( rmesa, _x + xo, _y + yo ); \
GLuint tmp = *(GLuint *)(buf + offset); \
tmp &= 0xff000000; \
d = tmp >> 24; \
} while (0)
#define TAG(x) r200##x##_24_8
#include "stenciltmp.h"
/*
* This function is called to specify which buffer to read and write
* for software rasterization (swrast) fallbacks. This doesn't necessarily
* correspond to glDrawBuffer() or glReadBuffer() calls.
*/
static void r200SetBuffer( GLcontext *ctx,
GLframebuffer *colorBuffer,
GLuint bufferBit )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
switch ( bufferBit ) {
case FRONT_LEFT_BIT:
if ( rmesa->doPageFlip && rmesa->sarea->pfCurrentPage == 1 ) {
rmesa->state.pixel.readOffset = rmesa->r200Screen->backOffset;
rmesa->state.pixel.readPitch = rmesa->r200Screen->backPitch;
rmesa->state.color.drawOffset = rmesa->r200Screen->backOffset;
rmesa->state.color.drawPitch = rmesa->r200Screen->backPitch;
} else {
rmesa->state.pixel.readOffset = rmesa->r200Screen->frontOffset;
rmesa->state.pixel.readPitch = rmesa->r200Screen->frontPitch;
rmesa->state.color.drawOffset = rmesa->r200Screen->frontOffset;
rmesa->state.color.drawPitch = rmesa->r200Screen->frontPitch;
}
break;
case BACK_LEFT_BIT:
if ( rmesa->doPageFlip && rmesa->sarea->pfCurrentPage == 1 ) {
rmesa->state.pixel.readOffset = rmesa->r200Screen->frontOffset;
rmesa->state.pixel.readPitch = rmesa->r200Screen->frontPitch;
rmesa->state.color.drawOffset = rmesa->r200Screen->frontOffset;
rmesa->state.color.drawPitch = rmesa->r200Screen->frontPitch;
} else {
rmesa->state.pixel.readOffset = rmesa->r200Screen->backOffset;
rmesa->state.pixel.readPitch = rmesa->r200Screen->backPitch;
rmesa->state.color.drawOffset = rmesa->r200Screen->backOffset;
rmesa->state.color.drawPitch = rmesa->r200Screen->backPitch;
}
break;
default:
_mesa_problem(ctx, "Bad bufferBit in r200SetBuffer()");
break;
}
}
/* Move locking out to get reasonable span performance (10x better
* than doing this in HW_LOCK above). WaitForIdle() is the main
* culprit.
*/
static void r200SpanRenderStart( GLcontext *ctx )
{
r200ContextPtr rmesa = R200_CONTEXT( ctx );
R200_FIREVERTICES( rmesa );
LOCK_HARDWARE( rmesa );
r200WaitForIdleLocked( rmesa );
/* Read & rewrite the first pixel in the frame buffer. This should
* be a noop, right? In fact without this conform fails as reading
* from the framebuffer sometimes produces old results -- the
* on-card read cache gets mixed up and doesn't notice that the
* framebuffer has been updated.
*
* In the worst case this is buggy too as p might get the wrong
* value first time, so really need a hidden pixel somewhere for this.
*/
{
int p;
volatile int *read_buf = (volatile int *)(rmesa->dri.screen->pFB +
rmesa->state.pixel.readOffset);
p = *read_buf;
*read_buf = p;
}
}
static void r200SpanRenderFinish( GLcontext *ctx )
{
r200ContextPtr rmesa = R200_CONTEXT( ctx );
_swrast_flush( ctx );
UNLOCK_HARDWARE( rmesa );
}
void r200InitSpanFuncs( GLcontext *ctx )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx);
swdd->SetBuffer = r200SetBuffer;
switch ( rmesa->r200Screen->cpp ) {
case 2:
swdd->WriteRGBASpan = r200WriteRGBASpan_RGB565;
swdd->WriteRGBSpan = r200WriteRGBSpan_RGB565;
swdd->WriteMonoRGBASpan = r200WriteMonoRGBASpan_RGB565;
swdd->WriteRGBAPixels = r200WriteRGBAPixels_RGB565;
swdd->WriteMonoRGBAPixels = r200WriteMonoRGBAPixels_RGB565;
swdd->ReadRGBASpan = r200ReadRGBASpan_RGB565;
swdd->ReadRGBAPixels = r200ReadRGBAPixels_RGB565;
break;
case 4:
swdd->WriteRGBASpan = r200WriteRGBASpan_ARGB8888;
swdd->WriteRGBSpan = r200WriteRGBSpan_ARGB8888;
swdd->WriteMonoRGBASpan = r200WriteMonoRGBASpan_ARGB8888;
swdd->WriteRGBAPixels = r200WriteRGBAPixels_ARGB8888;
swdd->WriteMonoRGBAPixels = r200WriteMonoRGBAPixels_ARGB8888;
swdd->ReadRGBASpan = r200ReadRGBASpan_ARGB8888;
swdd->ReadRGBAPixels = r200ReadRGBAPixels_ARGB8888;
break;
default:
break;
}
switch ( rmesa->glCtx->Visual.depthBits ) {
case 16:
swdd->ReadDepthSpan = r200ReadDepthSpan_16;
swdd->WriteDepthSpan = r200WriteDepthSpan_16;
swdd->ReadDepthPixels = r200ReadDepthPixels_16;
swdd->WriteDepthPixels = r200WriteDepthPixels_16;
break;
case 24:
swdd->ReadDepthSpan = r200ReadDepthSpan_24_8;
swdd->WriteDepthSpan = r200WriteDepthSpan_24_8;
swdd->ReadDepthPixels = r200ReadDepthPixels_24_8;
swdd->WriteDepthPixels = r200WriteDepthPixels_24_8;
swdd->ReadStencilSpan = r200ReadStencilSpan_24_8;
swdd->WriteStencilSpan = r200WriteStencilSpan_24_8;
swdd->ReadStencilPixels = r200ReadStencilPixels_24_8;
swdd->WriteStencilPixels = r200WriteStencilPixels_24_8;
break;
default:
break;
}
swdd->SpanRenderStart = r200SpanRenderStart;
swdd->SpanRenderFinish = r200SpanRenderFinish;
}

View File

@@ -0,0 +1,43 @@
/* $XFree86$ */
/*
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
The Weather Channel (TM) funded Tungsten Graphics to develop the
initial release of the Radeon 8500 driver under the XFree86 license.
This notice must be preserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#ifndef __R200_SPAN_H__
#define __R200_SPAN_H__
#ifdef GLX_DIRECT_RENDERING
extern void r200InitSpanFuncs( GLcontext *ctx );
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,68 @@
/* $XFree86$ */
/*
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
The Weather Channel (TM) funded Tungsten Graphics to develop the
initial release of the Radeon 8500 driver under the XFree86 license.
This notice must be preserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#ifndef __R200_STATE_H__
#define __R200_STATE_H__
#ifdef GLX_DIRECT_RENDERING
#include "r200_context.h"
extern void r200InitState( r200ContextPtr rmesa );
extern void r200InitStateFuncs( GLcontext *ctx );
extern void r200UpdateMaterial( GLcontext *ctx );
extern void r200SetCliprects( r200ContextPtr rmesa, GLenum mode );
extern void r200RecalcScissorRects( r200ContextPtr rmesa );
extern void r200UpdateViewportOffset( GLcontext *ctx );
extern void r200UpdateWindow( GLcontext *ctx );
extern void r200ValidateState( GLcontext *ctx );
extern void r200PrintDirty( r200ContextPtr rmesa,
const char *msg );
extern void r200Fallback( GLcontext *ctx, GLuint bit, GLboolean mode );
#define FALLBACK( rmesa, bit, mode ) do { \
if ( 0 ) fprintf( stderr, "FALLBACK in %s: #%d=%d\n", \
__FUNCTION__, bit, mode ); \
r200Fallback( rmesa->glCtx, bit, mode ); \
} while (0)
extern void r200LightingSpaceChange( GLcontext *ctx );
#endif
#endif

View File

@@ -0,0 +1,692 @@
/* $XFree86$ */
/*
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
The Weather Channel (TM) funded Tungsten Graphics to develop the
initial release of the Radeon 8500 driver under the XFree86 license.
This notice must be preserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#include "glheader.h"
#include "imports.h"
#include "mmath.h"
#include "enums.h"
#include "colormac.h"
#include "api_arrayelt.h"
#include "swrast/swrast.h"
#include "array_cache/acache.h"
#include "tnl/tnl.h"
#include "tnl/t_pipeline.h"
#include "swrast_setup/swrast_setup.h"
#include "r200_context.h"
#include "r200_ioctl.h"
#include "r200_state.h"
#include "r200_tcl.h"
#include "r200_tex.h"
#include "r200_swtcl.h"
#include "r200_vtxfmt.h"
/* =============================================================
* State initialization
*/
void r200PrintDirty( r200ContextPtr rmesa, const char *msg )
{
struct r200_state_atom *l;
fprintf(stderr, msg);
fprintf(stderr, ": ");
foreach(l, &(rmesa->hw.dirty)) {
fprintf(stderr, "%s, ", l->name);
}
fprintf(stderr, "\n");
}
static int cmdpkt( int id )
{
drmRadeonCmdHeader h;
h.i = 0;
h.packet.cmd_type = RADEON_CMD_PACKET;
h.packet.packet_id = id;
return h.i;
}
static int cmdvec( int offset, int stride, int count )
{
drmRadeonCmdHeader h;
h.i = 0;
h.vectors.cmd_type = RADEON_CMD_VECTORS;
h.vectors.offset = offset;
h.vectors.stride = stride;
h.vectors.count = count;
return h.i;
}
static int cmdscl( int offset, int stride, int count )
{
drmRadeonCmdHeader h;
h.i = 0;
h.scalars.cmd_type = RADEON_CMD_SCALARS;
h.scalars.offset = offset;
h.scalars.stride = stride;
h.scalars.count = count;
return h.i;
}
static int cmdscl2( int offset, int stride, int count )
{
drmRadeonCmdHeader h;
h.i = 0;
h.scalars.cmd_type = RADEON_CMD_SCALARS2;
h.scalars.offset = offset - 0x100;
h.scalars.stride = stride;
h.scalars.count = count;
return h.i;
}
#define CHECK( NM, FLAG ) \
static GLboolean check_##NM( GLcontext *ctx, int idx ) \
{ \
(void) idx; \
return FLAG; \
}
#define TCL_CHECK( NM, FLAG ) \
static GLboolean check_##NM( GLcontext *ctx, int idx ) \
{ \
r200ContextPtr rmesa = R200_CONTEXT(ctx); \
(void) idx; \
return !rmesa->TclFallback && (FLAG); \
}
CHECK( always, GL_TRUE )
CHECK( tex_any, ctx->Texture._EnabledUnits )
CHECK( tex, ctx->Texture.Unit[idx]._ReallyEnabled )
CHECK( fog, ctx->Fog.Enabled )
TCL_CHECK( tcl, GL_TRUE )
TCL_CHECK( tcl_tex_any, ctx->Texture._EnabledUnits )
TCL_CHECK( tcl_tex, ctx->Texture.Unit[idx]._ReallyEnabled )
TCL_CHECK( tcl_lighting, ctx->Light.Enabled )
TCL_CHECK( tcl_eyespace_or_lighting, ctx->_NeedEyeCoords || ctx->Light.Enabled )
TCL_CHECK( tcl_light, ctx->Light.Enabled && ctx->Light.Light[idx].Enabled )
TCL_CHECK( tcl_ucp, (ctx->Transform.ClipPlanesEnabled & (1 << idx)) )
/* TCL_CHECK( tcl_eyespace_or_fog, ctx->_NeedEyeCoords || ctx->Fog.Enabled ) */
static GLboolean check_tcl_eyespace_or_fog( GLcontext *ctx, int idx )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
int res;
(void) idx;
res = !rmesa->TclFallback && (ctx->_NeedEyeCoords || ctx->Fog.Enabled);
fprintf(stderr, "%s: %d\n", __FUNCTION__, res);
return res;
}
/* Initialize the context's hardware state.
*/
void r200InitState( r200ContextPtr rmesa )
{
GLcontext *ctx = rmesa->glCtx;
GLuint color_fmt, depth_fmt, i;
switch ( rmesa->r200Screen->cpp ) {
case 2:
color_fmt = R200_COLOR_FORMAT_RGB565;
break;
case 4:
color_fmt = R200_COLOR_FORMAT_ARGB8888;
break;
default:
fprintf( stderr, "Error: Unsupported pixel depth... exiting\n" );
exit( -1 );
}
rmesa->state.color.clear = 0x00000000;
switch ( ctx->Visual.depthBits ) {
case 16:
rmesa->state.depth.scale = 1.0 / (GLfloat)0xffff;
depth_fmt = R200_DEPTH_FORMAT_16BIT_INT_Z;
rmesa->state.stencil.clear = 0x00000000;
break;
case 24:
rmesa->state.depth.scale = 1.0 / (GLfloat)0xffffff;
depth_fmt = R200_DEPTH_FORMAT_24BIT_INT_Z;
rmesa->state.stencil.clear = 0xff000000;
break;
default:
fprintf( stderr, "Error: Unsupported depth %d... exiting\n",
ctx->Visual.depthBits );
exit( -1 );
}
/* Only have hw stencil when depth buffer is 24 bits deep */
rmesa->state.stencil.hwBuffer = ( ctx->Visual.stencilBits > 0 &&
ctx->Visual.depthBits == 24 );
rmesa->Fallback = 0;
if ( ctx->Visual.doubleBufferMode && rmesa->sarea->pfCurrentPage == 0 ) {
rmesa->state.color.drawOffset = rmesa->r200Screen->backOffset;
rmesa->state.color.drawPitch = rmesa->r200Screen->backPitch;
} else {
rmesa->state.color.drawOffset = rmesa->r200Screen->frontOffset;
rmesa->state.color.drawPitch = rmesa->r200Screen->frontPitch;
}
rmesa->state.pixel.readOffset = rmesa->state.color.drawOffset;
rmesa->state.pixel.readPitch = rmesa->state.color.drawPitch;
/* Initialize lists:
*/
make_empty_list(&(rmesa->hw.dirty)); rmesa->hw.dirty.name = "DIRTY";
make_empty_list(&(rmesa->hw.clean)); rmesa->hw.clean.name = "CLEAN";
#define ALLOC_STATE( ATOM, CHK, SZ, NM, IDX ) \
do { \
rmesa->hw.ATOM.cmd_size = SZ; \
rmesa->hw.ATOM.cmd = (int *)CALLOC(SZ * sizeof(int)); \
rmesa->hw.ATOM.lastcmd = (int *)CALLOC(SZ * sizeof(int)); \
rmesa->hw.ATOM.name = NM; \
rmesa->hw.ATOM.idx = IDX; \
rmesa->hw.ATOM.check = check_##CHK; \
insert_at_head(&(rmesa->hw.dirty), &(rmesa->hw.ATOM)); \
} while (0)
/* Allocate state buffers:
*/
ALLOC_STATE( ctx, always, CTX_STATE_SIZE, "CTX/context", 0 );
ALLOC_STATE( set, always, SET_STATE_SIZE, "SET/setup", 0 );
ALLOC_STATE( lin, always, LIN_STATE_SIZE, "LIN/line", 0 );
ALLOC_STATE( msk, always, MSK_STATE_SIZE, "MSK/mask", 0 );
ALLOC_STATE( vpt, always, VPT_STATE_SIZE, "VPT/viewport", 0 );
ALLOC_STATE( vtx, always, VTX_STATE_SIZE, "VTX/vertex", 0 );
ALLOC_STATE( vap, always, VAP_STATE_SIZE, "VAP/vap", 0 );
ALLOC_STATE( vte, always, VTE_STATE_SIZE, "VTE/vte", 0 );
ALLOC_STATE( msc, always, MSC_STATE_SIZE, "MSC/misc", 0 );
ALLOC_STATE( cst, always, CST_STATE_SIZE, "CST/constant", 0 );
ALLOC_STATE( zbs, always, ZBS_STATE_SIZE, "ZBS/zbias", 0 );
ALLOC_STATE( tam, tex_any, TAM_STATE_SIZE, "TAM/tam", 0 );
ALLOC_STATE( tf, tex_any, TF_STATE_SIZE, "TF/tfactor", 0 );
ALLOC_STATE( tex[0], tex_any, TEX_STATE_SIZE, "TEX/tex-0", 0 );
ALLOC_STATE( tex[1], tex_any, TEX_STATE_SIZE, "TEX/tex-1", 1 );
ALLOC_STATE( cube[0], tex_any, CUBE_STATE_SIZE, "CUBE/tex-0", 0 );
ALLOC_STATE( cube[1], tex_any, CUBE_STATE_SIZE, "CUBE/tex-1", 1 );
ALLOC_STATE( tcl, tcl, TCL_STATE_SIZE, "TCL/tcl", 0 );
ALLOC_STATE( msl, tcl, MSL_STATE_SIZE, "MSL/matrix-select", 0 );
ALLOC_STATE( tcg, tcl, TCG_STATE_SIZE, "TCG/texcoordgen", 0 );
ALLOC_STATE( mtl[0], tcl_lighting, MTL_STATE_SIZE, "MTL0/material0", 0 );
ALLOC_STATE( grd, tcl, GRD_STATE_SIZE, "GRD/guard-band", 0 );
ALLOC_STATE( fog, fog, FOG_STATE_SIZE, "FOG/fog", 0 );
ALLOC_STATE( glt, tcl_lighting, GLT_STATE_SIZE, "GLT/light-global", 0 );
ALLOC_STATE( eye, tcl_lighting, EYE_STATE_SIZE, "EYE/eye-vector", 0 );
ALLOC_STATE( mat[R200_MTX_MV], tcl, MAT_STATE_SIZE, "MAT/modelview", 0 );
ALLOC_STATE( mat[R200_MTX_IMV], tcl, MAT_STATE_SIZE, "MAT/it-modelview", 0 );
ALLOC_STATE( mat[R200_MTX_MVP], tcl, MAT_STATE_SIZE, "MAT/modelproject", 0 );
ALLOC_STATE( mat[R200_MTX_TEX0], tcl_tex, MAT_STATE_SIZE, "MAT/texmat0", 0 );
ALLOC_STATE( mat[R200_MTX_TEX1], tcl_tex, MAT_STATE_SIZE, "MAT/texmat1", 1 );
ALLOC_STATE( ucp[0], tcl_ucp, UCP_STATE_SIZE, "UCP/userclip-0", 0 );
ALLOC_STATE( ucp[1], tcl_ucp, UCP_STATE_SIZE, "UCP/userclip-1", 1 );
ALLOC_STATE( ucp[2], tcl_ucp, UCP_STATE_SIZE, "UCP/userclip-2", 2 );
ALLOC_STATE( ucp[3], tcl_ucp, UCP_STATE_SIZE, "UCP/userclip-3", 3 );
ALLOC_STATE( ucp[4], tcl_ucp, UCP_STATE_SIZE, "UCP/userclip-4", 4 );
ALLOC_STATE( ucp[5], tcl_ucp, UCP_STATE_SIZE, "UCP/userclip-5", 5 );
ALLOC_STATE( lit[0], tcl_light, LIT_STATE_SIZE, "LIT/light-0", 0 );
ALLOC_STATE( lit[1], tcl_light, LIT_STATE_SIZE, "LIT/light-1", 1 );
ALLOC_STATE( lit[2], tcl_light, LIT_STATE_SIZE, "LIT/light-2", 2 );
ALLOC_STATE( lit[3], tcl_light, LIT_STATE_SIZE, "LIT/light-3", 3 );
ALLOC_STATE( lit[4], tcl_light, LIT_STATE_SIZE, "LIT/light-4", 4 );
ALLOC_STATE( lit[5], tcl_light, LIT_STATE_SIZE, "LIT/light-5", 5 );
ALLOC_STATE( lit[6], tcl_light, LIT_STATE_SIZE, "LIT/light-6", 6 );
ALLOC_STATE( lit[7], tcl_light, LIT_STATE_SIZE, "LIT/light-7", 7 );
ALLOC_STATE( pix[0], always, PIX_STATE_SIZE, "PIX/pixstage-0", 0 );
ALLOC_STATE( pix[1], tex, PIX_STATE_SIZE, "PIX/pixstage-1", 1 );
/* Fill in the packet headers:
*/
rmesa->hw.ctx.cmd[CTX_CMD_0] = cmdpkt(RADEON_EMIT_PP_MISC);
rmesa->hw.ctx.cmd[CTX_CMD_1] = cmdpkt(RADEON_EMIT_PP_CNTL);
rmesa->hw.ctx.cmd[CTX_CMD_2] = cmdpkt(RADEON_EMIT_RB3D_COLORPITCH);
rmesa->hw.lin.cmd[LIN_CMD_0] = cmdpkt(RADEON_EMIT_RE_LINE_PATTERN);
rmesa->hw.lin.cmd[LIN_CMD_1] = cmdpkt(RADEON_EMIT_SE_LINE_WIDTH);
rmesa->hw.msk.cmd[MSK_CMD_0] = cmdpkt(RADEON_EMIT_RB3D_STENCILREFMASK);
rmesa->hw.vpt.cmd[VPT_CMD_0] = cmdpkt(RADEON_EMIT_SE_VPORT_XSCALE);
rmesa->hw.set.cmd[SET_CMD_0] = cmdpkt(RADEON_EMIT_SE_CNTL);
rmesa->hw.msc.cmd[MSC_CMD_0] = cmdpkt(RADEON_EMIT_RE_MISC);
rmesa->hw.cst.cmd[CST_CMD_0] = cmdpkt(R200_EMIT_PP_CNTL_X);
rmesa->hw.cst.cmd[CST_CMD_1] = cmdpkt(R200_EMIT_RB3D_DEPTHXY_OFFSET);
rmesa->hw.cst.cmd[CST_CMD_2] = cmdpkt(R200_EMIT_RE_AUX_SCISSOR_CNTL);
rmesa->hw.cst.cmd[CST_CMD_3] = cmdpkt(R200_EMIT_RE_SCISSOR_TL_0);
rmesa->hw.cst.cmd[CST_CMD_4] = cmdpkt(R200_EMIT_SE_VAP_CNTL_STATUS);
rmesa->hw.cst.cmd[CST_CMD_5] = cmdpkt(R200_EMIT_RE_POINTSIZE);
rmesa->hw.cst.cmd[CST_CMD_6] = cmdpkt(R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0);
rmesa->hw.tam.cmd[TAM_CMD_0] = cmdpkt(R200_EMIT_PP_TAM_DEBUG3);
rmesa->hw.tf.cmd[TF_CMD_0] = cmdpkt(R200_EMIT_TFACTOR_0);
rmesa->hw.tex[0].cmd[TEX_CMD_0] = cmdpkt(R200_EMIT_PP_TXFILTER_0);
rmesa->hw.tex[0].cmd[TEX_CMD_1] = cmdpkt(R200_EMIT_PP_TXOFFSET_0);
rmesa->hw.tex[1].cmd[TEX_CMD_0] = cmdpkt(R200_EMIT_PP_TXFILTER_1);
rmesa->hw.tex[1].cmd[TEX_CMD_1] = cmdpkt(R200_EMIT_PP_TXOFFSET_1);
rmesa->hw.cube[0].cmd[CUBE_CMD_0] = cmdpkt(R200_EMIT_PP_CUBIC_FACES_0);
rmesa->hw.cube[0].cmd[CUBE_CMD_1] = cmdpkt(R200_EMIT_PP_CUBIC_OFFSETS_0);
rmesa->hw.cube[1].cmd[CUBE_CMD_0] = cmdpkt(R200_EMIT_PP_CUBIC_FACES_1);
rmesa->hw.cube[1].cmd[CUBE_CMD_1] = cmdpkt(R200_EMIT_PP_CUBIC_OFFSETS_1);
rmesa->hw.pix[0].cmd[PIX_CMD_0] = cmdpkt(R200_EMIT_PP_TXCBLEND_0);
rmesa->hw.pix[1].cmd[PIX_CMD_0] = cmdpkt(R200_EMIT_PP_TXCBLEND_1);
rmesa->hw.zbs.cmd[ZBS_CMD_0] = cmdpkt(RADEON_EMIT_SE_ZBIAS_FACTOR);
rmesa->hw.tcl.cmd[TCL_CMD_0] = cmdpkt(R200_EMIT_TCL_LIGHT_MODEL_CTL_0);
rmesa->hw.tcl.cmd[TCL_CMD_1] = cmdpkt(R200_EMIT_TCL_UCP_VERT_BLEND_CTL);
rmesa->hw.tcg.cmd[TCG_CMD_0] = cmdpkt(R200_EMIT_TEX_PROC_CTL_2);
rmesa->hw.msl.cmd[MSL_CMD_0] = cmdpkt(R200_EMIT_MATRIX_SELECT_0);
rmesa->hw.vap.cmd[VAP_CMD_0] = cmdpkt(R200_EMIT_VAP_CTL);
rmesa->hw.vtx.cmd[VTX_CMD_0] = cmdpkt(R200_EMIT_VTX_FMT_0);
rmesa->hw.vtx.cmd[VTX_CMD_1] = cmdpkt(R200_EMIT_OUTPUT_VTX_COMP_SEL);
rmesa->hw.vtx.cmd[VTX_CMD_2] = cmdpkt(R200_EMIT_SE_VTX_STATE_CNTL);
rmesa->hw.vte.cmd[VTE_CMD_0] = cmdpkt(R200_EMIT_VTE_CNTL);
rmesa->hw.mtl[0].cmd[MTL_CMD_0] =
cmdvec( R200_VS_MAT_0_EMISS, 1, 16 );
rmesa->hw.mtl[0].cmd[MTL_CMD_1] =
cmdscl2( R200_SS_MAT_0_SHININESS, 1, 1 );
rmesa->hw.grd.cmd[GRD_CMD_0] =
cmdscl( R200_SS_VERT_GUARD_CLIP_ADJ_ADDR, 1, 4 );
rmesa->hw.fog.cmd[FOG_CMD_0] =
cmdvec( R200_VS_FOG_PARAM_ADDR, 1, 4 );
rmesa->hw.glt.cmd[GLT_CMD_0] =
cmdvec( R200_VS_GLOBAL_AMBIENT_ADDR, 1, 4 );
rmesa->hw.eye.cmd[EYE_CMD_0] =
cmdvec( R200_VS_EYE_VECTOR_ADDR, 1, 4 );
rmesa->hw.mat[R200_MTX_MV].cmd[MAT_CMD_0] =
cmdvec( R200_VS_MATRIX_0_MV, 1, 16);
rmesa->hw.mat[R200_MTX_IMV].cmd[MAT_CMD_0] =
cmdvec( R200_VS_MATRIX_1_INV_MV, 1, 16);
rmesa->hw.mat[R200_MTX_MVP].cmd[MAT_CMD_0] =
cmdvec( R200_VS_MATRIX_2_MVP, 1, 16);
rmesa->hw.mat[R200_MTX_TEX0].cmd[MAT_CMD_0] =
cmdvec( R200_VS_MATRIX_3_TEX0, 1, 16);
rmesa->hw.mat[R200_MTX_TEX1].cmd[MAT_CMD_0] =
cmdvec( R200_VS_MATRIX_4_TEX1, 1, 16);
for (i = 0 ; i < 8; i++) {
rmesa->hw.lit[i].cmd[LIT_CMD_0] =
cmdvec( R200_VS_LIGHT_AMBIENT_ADDR + i, 8, 24 );
rmesa->hw.lit[i].cmd[LIT_CMD_1] =
cmdscl( R200_SS_LIGHT_DCD_ADDR + i, 8, 7 );
}
for (i = 0 ; i < 6; i++) {
rmesa->hw.ucp[i].cmd[UCP_CMD_0] =
cmdvec( R200_VS_UCP_ADDR + i, 1, 4 );
}
/* Initial Harware state:
*/
rmesa->hw.ctx.cmd[CTX_PP_MISC] = (R200_ALPHA_TEST_PASS
/* | R200_RIGHT_HAND_CUBE_OGL*/);
rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] = (R200_FOG_VERTEX |
R200_FOG_USE_SPEC_ALPHA);
rmesa->hw.ctx.cmd[CTX_RE_SOLID_COLOR] = 0x00000000;
rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = (R200_COMB_FCN_ADD_CLAMP |
R200_SRC_BLEND_GL_ONE |
R200_DST_BLEND_GL_ZERO );
rmesa->hw.ctx.cmd[CTX_RB3D_DEPTHOFFSET] =
rmesa->r200Screen->depthOffset;
rmesa->hw.ctx.cmd[CTX_RB3D_DEPTHPITCH] =
((rmesa->r200Screen->depthPitch &
R200_DEPTHPITCH_MASK) |
R200_DEPTH_ENDIAN_NO_SWAP);
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] = (depth_fmt |
R200_Z_TEST_LESS |
R200_STENCIL_TEST_ALWAYS |
R200_STENCIL_FAIL_KEEP |
R200_STENCIL_ZPASS_KEEP |
R200_STENCIL_ZFAIL_KEEP |
R200_Z_WRITE_ENABLE);
rmesa->hw.ctx.cmd[CTX_PP_CNTL] = (R200_ANTI_ALIAS_NONE
| R200_TEX_BLEND_0_ENABLE);
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = color_fmt;
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_DITHER_ENABLE;
rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = (rmesa->state.color.drawOffset &
R200_COLOROFFSET_MASK);
rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = ((rmesa->state.color.drawPitch &
R200_COLORPITCH_MASK) |
R200_COLOR_ENDIAN_NO_SWAP);
rmesa->hw.set.cmd[SET_SE_CNTL] = (R200_FFACE_CULL_CCW |
R200_BFACE_SOLID |
R200_FFACE_SOLID |
R200_FLAT_SHADE_VTX_LAST |
R200_DIFFUSE_SHADE_GOURAUD |
R200_ALPHA_SHADE_GOURAUD |
R200_SPECULAR_SHADE_GOURAUD |
R200_FOG_SHADE_GOURAUD |
R200_VTX_PIX_CENTER_OGL |
R200_ROUND_MODE_TRUNC |
R200_ROUND_PREC_8TH_PIX);
rmesa->hw.set.cmd[SET_RE_CNTL] = (R200_PERSPECTIVE_ENABLE |
R200_SCISSOR_ENABLE);
rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] = ((1 << 16) | 0xffff);
rmesa->hw.lin.cmd[LIN_RE_LINE_STATE] =
((0 << R200_LINE_CURRENT_PTR_SHIFT) |
(1 << R200_LINE_CURRENT_COUNT_SHIFT));
rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] = (1 << 4);
rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] =
((0x00 << R200_STENCIL_REF_SHIFT) |
(0xff << R200_STENCIL_MASK_SHIFT) |
(0xff << R200_STENCIL_WRITEMASK_SHIFT));
rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = R200_ROP_COPY;
rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] = 0xffffffff;
rmesa->hw.tam.cmd[TAM_DEBUG3] = 0;
rmesa->hw.msc.cmd[MSC_RE_MISC] =
((0 << R200_STIPPLE_X_OFFSET_SHIFT) |
(0 << R200_STIPPLE_Y_OFFSET_SHIFT) |
R200_STIPPLE_BIG_BIT_ORDER);
rmesa->hw.cst.cmd[CST_PP_CNTL_X] = 0;
rmesa->hw.cst.cmd[CST_RB3D_DEPTHXY_OFFSET] = 0;
rmesa->hw.cst.cmd[CST_RE_AUX_SCISSOR_CNTL] = 0x0;
rmesa->hw.cst.cmd[CST_RE_SCISSOR_TL_0] = 0;
rmesa->hw.cst.cmd[CST_RE_SCISSOR_BR_0] = 0;
rmesa->hw.cst.cmd[CST_SE_VAP_CNTL_STATUS] =
#ifdef MESA_BIG_ENDIAN
R200_VC_32BIT_SWAP;
#else
R200_VC_NO_SWAP;
#endif
rmesa->hw.cst.cmd[CST_RE_POINTSIZE] = 0x100010;
rmesa->hw.cst.cmd[CST_SE_TCL_INPUT_VTX_0] =
(0x0 << R200_VERTEX_POSITION_ADDR__SHIFT);
rmesa->hw.cst.cmd[CST_SE_TCL_INPUT_VTX_1] =
(0x02 << R200_VTX_COLOR_0_ADDR__SHIFT) |
(0x03 << R200_VTX_COLOR_1_ADDR__SHIFT);
rmesa->hw.cst.cmd[CST_SE_TCL_INPUT_VTX_2] =
(0x06 << R200_VTX_TEX_0_ADDR__SHIFT) |
(0x07 << R200_VTX_TEX_1_ADDR__SHIFT) |
(0x08 << R200_VTX_TEX_2_ADDR__SHIFT) |
(0x09 << R200_VTX_TEX_3_ADDR__SHIFT);
rmesa->hw.cst.cmd[CST_SE_TCL_INPUT_VTX_3] =
(0x0A << R200_VTX_TEX_4_ADDR__SHIFT) |
(0x0B << R200_VTX_TEX_5_ADDR__SHIFT);
rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE] = 0x00000000;
rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = 0x00000000;
rmesa->hw.vpt.cmd[VPT_SE_VPORT_YSCALE] = 0x00000000;
rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = 0x00000000;
rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE] = 0x00000000;
rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = 0x00000000;
for (i = 0; i < 2; i++) { /* 2 texture units for now */
rmesa->hw.tex[i].cmd[TEX_PP_TXFILTER] = R200_BORDER_MODE_OGL;
rmesa->hw.tex[i].cmd[TEX_PP_TXFORMAT] =
((i << R200_TXFORMAT_ST_ROUTE_SHIFT) | /* <-- note i */
(2 << R200_TXFORMAT_WIDTH_SHIFT) |
(2 << R200_TXFORMAT_HEIGHT_SHIFT));
rmesa->hw.tex[i].cmd[TEX_PP_TXOFFSET] = 0;
rmesa->hw.tex[i].cmd[TEX_PP_BORDER_COLOR] = 0;
rmesa->hw.tex[i].cmd[TEX_PP_TXFORMAT_X] =
(/* R200_TEXCOORD_PROJ | */
0x100000); /* Small default bias */
rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_FACES] = 0;
rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_F1] = 0;
rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_F2] = 0;
rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_F3] = 0;
rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_F4] = 0;
rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_F5] = 0;
}
rmesa->hw.pix[0].cmd[PIX_PP_TXCBLEND] =
(R200_TXC_ARG_A_ZERO |
R200_TXC_ARG_B_ZERO |
R200_TXC_ARG_C_DIFFUSE_COLOR |
R200_TXC_OP_MADD);
rmesa->hw.pix[0].cmd[PIX_PP_TXCBLEND2] =
((0 << R200_TXC_TFACTOR_SEL_SHIFT) |
R200_TXC_SCALE_1X |
R200_TXC_CLAMP_0_1 |
R200_TXC_OUTPUT_REG_R0);
rmesa->hw.pix[0].cmd[PIX_PP_TXABLEND] =
(R200_TXA_ARG_A_ZERO |
R200_TXA_ARG_B_ZERO |
R200_TXA_ARG_C_DIFFUSE_ALPHA |
R200_TXA_OP_MADD);
rmesa->hw.pix[0].cmd[PIX_PP_TXABLEND2] =
((0 << R200_TXA_TFACTOR_SEL_SHIFT) |
R200_TXA_SCALE_1X |
R200_TXA_CLAMP_0_1 |
R200_TXA_OUTPUT_REG_R0);
rmesa->hw.pix[1].cmd[PIX_PP_TXCBLEND] =
(R200_TXC_ARG_A_ZERO |
R200_TXC_ARG_B_ZERO |
R200_TXC_ARG_C_DIFFUSE_COLOR |
R200_TXC_OP_MADD);
rmesa->hw.pix[1].cmd[PIX_PP_TXCBLEND2] =
((0 << R200_TXC_TFACTOR_SEL_SHIFT) |
R200_TXC_SCALE_1X |
R200_TXC_CLAMP_0_1 |
R200_TXC_OUTPUT_REG_R0);
rmesa->hw.pix[1].cmd[PIX_PP_TXABLEND] =
(R200_TXA_ARG_A_ZERO |
R200_TXA_ARG_B_ZERO |
R200_TXA_ARG_C_DIFFUSE_ALPHA |
R200_TXA_OP_MADD);
rmesa->hw.pix[1].cmd[PIX_PP_TXABLEND2] =
((0 << R200_TXA_TFACTOR_SEL_SHIFT) |
R200_TXA_SCALE_1X |
R200_TXA_CLAMP_0_1 |
R200_TXA_OUTPUT_REG_R0);
rmesa->hw.tf.cmd[TF_TFACTOR_0] = 0;
rmesa->hw.tf.cmd[TF_TFACTOR_1] = 0;
rmesa->hw.tf.cmd[TF_TFACTOR_2] = 0;
rmesa->hw.tf.cmd[TF_TFACTOR_3] = 0;
rmesa->hw.tf.cmd[TF_TFACTOR_4] = 0;
rmesa->hw.tf.cmd[TF_TFACTOR_5] = 0;
rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] =
(R200_VAP_TCL_ENABLE |
(0x9 << R200_VAP_VF_MAX_VTX_NUM__SHIFT));
rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] =
(R200_VPORT_X_SCALE_ENA |
R200_VPORT_Y_SCALE_ENA |
R200_VPORT_Z_SCALE_ENA |
R200_VPORT_X_OFFSET_ENA |
R200_VPORT_Y_OFFSET_ENA |
R200_VPORT_Z_OFFSET_ENA |
/* FIXME: Turn on for tex rect only */
R200_VTX_ST_DENORMALIZED |
R200_VTX_W0_FMT);
rmesa->hw.vtx.cmd[VTX_VTXFMT_0] = 0;
rmesa->hw.vtx.cmd[VTX_VTXFMT_1] = 0;
rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] =
((R200_VTX_Z0 | R200_VTX_W0 |
(R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT)));
rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_1] = 0;
rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] = (R200_OUTPUT_XYZW);
rmesa->hw.vtx.cmd[VTX_STATE_CNTL] = R200_VSC_UPDATE_USER_COLOR_0_ENABLE;
/* Matrix selection */
rmesa->hw.msl.cmd[MSL_MATRIX_SELECT_0] =
(R200_MTX_MV << R200_MODELVIEW_0_SHIFT);
rmesa->hw.msl.cmd[MSL_MATRIX_SELECT_1] =
(R200_MTX_IMV << R200_IT_MODELVIEW_0_SHIFT);
rmesa->hw.msl.cmd[MSL_MATRIX_SELECT_2] =
(R200_MTX_MVP << R200_MODELPROJECT_0_SHIFT);
rmesa->hw.msl.cmd[MSL_MATRIX_SELECT_3] =
((R200_MTX_TEX0 << R200_TEXMAT_0_SHIFT) |
(R200_MTX_TEX1 << R200_TEXMAT_1_SHIFT) |
(R200_MTX_TEX2 << R200_TEXMAT_2_SHIFT) |
(R200_MTX_TEX3 << R200_TEXMAT_3_SHIFT));
rmesa->hw.msl.cmd[MSL_MATRIX_SELECT_4] =
((R200_MTX_TEX4 << R200_TEXMAT_4_SHIFT) |
(R200_MTX_TEX5 << R200_TEXMAT_5_SHIFT));
/* General TCL state */
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] =
(R200_SPECULAR_LIGHTS |
R200_DIFFUSE_SPECULAR_COMBINE |
R200_LOCAL_LIGHT_VEC_GL);
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1] =
((R200_LM1_SOURCE_LIGHT_PREMULT << R200_FRONT_EMISSIVE_SOURCE_SHIFT) |
(R200_LM1_SOURCE_LIGHT_PREMULT << R200_FRONT_AMBIENT_SOURCE_SHIFT) |
(R200_LM1_SOURCE_LIGHT_PREMULT << R200_FRONT_DIFFUSE_SOURCE_SHIFT) |
(R200_LM1_SOURCE_LIGHT_PREMULT << R200_FRONT_SPECULAR_SOURCE_SHIFT) |
(R200_LM1_SOURCE_LIGHT_PREMULT << R200_BACK_EMISSIVE_SOURCE_SHIFT) |
(R200_LM1_SOURCE_LIGHT_PREMULT << R200_BACK_AMBIENT_SOURCE_SHIFT) |
(R200_LM1_SOURCE_LIGHT_PREMULT << R200_BACK_DIFFUSE_SOURCE_SHIFT) |
(R200_LM1_SOURCE_LIGHT_PREMULT << R200_BACK_SPECULAR_SOURCE_SHIFT));
rmesa->hw.tcl.cmd[TCL_PER_LIGHT_CTL_0] = 0; /* filled in via callbacks */
rmesa->hw.tcl.cmd[TCL_PER_LIGHT_CTL_1] = 0;
rmesa->hw.tcl.cmd[TCL_PER_LIGHT_CTL_2] = 0;
rmesa->hw.tcl.cmd[TCL_PER_LIGHT_CTL_3] = 0;
rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] =
(R200_UCP_IN_CLIP_SPACE |
R200_CULL_FRONT_IS_CCW);
/* Texgen/Texmat state */
rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_2] = 0x0; /* masks??? */
rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_3] =
((0 << R200_TEXGEN_0_INPUT_TEX_SHIFT) |
(1 << R200_TEXGEN_1_INPUT_TEX_SHIFT) |
(2 << R200_TEXGEN_2_INPUT_TEX_SHIFT) |
(3 << R200_TEXGEN_3_INPUT_TEX_SHIFT) |
(4 << R200_TEXGEN_4_INPUT_TEX_SHIFT) |
(5 << R200_TEXGEN_5_INPUT_TEX_SHIFT));
rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0] = 0;
rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_1] =
((0 << R200_TEXGEN_0_INPUT_SHIFT) |
(1 << R200_TEXGEN_1_INPUT_SHIFT) |
(2 << R200_TEXGEN_2_INPUT_SHIFT) |
(3 << R200_TEXGEN_3_INPUT_SHIFT) |
(4 << R200_TEXGEN_4_INPUT_SHIFT) |
(5 << R200_TEXGEN_5_INPUT_SHIFT));
rmesa->hw.tcg.cmd[TCG_TEX_CYL_WRAP_CTL] = 0;
rmesa->TexGenInputs = rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_1];
for (i = 0 ; i < 8; i++) {
struct gl_light *l = &ctx->Light.Light[i];
GLenum p = GL_LIGHT0 + i;
*(float *)&(rmesa->hw.lit[i].cmd[LIT_RANGE_CUTOFF]) = FLT_MAX;
ctx->Driver.Lightfv( ctx, p, GL_AMBIENT, l->Ambient );
ctx->Driver.Lightfv( ctx, p, GL_DIFFUSE, l->Diffuse );
ctx->Driver.Lightfv( ctx, p, GL_SPECULAR, l->Specular );
ctx->Driver.Lightfv( ctx, p, GL_POSITION, 0 );
ctx->Driver.Lightfv( ctx, p, GL_SPOT_DIRECTION, 0 );
ctx->Driver.Lightfv( ctx, p, GL_SPOT_EXPONENT, &l->SpotExponent );
ctx->Driver.Lightfv( ctx, p, GL_SPOT_CUTOFF, &l->SpotCutoff );
ctx->Driver.Lightfv( ctx, p, GL_CONSTANT_ATTENUATION,
&l->ConstantAttenuation );
ctx->Driver.Lightfv( ctx, p, GL_LINEAR_ATTENUATION,
&l->LinearAttenuation );
ctx->Driver.Lightfv( ctx, p, GL_QUADRATIC_ATTENUATION,
&l->QuadraticAttenuation );
}
ctx->Driver.LightModelfv( ctx, GL_LIGHT_MODEL_AMBIENT,
ctx->Light.Model.Ambient );
TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx );
for (i = 0 ; i < 6; i++) {
ctx->Driver.ClipPlane( ctx, GL_CLIP_PLANE0 + i, NULL );
}
ctx->Driver.Fogfv( ctx, GL_FOG_MODE, 0 );
ctx->Driver.Fogfv( ctx, GL_FOG_DENSITY, &ctx->Fog.Density );
ctx->Driver.Fogfv( ctx, GL_FOG_START, &ctx->Fog.Start );
ctx->Driver.Fogfv( ctx, GL_FOG_END, &ctx->Fog.End );
ctx->Driver.Fogfv( ctx, GL_FOG_COLOR, ctx->Fog.Color );
ctx->Driver.Fogfv( ctx, GL_FOG_COORDINATE_SOURCE_EXT, 0 );
rmesa->hw.grd.cmd[GRD_VERT_GUARD_CLIP_ADJ] = IEEE_ONE;
rmesa->hw.grd.cmd[GRD_VERT_GUARD_DISCARD_ADJ] = IEEE_ONE;
rmesa->hw.grd.cmd[GRD_HORZ_GUARD_CLIP_ADJ] = IEEE_ONE;
rmesa->hw.grd.cmd[GRD_HORZ_GUARD_DISCARD_ADJ] = IEEE_ONE;
rmesa->hw.eye.cmd[EYE_X] = 0;
rmesa->hw.eye.cmd[EYE_Y] = 0;
rmesa->hw.eye.cmd[EYE_Z] = IEEE_ONE;
rmesa->hw.eye.cmd[EYE_RESCALE_FACTOR] = IEEE_ONE;
r200LightingSpaceChange( ctx );
rmesa->lost_context = 1;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,80 @@
/* $XFree86$ */
/*
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
The Weather Channel (TM) funded Tungsten Graphics to develop the
initial release of the Radeon 8500 driver under the XFree86 license.
This notice must be preserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#ifndef __R200_SWTCL_H__
#define __R200_SWTCL_H__
#include "mtypes.h"
#include "swrast/swrast.h"
#include "r200_context.h"
extern void r200InitSwtcl( GLcontext *ctx );
extern void r200DestroySwtcl( GLcontext *ctx );
extern void r200FlushVertices( GLcontext *ctx, GLuint flags );
extern void r200ChooseRenderState( GLcontext *ctx );
extern void r200ChooseVertexState( GLcontext *ctx );
extern void r200CheckTexSizes( GLcontext *ctx );
extern void r200BuildVertices( GLcontext *ctx, GLuint start, GLuint count,
GLuint newinputs );
extern void r200PrintSetupFlags(char *msg, GLuint flags );
extern void r200_emit_contiguous_verts( GLcontext *ctx,
GLuint start,
GLuint count );
extern void r200_emit_indexed_verts( GLcontext *ctx,
GLuint start,
GLuint count );
extern void r200_translate_vertex( GLcontext *ctx,
const r200Vertex *src,
SWvertex *dst );
extern void r200_print_vertex( GLcontext *ctx, const r200Vertex *v );
extern void r200_import_float_colors( GLcontext *ctx );
extern void r200_import_float_spec_colors( GLcontext *ctx );
extern void r200PointsBitmap( GLcontext *ctx, GLint px, GLint py,
GLsizei width, GLsizei height,
const struct gl_pixelstore_attrib *unpack,
const GLubyte *bitmap );
#endif

View File

@@ -0,0 +1,555 @@
/* $XFree86$ */
/*
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
The Weather Channel (TM) funded Tungsten Graphics to develop the
initial release of the Radeon 8500 driver under the XFree86 license.
This notice must be preserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#include "glheader.h"
#include "imports.h"
#include "mmath.h"
#include "mtypes.h"
#include "enums.h"
#include "colormac.h"
#include "light.h"
#include "array_cache/acache.h"
#include "tnl/tnl.h"
#include "tnl/t_pipeline.h"
#include "r200_context.h"
#include "r200_state.h"
#include "r200_ioctl.h"
#include "r200_tex.h"
#include "r200_tcl.h"
#include "r200_swtcl.h"
#include "r200_maos.h"
#define HAVE_POINTS 1
#define HAVE_LINES 1
#define HAVE_LINE_LOOP 0
#define HAVE_LINE_STRIPS 1
#define HAVE_TRIANGLES 1
#define HAVE_TRI_STRIPS 1
#define HAVE_TRI_STRIP_1 0
#define HAVE_TRI_FANS 1
#define HAVE_QUADS 0 /* hw quad verts in wrong order??? */
#define HAVE_QUAD_STRIPS 1
#define HAVE_POLYGONS 1
#define HAVE_ELTS 1
#define HW_POINTS R200_VF_PRIM_POINTS
#define HW_LINES R200_VF_PRIM_LINES
#define HW_LINE_LOOP 0
#define HW_LINE_STRIP R200_VF_PRIM_LINE_STRIP
#define HW_TRIANGLES R200_VF_PRIM_TRIANGLES
#define HW_TRIANGLE_STRIP_0 R200_VF_PRIM_TRIANGLE_STRIP
#define HW_TRIANGLE_STRIP_1 0
#define HW_TRIANGLE_FAN R200_VF_PRIM_TRIANGLE_FAN
#define HW_QUADS R200_VF_PRIM_QUADS
#define HW_QUAD_STRIP R200_VF_PRIM_QUAD_STRIP
#define HW_POLYGON R200_VF_PRIM_POLYGON
static GLboolean discrete_prim[0x10] = {
0, /* 0 none */
1, /* 1 points */
1, /* 2 lines */
0, /* 3 line_strip */
1, /* 4 tri_list */
0, /* 5 tri_fan */
0, /* 6 tri_strip */
0, /* 7 tri_w_flags */
1, /* 8 rect list (unused) */
1, /* 9 3vert point */
1, /* a 3vert line */
0, /* b point sprite */
0, /* c line loop */
1, /* d quads */
0, /* e quad strip */
0, /* f polygon */
};
#define LOCAL_VARS r200ContextPtr rmesa = R200_CONTEXT(ctx)
#define ELTS_VARS GLushort *dest
#define ELT_INIT(prim, hw_prim) \
r200TclPrimitive( ctx, prim, hw_prim | R200_VF_PRIM_WALK_IND )
#define GET_ELTS() rmesa->tcl.Elts
#define NEW_PRIMITIVE() R200_NEWPRIM( rmesa )
#define NEW_BUFFER() r200RefillCurrentDmaRegion( rmesa )
/* Don't really know how many elts will fit in what's left of cmdbuf,
* as there is state to emit, etc:
*/
#if 0
#define GET_CURRENT_VB_MAX_ELTS() \
((R200_CMD_BUF_SZ - (rmesa->store.cmd_used + 16)) / 2)
#define GET_SUBSEQUENT_VB_MAX_ELTS() ((R200_CMD_BUF_SZ - 16) / 2)
#else
/* Testing on isosurf shows a maximum around here. Don't know if it's
* the card or driver or kernel module that is causing the behaviour.
*/
#define GET_CURRENT_VB_MAX_ELTS() 300
#define GET_SUBSEQUENT_VB_MAX_ELTS() 300
#endif
#define RESET_STIPPLE() do { \
R200_STATECHANGE( rmesa, lin ); \
r200EmitState( rmesa ); \
} while (0)
#define AUTO_STIPPLE( mode ) do { \
R200_STATECHANGE( rmesa, lin ); \
if (mode) \
rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] |= \
R200_LINE_PATTERN_AUTO_RESET; \
else \
rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] &= \
~R200_LINE_PATTERN_AUTO_RESET; \
r200EmitState( rmesa ); \
} while (0)
/* How do you extend an existing primitive?
*/
#define ALLOC_ELTS(nr) \
do { \
if (rmesa->dma.flush == r200FlushElts && \
rmesa->store.cmd_used + nr*2 < R200_CMD_BUF_SZ) { \
\
dest = (GLushort *)(rmesa->store.cmd_buf + \
rmesa->store.cmd_used); \
rmesa->store.cmd_used += nr*2; \
} \
else { \
if (rmesa->dma.flush) \
rmesa->dma.flush( rmesa ); \
\
r200EmitAOS( rmesa, \
rmesa->tcl.aos_components, \
rmesa->tcl.nr_aos_components, \
0 ); \
\
dest = r200AllocEltsOpenEnded( rmesa, \
rmesa->tcl.hw_primitive, \
nr ); \
} \
} while (0)
/* TODO: Try to extend existing primitive if both are identical,
* discrete and there are no intervening state changes. (Somewhat
* duplicates changes to DrawArrays code)
*/
static void EMIT_PRIM( GLcontext *ctx,
GLenum prim,
GLuint hwprim,
GLuint start,
GLuint count)
{
r200ContextPtr rmesa = R200_CONTEXT( ctx );
r200TclPrimitive( ctx, prim, hwprim );
r200EmitAOS( rmesa,
rmesa->tcl.aos_components,
rmesa->tcl.nr_aos_components,
start );
/* Why couldn't this packet have taken an offset param?
*/
r200EmitVbufPrim( rmesa,
rmesa->tcl.hw_primitive,
count - start );
}
/* Try & join small primitives
*/
#if 0
#define PREFER_DISCRETE_ELT_PRIM( NR, PRIM ) 0
#else
#define PREFER_DISCRETE_ELT_PRIM( NR, PRIM ) \
((NR) < 20 || \
((NR) < 40 && \
rmesa->tcl.hw_primitive == (PRIM| \
R200_VF_TCL_OUTPUT_VTX_ENABLE| \
R200_VF_PRIM_WALK_IND)))
#endif
#ifdef MESA_BIG_ENDIAN
/* We could do without (most of) this ugliness if dest was always 32 bit word aligned... */
#define EMIT_ELT(offset, x) do { \
int off = offset + ( ( (GLuint)dest & 0x2 ) >> 1 ); \
GLushort *des = (GLushort *)( (GLuint)dest & ~0x2 ); \
(des)[ off + 1 - 2 * ( off & 1 ) ] = (GLushort)(x); } while (0)
#else
#define EMIT_ELT(offset, x) (dest)[offset] = (GLushort) (x)
#endif
#define EMIT_TWO_ELTS(offset, x, y) *(GLuint *)(dest+offset) = ((y)<<16)|(x);
#define INCR_ELTS( nr ) dest += nr
#define RELEASE_ELT_VERTS() \
r200ReleaseArrays( ctx, ~0 )
#define TAG(x) tcl_##x
#include "tnl_dd/t_dd_dmatmp2.h"
/**********************************************************************/
/* External entrypoints */
/**********************************************************************/
void r200EmitPrimitive( GLcontext *ctx,
GLuint first,
GLuint last,
GLuint flags )
{
tcl_render_tab_verts[flags&PRIM_MODE_MASK]( ctx, first, last, flags );
}
void r200EmitEltPrimitive( GLcontext *ctx,
GLuint first,
GLuint last,
GLuint flags )
{
tcl_render_tab_elts[flags&PRIM_MODE_MASK]( ctx, first, last, flags );
}
void r200TclPrimitive( GLcontext *ctx,
GLenum prim,
int hw_prim )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
GLuint newprim = hw_prim | R200_VF_TCL_OUTPUT_VTX_ENABLE;
if (newprim != rmesa->tcl.hw_primitive ||
!discrete_prim[hw_prim&0xf]) {
R200_NEWPRIM( rmesa );
rmesa->tcl.hw_primitive = newprim;
}
}
/**********************************************************************/
/* Render pipeline stage */
/**********************************************************************/
/* TCL render.
*/
static GLboolean r200_run_tcl_render( GLcontext *ctx,
struct gl_pipeline_stage *stage )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
GLuint i,flags = 0,length;
/* TODO: separate this from the swtnl pipeline
*/
if (rmesa->TclFallback)
return GL_TRUE; /* fallback to software t&l */
if (R200_DEBUG & DEBUG_PRIMS)
fprintf(stderr, "%s\n", __FUNCTION__);
if (VB->Count == 0)
return GL_FALSE;
r200ReleaseArrays( ctx, stage->changed_inputs );
r200EmitArrays( ctx, stage->inputs );
rmesa->tcl.Elts = VB->Elts;
for (i = VB->FirstPrimitive ; !(flags & PRIM_LAST) ; i += length)
{
flags = VB->Primitive[i];
length = VB->PrimitiveLength[i];
if (R200_DEBUG & DEBUG_PRIMS)
fprintf(stderr, "%s: prim %s %d..%d\n",
__FUNCTION__,
_mesa_lookup_enum_by_nr(flags & PRIM_MODE_MASK),
i, i+length);
if (!length)
continue;
if (rmesa->tcl.Elts)
r200EmitEltPrimitive( ctx, i, i+length, flags );
else
r200EmitPrimitive( ctx, i, i+length, flags );
}
return GL_FALSE; /* finished the pipe */
}
static void r200_check_tcl_render( GLcontext *ctx,
struct gl_pipeline_stage *stage )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
GLuint inputs = VERT_BIT_POS;
/* Validate state:
*/
if (rmesa->NewGLState)
r200ValidateState( ctx );
if (0)
fprintf(stderr, "%s: RE %d TGE %d NN %d\n",
__FUNCTION__,
ctx->Texture.Unit[0]._ReallyEnabled,
ctx->Texture.Unit[0].TexGenEnabled,
rmesa->TexGenNeedNormals[0]);
if (ctx->RenderMode == GL_RENDER) {
/* Make all this event-driven:
*/
if (ctx->Light.Enabled) {
inputs |= VERT_BIT_NORMAL;
if (ctx->Light.ColorMaterialEnabled) {
inputs |= VERT_BIT_COLOR0;
}
}
else {
inputs |= VERT_BIT_COLOR0;
if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) {
inputs |= VERT_BIT_COLOR1;
}
}
if (ctx->Texture.Unit[0]._ReallyEnabled) {
if (ctx->Texture.Unit[0].TexGenEnabled) {
if (rmesa->TexGenNeedNormals[0]) {
inputs |= VERT_BIT_NORMAL;
}
} else {
inputs |= VERT_BIT_TEX0;
}
}
if (ctx->Texture.Unit[1]._ReallyEnabled) {
if (ctx->Texture.Unit[1].TexGenEnabled) {
if (rmesa->TexGenNeedNormals[1]) {
inputs |= VERT_BIT_NORMAL;
}
} else {
inputs |= VERT_BIT_TEX1;
}
}
stage->inputs = inputs;
stage->active = 1;
}
else
stage->active = 0;
}
static void r200_init_tcl_render( GLcontext *ctx,
struct gl_pipeline_stage *stage )
{
stage->check = r200_check_tcl_render;
stage->check( ctx, stage );
}
static void dtr( struct gl_pipeline_stage *stage )
{
(void)stage;
}
/* Initial state for tcl stage.
*/
const struct gl_pipeline_stage _r200_tcl_stage =
{
"r200 render",
(_DD_NEW_SEPARATE_SPECULAR |
_NEW_LIGHT|
_NEW_TEXTURE|
_NEW_FOG|
_NEW_RENDERMODE), /* re-check (new inputs) */
0, /* re-run (always runs) */
GL_TRUE, /* active */
0, 0, /* inputs (set in check_render), outputs */
0, 0, /* changed_inputs, private */
dtr, /* destructor */
r200_init_tcl_render, /* check - initially set to alloc data */
r200_run_tcl_render /* run */
};
/**********************************************************************/
/* Validate state at pipeline start */
/**********************************************************************/
/*-----------------------------------------------------------------------
* Manage TCL fallbacks
*/
static void transition_to_swtnl( GLcontext *ctx )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
TNLcontext *tnl = TNL_CONTEXT(ctx);
R200_NEWPRIM( rmesa );
rmesa->swtcl.vertex_format = 0;
r200ChooseVertexState( ctx );
r200ChooseRenderState( ctx );
_mesa_validate_all_lighting_tables( ctx );
tnl->Driver.NotifyMaterialChange =
_mesa_validate_all_lighting_tables;
r200ReleaseArrays( ctx, ~0 );
/* Still using the D3D based hardware-rasterizer from the radeon;
* need to put the card into D3D mode to make it work:
*/
R200_STATECHANGE( rmesa, vap );
rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] &= ~R200_VAP_TCL_ENABLE;
rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] |= R200_VAP_D3D_TEX_DEFAULT;
R200_STATECHANGE( rmesa, vte );
rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] &= ~R200_VTX_W0_FMT;
R200_STATECHANGE( rmesa, set );
rmesa->hw.set.cmd[SET_RE_CNTL] |= (R200_VTX_STQ0_D3D |
R200_VTX_STQ1_D3D);
}
static void transition_to_hwtnl( GLcontext *ctx )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
TNLcontext *tnl = TNL_CONTEXT(ctx);
_tnl_need_projected_coords( ctx, GL_FALSE );
r200UpdateMaterial( ctx );
tnl->Driver.NotifyMaterialChange = r200UpdateMaterial;
if ( rmesa->dma.flush )
rmesa->dma.flush( rmesa );
rmesa->dma.flush = 0;
rmesa->swtcl.vertex_format = 0;
if (rmesa->swtcl.indexed_verts.buf)
r200ReleaseDmaRegion( rmesa, &rmesa->swtcl.indexed_verts,
__FUNCTION__ );
R200_STATECHANGE( rmesa, vap );
rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] |= R200_VAP_TCL_ENABLE;
rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] &= ~(R200_VAP_FORCE_W_TO_ONE |
R200_VAP_D3D_TEX_DEFAULT);
R200_STATECHANGE( rmesa, vte );
rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] &= ~(R200_VTX_XY_FMT|R200_VTX_Z_FMT);
rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] |= R200_VTX_W0_FMT;
R200_STATECHANGE( rmesa, set );
rmesa->hw.set.cmd[SET_RE_CNTL] &= ~(R200_VTX_STQ0_D3D |
R200_VTX_STQ1_D3D);
if (R200_DEBUG & DEBUG_FALLBACKS)
fprintf(stderr, "R200 end tcl fallback\n");
}
static char *fallbackStrings[] = {
"Rasterization fallback",
"Unfilled triangles",
"Twosided lighting, differing materials",
"Materials in VB (maybe between begin/end)",
"Texgen unit 0",
"Texgen unit 1",
"Texgen unit 2",
"User disable"
};
static char *getFallbackString(GLuint bit)
{
int i = 0;
while (bit > 1) {
i++;
bit >>= 1;
}
return fallbackStrings[i];
}
void r200TclFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
GLuint oldfallback = rmesa->TclFallback;
if (mode) {
rmesa->TclFallback |= bit;
if (oldfallback == 0) {
if (R200_DEBUG & DEBUG_FALLBACKS)
fprintf(stderr, "R200 begin tcl fallback %s\n",
getFallbackString( bit ));
transition_to_swtnl( ctx );
}
}
else {
rmesa->TclFallback &= ~bit;
if (oldfallback == bit) {
if (R200_DEBUG & DEBUG_FALLBACKS)
fprintf(stderr, "R200 end tcl fallback %s\n",
getFallbackString( bit ));
transition_to_hwtnl( ctx );
}
}
}

View File

@@ -0,0 +1,66 @@
/* $XFree86$ */
/*
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
The Weather Channel (TM) funded Tungsten Graphics to develop the
initial release of the Radeon 8500 driver under the XFree86 license.
This notice must be preserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#ifndef __R200_TCL_H__
#define __R200_TCL_H__
#ifdef GLX_DIRECT_RENDERING
#include "r200_context.h"
extern void r200TclPrimitive( GLcontext *ctx, GLenum prim, int hw_prim );
extern void r200EmitEltPrimitive( GLcontext *ctx, GLuint first, GLuint last,
GLuint flags );
extern void r200EmitPrimitive( GLcontext *ctx, GLuint first, GLuint last,
GLuint flags );
extern void r200TclFallback( GLcontext *ctx, GLuint bit, GLboolean mode );
#define R200_TCL_FALLBACK_RASTER 0x1 /* rasterization */
#define R200_TCL_FALLBACK_UNFILLED 0x2 /* unfilled tris */
#define R200_TCL_FALLBACK_LIGHT_TWOSIDE 0x4 /* twoside tris */
#define R200_TCL_FALLBACK_MATERIAL 0x8 /* material in vb */
#define R200_TCL_FALLBACK_TEXGEN_0 0x10 /* texgen, unit 0 */
#define R200_TCL_FALLBACK_TEXGEN_1 0x20 /* texgen, unit 1 */
#define R200_TCL_FALLBACK_TEXGEN_2 0x40 /* texgen, unit 2 */
#define R200_TCL_FALLBACK_TCL_DISABLE 0x80 /* user disable */
#define R200_TCL_FALLBACK_BITMAP 0x100 /* draw bitmap with points */
#define R200_MAX_TCL_VERTSIZE (4*4) /* using maos now... */
#define TCL_FALLBACK( ctx, bit, mode ) r200TclFallback( ctx, bit, mode )
#endif
#endif

View File

@@ -0,0 +1,988 @@
/* $XFree86$ */
/*
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
The Weather Channel (TM) funded Tungsten Graphics to develop the
initial release of the Radeon 8500 driver under the XFree86 license.
This notice must be preserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#include "glheader.h"
#include "imports.h"
#include "colormac.h"
#include "context.h"
#include "enums.h"
#include "image.h"
#include "mmath.h"
#include "simple_list.h"
#include "texformat.h"
#include "texstore.h"
#include "texutil.h"
#include "r200_context.h"
#include "r200_state.h"
#include "r200_ioctl.h"
#include "r200_swtcl.h"
#include "r200_tex.h"
/* =============================================================
* Utility functions:
*/
static void r200SetTexWrap( r200TexObjPtr t, GLenum swrap, GLenum twrap, GLenum rwrap )
{
t->pp_txfilter &= ~(R200_CLAMP_S_MASK | R200_CLAMP_T_MASK);
switch ( swrap ) {
case GL_REPEAT:
t->pp_txfilter |= R200_CLAMP_S_WRAP;
break;
case GL_CLAMP:
t->pp_txfilter |= R200_CLAMP_S_CLAMP_LAST;
break;
case GL_CLAMP_TO_EDGE:
t->pp_txfilter |= R200_CLAMP_S_CLAMP_LAST;
break;
case GL_CLAMP_TO_BORDER:
t->pp_txfilter |= R200_CLAMP_S_CLAMP_BORDER;
break;
case GL_MIRRORED_REPEAT_ARB:
t->pp_txfilter |= R200_CLAMP_S_MIRROR;
break;
case GL_MIRROR_CLAMP_ATI:
t->pp_txfilter |= R200_CLAMP_S_MIRROR_CLAMP_BORDER;
break;
case GL_MIRROR_CLAMP_TO_EDGE_ATI:
t->pp_txfilter |= R200_CLAMP_S_MIRROR_CLAMP_LAST;
break;
default:
_mesa_problem(NULL, "bad S wrap mode in r200SetTexWrap");
}
switch ( twrap ) {
case GL_REPEAT:
t->pp_txfilter |= R200_CLAMP_T_WRAP;
break;
case GL_CLAMP:
t->pp_txfilter |= R200_CLAMP_T_CLAMP_LAST;
break;
case GL_CLAMP_TO_EDGE:
t->pp_txfilter |= R200_CLAMP_T_CLAMP_LAST;
break;
case GL_CLAMP_TO_BORDER:
t->pp_txfilter |= R200_CLAMP_T_CLAMP_BORDER;
break;
case GL_MIRRORED_REPEAT_ARB:
t->pp_txfilter |= R200_CLAMP_T_MIRROR;
break;
case GL_MIRROR_CLAMP_ATI:
t->pp_txfilter |= R200_CLAMP_T_MIRROR_CLAMP_BORDER;
break;
case GL_MIRROR_CLAMP_TO_EDGE_ATI:
t->pp_txfilter |= R200_CLAMP_T_MIRROR_CLAMP_LAST;
break;
default:
_mesa_problem(NULL, "bad S wrap mode in r200SetTexWrap");
}
t->pp_txformat_x &= ~R200_CLAMP_Q_MASK;
switch ( rwrap ) {
case GL_REPEAT:
t->pp_txformat_x |= R200_CLAMP_Q_WRAP;
break;
case GL_CLAMP:
t->pp_txformat_x |= R200_CLAMP_Q_CLAMP_LAST;
break;
case GL_CLAMP_TO_EDGE:
t->pp_txformat_x |= R200_CLAMP_Q_CLAMP_LAST;
break;
case GL_CLAMP_TO_BORDER:
t->pp_txformat_x |= R200_CLAMP_Q_CLAMP_BORDER;
break;
case GL_MIRRORED_REPEAT_ARB:
t->pp_txformat_x |= R200_CLAMP_Q_MIRROR;
break;
case GL_MIRROR_CLAMP_ATI:
t->pp_txformat_x |= R200_CLAMP_Q_MIRROR_CLAMP_BORDER;
break;
case GL_MIRROR_CLAMP_TO_EDGE_ATI:
t->pp_txformat_x |= R200_CLAMP_Q_MIRROR_CLAMP_LAST;
break;
default:
_mesa_problem(NULL, "bad R wrap mode in r200SetTexWrap");
}
}
static void r200SetTexMaxAnisotropy( r200TexObjPtr t, GLfloat max )
{
t->pp_txfilter &= ~R200_MAX_ANISO_MASK;
if ( max == 1.0 ) {
t->pp_txfilter |= R200_MAX_ANISO_1_TO_1;
} else if ( max <= 2.0 ) {
t->pp_txfilter |= R200_MAX_ANISO_2_TO_1;
} else if ( max <= 4.0 ) {
t->pp_txfilter |= R200_MAX_ANISO_4_TO_1;
} else if ( max <= 8.0 ) {
t->pp_txfilter |= R200_MAX_ANISO_8_TO_1;
} else {
t->pp_txfilter |= R200_MAX_ANISO_16_TO_1;
}
}
static void r200SetTexFilter( r200TexObjPtr t, GLenum minf, GLenum magf )
{
GLuint anisotropy = (t->pp_txfilter & R200_MAX_ANISO_MASK);
t->pp_txfilter &= ~(R200_MIN_FILTER_MASK | R200_MAG_FILTER_MASK);
t->pp_txformat_x &= ~R200_VOLUME_FILTER_MASK;
if ( anisotropy == R200_MAX_ANISO_1_TO_1 ) {
switch ( minf ) {
case GL_NEAREST:
t->pp_txfilter |= R200_MIN_FILTER_NEAREST;
break;
case GL_LINEAR:
t->pp_txfilter |= R200_MIN_FILTER_LINEAR;
break;
case GL_NEAREST_MIPMAP_NEAREST:
t->pp_txfilter |= R200_MIN_FILTER_NEAREST_MIP_NEAREST;
break;
case GL_NEAREST_MIPMAP_LINEAR:
t->pp_txfilter |= R200_MIN_FILTER_LINEAR_MIP_NEAREST;
break;
case GL_LINEAR_MIPMAP_NEAREST:
t->pp_txfilter |= R200_MIN_FILTER_NEAREST_MIP_LINEAR;
break;
case GL_LINEAR_MIPMAP_LINEAR:
t->pp_txfilter |= R200_MIN_FILTER_LINEAR_MIP_LINEAR;
break;
}
} else {
switch ( minf ) {
case GL_NEAREST:
t->pp_txfilter |= R200_MIN_FILTER_ANISO_NEAREST;
break;
case GL_LINEAR:
t->pp_txfilter |= R200_MIN_FILTER_ANISO_LINEAR;
break;
case GL_NEAREST_MIPMAP_NEAREST:
case GL_LINEAR_MIPMAP_NEAREST:
t->pp_txfilter |= R200_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST;
break;
case GL_NEAREST_MIPMAP_LINEAR:
case GL_LINEAR_MIPMAP_LINEAR:
t->pp_txfilter |= R200_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR;
break;
}
}
/* Note we don't have 3D mipmaps so only use the mag filter setting
* to set the 3D texture filter mode.
*/
switch ( magf ) {
case GL_NEAREST:
t->pp_txfilter |= R200_MAG_FILTER_NEAREST;
t->pp_txformat_x |= R200_VOLUME_FILTER_NEAREST;
break;
case GL_LINEAR:
t->pp_txfilter |= R200_MAG_FILTER_LINEAR;
t->pp_txformat_x |= R200_VOLUME_FILTER_LINEAR;
break;
}
}
static void r200SetTexBorderColor( r200TexObjPtr t, GLubyte c[4] )
{
t->pp_border_color = r200PackColor( 4, c[0], c[1], c[2], c[3] );
}
static r200TexObjPtr r200AllocTexObj( struct gl_texture_object *texObj )
{
r200TexObjPtr t;
t = CALLOC_STRUCT( r200_tex_obj );
if (!t)
return NULL;
if ( R200_DEBUG & DEBUG_TEXTURE ) {
fprintf( stderr, "%s( %p, %p )\n", __FUNCTION__, texObj, t );
}
t->tObj = texObj;
make_empty_list( t );
/* Initialize non-image-dependent parts of the state:
*/
r200SetTexWrap( t, texObj->WrapS, texObj->WrapT, texObj->WrapR );
r200SetTexMaxAnisotropy( t, texObj->MaxAnisotropy );
r200SetTexFilter( t, texObj->MinFilter, texObj->MagFilter );
r200SetTexBorderColor( t, texObj->_BorderChan );
return t;
}
static const struct gl_texture_format *
r200ChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
GLenum format, GLenum type )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
const GLboolean do32bpt = ( rmesa->r200Screen->cpp == 4 );
switch ( internalFormat ) {
case 4:
case GL_RGBA:
if ( format == GL_BGRA ) {
if ( type == GL_UNSIGNED_INT_8_8_8_8_REV ) {
return &_mesa_texformat_argb8888;
}
else if ( type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) {
return &_mesa_texformat_argb4444;
}
else if ( type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) {
return &_mesa_texformat_argb1555;
}
}
return do32bpt ? &_mesa_texformat_rgba8888 : &_mesa_texformat_argb4444;
case 3:
case GL_RGB:
if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) {
return &_mesa_texformat_rgb565;
}
return do32bpt ? &_mesa_texformat_rgba8888 : &_mesa_texformat_rgb565;
case GL_RGBA8:
case GL_RGB10_A2:
case GL_RGBA12:
case GL_RGBA16:
return do32bpt ? &_mesa_texformat_rgba8888 : &_mesa_texformat_argb4444;
case GL_RGBA4:
case GL_RGBA2:
return &_mesa_texformat_argb4444;
case GL_RGB5_A1:
return &_mesa_texformat_argb1555;
case GL_RGB8:
case GL_RGB10:
case GL_RGB12:
case GL_RGB16:
return do32bpt ? &_mesa_texformat_rgba8888 : &_mesa_texformat_rgb565;
case GL_RGB5:
case GL_RGB4:
case GL_R3_G3_B2:
return &_mesa_texformat_rgb565;
case GL_ALPHA:
case GL_ALPHA4:
case GL_ALPHA8:
case GL_ALPHA12:
case GL_ALPHA16:
return &_mesa_texformat_al88;
case 1:
case GL_LUMINANCE:
case GL_LUMINANCE4:
case GL_LUMINANCE8:
case GL_LUMINANCE12:
case GL_LUMINANCE16:
return &_mesa_texformat_al88;
case 2:
case GL_LUMINANCE_ALPHA:
case GL_LUMINANCE4_ALPHA4:
case GL_LUMINANCE6_ALPHA2:
case GL_LUMINANCE8_ALPHA8:
case GL_LUMINANCE12_ALPHA4:
case GL_LUMINANCE12_ALPHA12:
case GL_LUMINANCE16_ALPHA16:
return &_mesa_texformat_al88;
case GL_INTENSITY:
case GL_INTENSITY4:
case GL_INTENSITY8:
case GL_INTENSITY12:
case GL_INTENSITY16:
/* At the moment, glean & conform both fail using the i8 internal
* format.
*/
return &_mesa_texformat_al88;
/* return &_mesa_texformat_i8; */
case GL_YCBCR_MESA:
if (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
type == GL_UNSIGNED_BYTE)
return &_mesa_texformat_ycbcr;
else
return &_mesa_texformat_ycbcr_rev;
default:
_mesa_problem(ctx, "unexpected texture format in r200ChoosTexFormat");
return NULL;
}
return NULL; /* never get here */
}
static GLboolean
r200ValidateClientStorage( GLcontext *ctx, GLenum target,
GLint internalFormat,
GLint srcWidth, GLint srcHeight,
GLenum format, GLenum type, const void *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
int texelBytes;
if (0)
fprintf(stderr, "intformat %s format %s type %s\n",
_mesa_lookup_enum_by_nr( internalFormat ),
_mesa_lookup_enum_by_nr( format ),
_mesa_lookup_enum_by_nr( type ));
if (!ctx->Unpack.ClientStorage)
return 0;
if (ctx->_ImageTransferState ||
texImage->IsCompressed ||
texObj->GenerateMipmap)
return 0;
/* This list is incomplete, may be different on ppc???
*/
switch ( internalFormat ) {
case GL_RGBA:
if ( format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8_REV ) {
texImage->TexFormat = &_mesa_texformat_argb8888;
texelBytes = 4;
}
else
return 0;
break;
case GL_YCBCR_MESA:
if ( format == GL_YCBCR_MESA &&
type == GL_UNSIGNED_SHORT_8_8_REV_APPLE ) {
texImage->TexFormat = &_mesa_texformat_ycbcr_rev;
texelBytes = 2;
}
else if ( format == GL_YCBCR_MESA &&
(type == GL_UNSIGNED_SHORT_8_8_APPLE ||
type == GL_UNSIGNED_BYTE)) {
texImage->TexFormat = &_mesa_texformat_ycbcr;
texelBytes = 2;
}
else
return 0;
break;
default:
return 0;
}
/* Could deal with these packing issues, but currently don't:
*/
if (packing->SkipPixels ||
packing->SkipRows ||
packing->SwapBytes ||
packing->LsbFirst) {
return 0;
}
{
GLint srcRowStride = _mesa_image_row_stride(packing, srcWidth,
format, type);
if (0)
fprintf(stderr, "%s: srcRowStride %d/%x\n",
__FUNCTION__, srcRowStride, srcRowStride);
/* Could check this later in upload, pitch restrictions could be
* relaxed, but would need to store the image pitch somewhere,
* as packing details might change before image is uploaded:
*/
if (!r200IsAgpMemory( rmesa, pixels, srcHeight * srcRowStride ) ||
(srcRowStride & 63))
return 0;
/* Have validated that _mesa_transfer_teximage would be a straight
* memcpy at this point. NOTE: future calls to TexSubImage will
* overwrite the client data. This is explicitly mentioned in the
* extension spec.
*/
texImage->Data = (void *)pixels;
texImage->IsClientData = GL_TRUE;
texImage->RowStride = srcRowStride / texelBytes;
return 1;
}
}
static void r200TexImage1D( GLcontext *ctx, GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint border,
GLenum format, GLenum type, const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
r200TexObjPtr t = (r200TexObjPtr) texObj->DriverData;
if ( t ) {
r200SwapOutTexObj( rmesa, t );
}
else {
t = r200AllocTexObj( texObj );
if (!t) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
return;
}
texObj->DriverData = t;
}
/* Note, this will call r200ChooseTextureFormat */
_mesa_store_teximage1d(ctx, target, level, internalFormat,
width, border, format, type, pixels,
&ctx->Unpack, texObj, texImage);
t->dirty_images[0] |= (1 << level);
}
static void r200TexSubImage1D( GLcontext *ctx, GLenum target, GLint level,
GLint xoffset,
GLsizei width,
GLenum format, GLenum type,
const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
r200TexObjPtr t = (r200TexObjPtr)texObj->DriverData;
assert( t ); /* this _should_ be true */
if ( t ) {
r200SwapOutTexObj( rmesa, t );
t->dirty_images[0] |= (1 << level);
}
else {
t = r200AllocTexObj(texObj);
if (!t) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
return;
}
texObj->DriverData = t;
}
_mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
format, type, pixels, packing, texObj,
texImage);
t->dirty_images[0] |= (1 << level);
}
static void r200TexImage2D( 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 )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
r200TexObjPtr t = (r200TexObjPtr)texObj->DriverData;
GLuint face;
/* which cube face or ordinary 2D image */
switch (target) {
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
ASSERT(face < 6);
break;
default:
face = 0;
}
if ( t ) {
r200SwapOutTexObj( rmesa, t );
}
else {
t = r200AllocTexObj( texObj );
if (!t) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
return;
}
texObj->DriverData = t;
}
texImage->IsClientData = GL_FALSE;
if (r200ValidateClientStorage( ctx, target,
internalFormat,
width, height,
format, type, pixels,
packing, texObj, texImage)) {
if (R200_DEBUG & DEBUG_TEXTURE)
fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);
}
else {
if (R200_DEBUG & DEBUG_TEXTURE)
fprintf(stderr, "%s: Using normal storage\n", __FUNCTION__);
/* Normal path: copy (to cached memory) and eventually upload
* via another copy to agp memory and then a blit... Could
* eliminate one copy by going straight to (permanent) agp.
*
* Note, this will call r200ChooseTextureFormat.
*/
_mesa_store_teximage2d(ctx, target, level, internalFormat,
width, height, border, format, type, pixels,
&ctx->Unpack, texObj, texImage);
t->dirty_images[face] |= (1 << level);
}
}
static void r200TexSubImage2D( 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 )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
r200TexObjPtr t = (r200TexObjPtr) texObj->DriverData;
GLuint face;
/* fprintf(stderr, "%s\n", __FUNCTION__); */
/* which cube face or ordinary 2D image */
switch (target) {
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
ASSERT(face < 6);
break;
default:
face = 0;
}
assert( t ); /* this _should_ be true */
if ( t ) {
r200SwapOutTexObj( rmesa, t );
}
else {
t = r200AllocTexObj(texObj);
if (!t) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
return;
}
texObj->DriverData = t;
}
_mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
height, format, type, pixels, packing, texObj,
texImage);
t->dirty_images[face] |= (1 << level);
}
static void r200TexImage3D( GLcontext *ctx, GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint height, GLint depth,
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 )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
r200TexObjPtr t = (r200TexObjPtr)texObj->DriverData;
if ( t ) {
r200SwapOutTexObj( rmesa, t );
}
else {
t = r200AllocTexObj( texObj );
if (!t) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
return;
}
texObj->DriverData = t;
}
texImage->IsClientData = GL_FALSE;
#if 0
if (r200ValidateClientStorage( ctx, target,
internalFormat,
width, height,
format, type, pixels,
packing, texObj, texImage)) {
if (R200_DEBUG & DEBUG_TEXTURE)
fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);
}
else
#endif
{
if (R200_DEBUG & DEBUG_TEXTURE)
fprintf(stderr, "%s: Using normal storage\n", __FUNCTION__);
/* Normal path: copy (to cached memory) and eventually upload
* via another copy to agp memory and then a blit... Could
* eliminate one copy by going straight to (permanent) agp.
*
* Note, this will call r200ChooseTextureFormat.
*/
_mesa_store_teximage3d(ctx, target, level, internalFormat,
width, height, depth, border,
format, type, pixels,
&ctx->Unpack, texObj, texImage);
t->dirty_images[0] |= (1 << level);
}
}
static void
r200TexSubImage3D( GLcontext *ctx, GLenum target, GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLenum type,
const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
r200TexObjPtr t = (r200TexObjPtr) texObj->DriverData;
/* fprintf(stderr, "%s\n", __FUNCTION__); */
assert( t ); /* this _should_ be true */
if ( t ) {
r200SwapOutTexObj( rmesa, t );
}
else {
t = r200AllocTexObj(texObj);
if (!t) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage3D");
return;
}
texObj->DriverData = t;
}
_mesa_store_texsubimage3d(ctx, target, level, xoffset, yoffset, zoffset,
width, height, depth,
format, type, pixels, packing, texObj, texImage);
t->dirty_images[0] |= (1 << level);
}
static void r200TexEnv( GLcontext *ctx, GLenum target,
GLenum pname, const GLfloat *param )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
GLuint unit = ctx->Texture.CurrentUnit;
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
if ( R200_DEBUG & DEBUG_STATE ) {
fprintf( stderr, "%s( %s )\n",
__FUNCTION__, _mesa_lookup_enum_by_nr( pname ) );
}
/* This is incorrect: Need to maintain this data for each of
* GL_TEXTURE_{123}D, GL_TEXTURE_RECTANGLE_NV, etc, and switch
* between them according to _ReallyEnabled.
*/
switch ( pname ) {
case GL_TEXTURE_ENV_COLOR: {
GLubyte c[4];
GLuint envColor;
UNCLAMPED_FLOAT_TO_RGBA_CHAN( c, texUnit->EnvColor );
envColor = r200PackColor( 4, c[0], c[1], c[2], c[3] );
if ( rmesa->hw.tf.cmd[TF_TFACTOR_0 + unit] != envColor ) {
R200_STATECHANGE( rmesa, tf );
rmesa->hw.tf.cmd[TF_TFACTOR_0 + unit] = envColor;
}
break;
}
case GL_TEXTURE_LOD_BIAS_EXT: {
GLfloat bias;
GLuint b;
const int fixed_one = 0x8000000;
/* The R200's LOD bias is a signed 2's complement value with a
* range of -16.0 <= bias < 16.0.
*
* NOTE: Add a small bias to the bias for conform mipsel.c test.
*/
bias = *param + .01;
bias = CLAMP( bias, -16.0, 16.0 );
b = (int)(bias * fixed_one) & R200_LOD_BIAS_MASK;
if ( (rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT_X] & R200_LOD_BIAS_MASK) != b ) {
R200_STATECHANGE( rmesa, tex[unit] );
rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT_X] &= ~R200_LOD_BIAS_MASK;
rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT_X] |= b;
}
break;
}
default:
return;
}
}
static void r200TexParameter( GLcontext *ctx, GLenum target,
struct gl_texture_object *texObj,
GLenum pname, const GLfloat *params )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
r200TexObjPtr t = (r200TexObjPtr) texObj->DriverData;
if ( R200_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) {
fprintf( stderr, "%s( %s )\n", __FUNCTION__,
_mesa_lookup_enum_by_nr( pname ) );
}
if (!t)
return;
switch ( pname ) {
case GL_TEXTURE_MIN_FILTER:
case GL_TEXTURE_MAG_FILTER:
case GL_TEXTURE_MAX_ANISOTROPY_EXT:
r200SetTexMaxAnisotropy( t, texObj->MaxAnisotropy );
r200SetTexFilter( t, texObj->MinFilter, texObj->MagFilter );
break;
case GL_TEXTURE_WRAP_S:
case GL_TEXTURE_WRAP_T:
case GL_TEXTURE_WRAP_R:
r200SetTexWrap( t, texObj->WrapS, texObj->WrapT, texObj->WrapR );
break;
case GL_TEXTURE_BORDER_COLOR:
r200SetTexBorderColor( t, texObj->_BorderChan );
break;
case GL_TEXTURE_BASE_LEVEL:
case GL_TEXTURE_MAX_LEVEL:
case GL_TEXTURE_MIN_LOD:
case GL_TEXTURE_MAX_LOD:
/* This isn't the most efficient solution but there doesn't appear to
* be a nice alternative for R200. Since there's no LOD clamping,
* we just have to rely on loading the right subset of mipmap levels
* to simulate a clamped LOD.
*/
r200SwapOutTexObj( rmesa, t );
break;
default:
return;
}
/* Mark this texobj as dirty (one bit per tex unit)
*/
t->dirty_state = TEX_ALL;
}
static void r200BindTexture( GLcontext *ctx, GLenum target,
struct gl_texture_object *texObj )
{
r200TexObjPtr t = (r200TexObjPtr) texObj->DriverData;
GLuint unit = ctx->Texture.CurrentUnit;
if ( R200_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) {
fprintf( stderr, "%s( %p ) unit=%d\n", __FUNCTION__, texObj, unit );
}
if ( target == GL_TEXTURE_2D || target == GL_TEXTURE_1D ) {
if ( !t ) {
t = r200AllocTexObj( texObj );
texObj->DriverData = t;
}
}
}
static void r200DeleteTexture( GLcontext *ctx,
struct gl_texture_object *texObj )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
r200TexObjPtr t = (r200TexObjPtr) texObj->DriverData;
if ( R200_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) {
fprintf( stderr, "%s( %p )\n", __FUNCTION__, texObj );
}
if ( t ) {
if ( rmesa ) {
R200_FIREVERTICES( rmesa );
}
r200DestroyTexObj( rmesa, t );
texObj->DriverData = NULL;
}
}
static GLboolean r200IsTextureResident( GLcontext *ctx,
struct gl_texture_object *texObj )
{
r200TexObjPtr t = (r200TexObjPtr) texObj->DriverData;
return ( t && t->memBlock );
}
static void r200InitTextureObjects( GLcontext *ctx )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
struct gl_texture_object *texObj;
GLuint tmp = ctx->Texture.CurrentUnit;
ctx->Texture.CurrentUnit = 0;
texObj = ctx->Texture.Unit[0].Current1D;
r200BindTexture( ctx, GL_TEXTURE_1D, texObj );
move_to_tail( &rmesa->texture.swapped,
(r200TexObjPtr)texObj->DriverData );
texObj = ctx->Texture.Unit[0].Current2D;
r200BindTexture( ctx, GL_TEXTURE_2D, texObj );
move_to_tail( &rmesa->texture.swapped,
(r200TexObjPtr)texObj->DriverData );
ctx->Texture.CurrentUnit = 1;
texObj = ctx->Texture.Unit[1].Current1D;
r200BindTexture( ctx, GL_TEXTURE_1D, texObj );
move_to_tail( &rmesa->texture.swapped,
(r200TexObjPtr)texObj->DriverData );
texObj = ctx->Texture.Unit[1].Current2D;
r200BindTexture( ctx, GL_TEXTURE_2D, texObj );
move_to_tail( &rmesa->texture.swapped,
(r200TexObjPtr)texObj->DriverData );
ctx->Texture.CurrentUnit = tmp;
}
/* Need:
* - Same GEN_MODE for all active bits
* - Same EyePlane/ObjPlane for all active bits when using Eye/Obj
* - STRQ presumably all supported (matrix means incoming R values
* can end up in STQ, this has implications for vertex support,
* presumably ok if maos is used, though?)
*
* Basically impossible to do this on the fly - just collect some
* basic info & do the checks from ValidateState().
*/
static void r200TexGen( GLcontext *ctx,
GLenum coord,
GLenum pname,
const GLfloat *params )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
GLuint unit = ctx->Texture.CurrentUnit;
rmesa->recheck_texgen[unit] = GL_TRUE;
}
void r200InitTextureFuncs( GLcontext *ctx )
{
ctx->Driver.ChooseTextureFormat = r200ChooseTextureFormat;
ctx->Driver.TexImage1D = r200TexImage1D;
ctx->Driver.TexImage2D = r200TexImage2D;
#if ENABLE_HW_3D_TEXTURE
ctx->Driver.TexImage3D = r200TexImage3D;
#else
ctx->Driver.TexImage3D = _mesa_store_teximage3d;
#endif
ctx->Driver.TexSubImage1D = r200TexSubImage1D;
ctx->Driver.TexSubImage2D = r200TexSubImage2D;
#if ENABLE_HW_3D_TEXTURE
ctx->Driver.TexSubImage3D = r200TexSubImage3D;
#else
ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
#endif
ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d;
ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d;
ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d;
ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d;
ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d;
ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage;
ctx->Driver.BindTexture = r200BindTexture;
ctx->Driver.CreateTexture = NULL; /* FIXME: Is this used??? */
ctx->Driver.DeleteTexture = r200DeleteTexture;
ctx->Driver.IsTextureResident = r200IsTextureResident;
ctx->Driver.PrioritizeTexture = NULL;
ctx->Driver.ActiveTexture = NULL;
ctx->Driver.UpdateTexturePalette = NULL;
ctx->Driver.TexEnv = r200TexEnv;
ctx->Driver.TexParameter = r200TexParameter;
ctx->Driver.TexGen = r200TexGen;
r200InitTextureObjects( ctx );
}

View File

@@ -0,0 +1,55 @@
/* $XFree86$ */
/*
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
The Weather Channel (TM) funded Tungsten Graphics to develop the
initial release of the Radeon 8500 driver under the XFree86 license.
This notice must be preserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#ifndef __R200_TEX_H__
#define __R200_TEX_H__
#ifdef GLX_DIRECT_RENDERING
extern void r200UpdateTextureState( GLcontext *ctx );
extern int r200UploadTexImages( r200ContextPtr rmesa, r200TexObjPtr t, GLuint face );
extern void r200AgeTextures( r200ContextPtr rmesa, int heap );
extern void r200DestroyTexObj( r200ContextPtr rmesa, r200TexObjPtr t );
extern void r200SwapOutTexObj( r200ContextPtr rmesa, r200TexObjPtr t );
extern void r200PrintLocalLRU( r200ContextPtr rmesa, int heap );
extern void r200PrintGlobalLRU( r200ContextPtr rmesa, int heap );
extern void r200UpdateTexLRU( r200ContextPtr rmesa, r200TexObjPtr t );
extern void r200InitTextureFuncs( GLcontext *ctx );
#endif
#endif /* __R200_TEX_H__ */

View File

@@ -0,0 +1,811 @@
/* $XFree86$ */
/**************************************************************************
Copyright (C) Tungsten Graphics 2002. All Rights Reserved.
The Weather Channel, Inc. funded Tungsten Graphics to develop the
initial release of the Radeon 8500 driver under the XFree86
license. This notice must be preserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation on the rights to use, copy, modify, merge, publish,
distribute, sub license, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR THEIR
SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
**************************************************************************/
/*
* Authors:
* Kevin E. Martin <martin@valinux.com>
* Gareth Hughes <gareth@valinux.com>
*
*/
#include "glheader.h"
#include "imports.h"
#include "context.h"
#include "colormac.h"
#include "mmath.h"
#include "macros.h"
#include "simple_list.h"
#include "radeon_reg.h" /* gets definition for usleep */
#include "r200_context.h"
#include "r200_state.h"
#include "r200_ioctl.h"
#include "r200_swtcl.h"
#include "r200_tex.h"
#include <unistd.h> /* for usleep() */
#include <errno.h>
/* Destroy hardware state associated with texture `t'.
*/
void r200DestroyTexObj( r200ContextPtr rmesa, r200TexObjPtr t )
{
if ( !t )
return;
if ( R200_DEBUG & DEBUG_TEXTURE ) {
fprintf( stderr, "%s( %p, %p )\n", __FUNCTION__, t, t->tObj );
}
if ( t->memBlock ) {
mmFreeMem( t->memBlock );
t->memBlock = NULL;
}
if ( t->tObj )
t->tObj->DriverData = NULL;
if ( rmesa ) {
if ( t == rmesa->state.texture.unit[0].texobj ) {
rmesa->state.texture.unit[0].texobj = NULL;
remove_from_list( &rmesa->hw.tex[0] );
make_empty_list( &rmesa->hw.tex[0] );
remove_from_list( &rmesa->hw.cube[0] );
make_empty_list( &rmesa->hw.cube[0] );
}
if ( t == rmesa->state.texture.unit[1].texobj ) {
rmesa->state.texture.unit[1].texobj = NULL;
remove_from_list( &rmesa->hw.tex[1] );
make_empty_list( &rmesa->hw.tex[1] );
remove_from_list( &rmesa->hw.cube[1] );
make_empty_list( &rmesa->hw.cube[1] );
}
}
remove_from_list( t );
FREE( t );
}
/* Keep track of swapped out texture objects.
*/
void r200SwapOutTexObj( r200ContextPtr rmesa, r200TexObjPtr t )
{
GLuint face;
if ( R200_DEBUG & DEBUG_TEXTURE ) {
fprintf( stderr, "%s( %p, %p )\n", __FUNCTION__, t, t->tObj );
}
if (t->memBlock) {
mmFreeMem( t->memBlock );
t->memBlock = NULL;
}
if (!t->tObj) {
remove_from_list( t );
FREE( t );
}
else {
for (face = 0; face < 6; face++)
t->dirty_images[face] = ~0;
move_to_tail( &rmesa->texture.swapped, t );
}
}
/* Print out debugging information about texture LRU.
*/
void r200PrintLocalLRU( r200ContextPtr rmesa, int heap )
{
r200TexObjPtr t;
int sz = 1 << (rmesa->r200Screen->logTexGranularity[heap]);
fprintf( stderr, "\nLocal LRU, heap %d:\n", heap );
foreach ( t, &rmesa->texture.objects[heap] ) {
if (!t->memBlock)
continue;
if (!t->tObj) {
fprintf( stderr, "Placeholder %d at 0x%x sz 0x%x\n",
t->memBlock->ofs / sz,
t->memBlock->ofs,
t->memBlock->size );
} else {
fprintf( stderr, "Texture at 0x%x sz 0x%x\n",
t->memBlock->ofs,
t->memBlock->size );
}
}
fprintf( stderr, "\n" );
}
void r200PrintGlobalLRU( r200ContextPtr rmesa, int heap )
{
radeon_tex_region_t *list = rmesa->sarea->texList[heap];
int i, j;
fprintf( stderr, "\nGlobal LRU, heap %d list %p:\n", heap, list );
for ( i = 0, j = RADEON_NR_TEX_REGIONS ; i < RADEON_NR_TEX_REGIONS ; i++ ) {
fprintf( stderr, "list[%d] age %d next %d prev %d\n",
j, list[j].age, list[j].next, list[j].prev );
j = list[j].next;
if ( j == RADEON_NR_TEX_REGIONS ) break;
}
if ( j != RADEON_NR_TEX_REGIONS ) {
fprintf( stderr, "Loop detected in global LRU\n" );
for ( i = 0 ; i < RADEON_NR_TEX_REGIONS ; i++ ) {
fprintf( stderr, "list[%d] age %d next %d prev %d\n",
i, list[i].age, list[i].next, list[i].prev );
}
}
fprintf( stderr, "\n" );
}
/* Reset the global texture LRU.
*/
static void r200ResetGlobalLRU( r200ContextPtr rmesa, int heap )
{
radeon_tex_region_t *list = rmesa->sarea->texList[heap];
int sz = 1 << rmesa->r200Screen->logTexGranularity[heap];
int i;
/*
* (Re)initialize the global circular LRU list. The last element in
* the array (RADEON_NR_TEX_REGIONS) is the sentinal. Keeping it at
* the end of the array allows it to be addressed rationally when
* looking up objects at a particular location in texture memory.
*/
for ( i = 0 ; (i+1) * sz <= rmesa->r200Screen->texSize[heap] ; i++ ) {
list[i].prev = i-1;
list[i].next = i+1;
list[i].age = 0;
}
i--;
list[0].prev = RADEON_NR_TEX_REGIONS;
list[i].prev = i-1;
list[i].next = RADEON_NR_TEX_REGIONS;
list[RADEON_NR_TEX_REGIONS].prev = i;
list[RADEON_NR_TEX_REGIONS].next = 0;
rmesa->sarea->texAge[heap] = 0;
}
/* Update the local and glock texture LRUs.
*/
void r200UpdateTexLRU(r200ContextPtr rmesa, r200TexObjPtr t )
{
int heap = t->heap;
radeon_tex_region_t *list = rmesa->sarea->texList[heap];
int sz = rmesa->r200Screen->logTexGranularity[heap];
int i, start, end;
rmesa->texture.age[heap] = ++rmesa->sarea->texAge[heap];
if ( !t->memBlock )
return;
start = t->memBlock->ofs >> sz;
end = (t->memBlock->ofs + t->memBlock->size-1) >> sz;
/* Update our local LRU */
move_to_head( &rmesa->texture.objects[heap], t );
/* Update the global LRU */
for ( i = start ; i <= end ; i++ ) {
list[i].in_use = 1;
list[i].age = rmesa->texture.age[heap];
/* remove_from_list(i) */
list[(GLuint)list[i].next].prev = list[i].prev;
list[(GLuint)list[i].prev].next = list[i].next;
/* insert_at_head(list, i) */
list[i].prev = RADEON_NR_TEX_REGIONS;
list[i].next = list[RADEON_NR_TEX_REGIONS].next;
list[(GLuint)list[RADEON_NR_TEX_REGIONS].next].prev = i;
list[RADEON_NR_TEX_REGIONS].next = i;
}
if ( 0 ) {
r200PrintGlobalLRU( rmesa, t->heap );
r200PrintLocalLRU( rmesa, t->heap );
}
}
/* Update our notion of what textures have been changed since we last
* held the lock. This pertains to both our local textures and the
* textures belonging to other clients. Keep track of other client's
* textures by pushing a placeholder texture onto the LRU list -- these
* are denoted by (tObj == NULL).
*/
static void r200TexturesGone( r200ContextPtr rmesa, int heap,
int offset, int size, int in_use )
{
r200TexObjPtr t, tmp;
foreach_s ( t, tmp, &rmesa->texture.objects[heap] ) {
if ( !t->memBlock ||
t->memBlock->ofs >= offset + size ||
t->memBlock->ofs + t->memBlock->size <= offset )
continue;
/* It overlaps - kick it out. Need to hold onto the currently
* bound objects, however.
*/
r200SwapOutTexObj( rmesa, t );
}
if ( in_use ) {
t = (r200TexObjPtr) CALLOC( sizeof(*t) );
if ( !t ) return;
t->memBlock = mmAllocMem( rmesa->texture.heap[heap], size, 0, offset );
if ( !t->memBlock ) {
fprintf( stderr, "Couldn't alloc placeholder sz %x ofs %x\n",
(int)size, (int)offset );
mmDumpMemInfo( rmesa->texture.heap[heap] );
return;
}
insert_at_head( &rmesa->texture.objects[heap], t );
}
}
/* Update our client's shared texture state. If another client has
* modified a region in which we have textures, then we need to figure
* out which of our textures has been removed, and update our global
* LRU.
*/
void r200AgeTextures( r200ContextPtr rmesa, int heap )
{
RADEONSAREAPrivPtr sarea = rmesa->sarea;
if ( R200_DEBUG & DEBUG_TEXTURE ) {
fprintf(stderr, "%s %d\n", __FUNCTION__, heap);
}
if ( sarea->texAge[heap] != rmesa->texture.age[heap] ) {
int sz = 1 << rmesa->r200Screen->logTexGranularity[heap];
int nr = 0;
int idx;
for ( idx = sarea->texList[heap][RADEON_NR_TEX_REGIONS].prev ;
idx != RADEON_NR_TEX_REGIONS && nr < RADEON_NR_TEX_REGIONS ;
idx = sarea->texList[heap][idx].prev, nr++ )
{
/* If switching texturing schemes, then the SAREA might not
* have been properly cleared, so we need to reset the
* global texture LRU.
*/
if ( idx * sz > rmesa->r200Screen->texSize[heap] ) {
nr = RADEON_NR_TEX_REGIONS;
break;
}
if ( sarea->texList[heap][idx].age > rmesa->texture.age[heap] ) {
r200TexturesGone( rmesa, heap, idx * sz, sz,
sarea->texList[heap][idx].in_use );
}
}
if ( nr == RADEON_NR_TEX_REGIONS ) {
r200TexturesGone( rmesa, heap, 0,
rmesa->r200Screen->texSize[heap], 0 );
r200ResetGlobalLRU( rmesa, heap );
}
rmesa->texture.age[heap] = sarea->texAge[heap];
}
}
/* ------------------------------------------------------------
* Texture image conversions
*/
static void r200UploadAGPClientSubImage( r200ContextPtr rmesa,
r200TexObjPtr t,
struct gl_texture_image *texImage,
GLint hwlevel,
GLint x, GLint y,
GLint width, GLint height )
{
const struct gl_texture_format *texFormat = texImage->TexFormat;
GLuint srcPitch, dstPitch;
int blit_format;
int srcOffset;
/*
* XXX it appears that we always upload the full image, not a subimage.
* I.e. x==0, y==0, width=texWidth, height=texWidth. If this is ever
* changed, the src pitch will have to change.
*/
switch ( texFormat->TexelBytes ) {
case 1:
blit_format = R200_CP_COLOR_FORMAT_CI8;
srcPitch = t->image[0][0].width * texFormat->TexelBytes;
dstPitch = t->image[0][0].width * texFormat->TexelBytes;
break;
case 2:
blit_format = R200_CP_COLOR_FORMAT_RGB565;
srcPitch = t->image[0][0].width * texFormat->TexelBytes;
dstPitch = t->image[0][0].width * texFormat->TexelBytes;
break;
case 4:
blit_format = R200_CP_COLOR_FORMAT_ARGB8888;
srcPitch = t->image[0][0].width * texFormat->TexelBytes;
dstPitch = t->image[0][0].width * texFormat->TexelBytes;
break;
default:
return;
}
t->image[0][hwlevel].data = texImage->Data;
srcOffset = r200AgpOffsetFromVirtual( rmesa, texImage->Data );
assert( srcOffset != ~0 );
/* Don't currently need to cope with small pitches?
*/
width = texImage->Width;
height = texImage->Height;
r200EmitWait( rmesa, RADEON_WAIT_3D );
r200EmitBlit( rmesa, blit_format,
srcPitch,
srcOffset,
dstPitch,
t->bufAddr,
x,
y,
t->image[0][hwlevel].x + x,
t->image[0][hwlevel].y + y,
width,
height );
r200EmitWait( rmesa, RADEON_WAIT_2D );
}
static void r200UploadRectSubImage( r200ContextPtr rmesa,
r200TexObjPtr t,
struct gl_texture_image *texImage,
GLint x, GLint y,
GLint width, GLint height )
{
const struct gl_texture_format *texFormat = texImage->TexFormat;
int blit_format, dstPitch, done;
switch ( texFormat->TexelBytes ) {
case 1:
blit_format = R200_CP_COLOR_FORMAT_CI8;
break;
case 2:
blit_format = R200_CP_COLOR_FORMAT_RGB565;
break;
case 4:
blit_format = R200_CP_COLOR_FORMAT_ARGB8888;
break;
default:
return;
}
t->image[0][0].data = texImage->Data;
/* Currently don't need to cope with small pitches.
*/
width = texImage->Width;
height = texImage->Height;
dstPitch = t->pp_txpitch + 32;
if (rmesa->prefer_agp_client_texturing && texImage->IsClientData) {
/* In this case, could also use agp texturing. This is
* currently disabled, but has been tested & works.
*/
t->pp_txoffset = r200AgpOffsetFromVirtual( rmesa, texImage->Data );
t->pp_txpitch = texImage->RowStride * texFormat->TexelBytes - 32;
if (R200_DEBUG & DEBUG_TEXTURE)
fprintf(stderr,
"Using agp texturing for rectangular client texture\n");
/* Release FB memory allocated for this image:
*/
if ( t->memBlock ) {
mmFreeMem( t->memBlock );
t->memBlock = NULL;
}
}
else if (texImage->IsClientData) {
/* Data already in agp memory, with usable pitch.
*/
GLuint srcPitch;
srcPitch = texImage->RowStride * texFormat->TexelBytes;
r200EmitBlit( rmesa,
blit_format,
srcPitch,
r200AgpOffsetFromVirtual( rmesa, texImage->Data ),
dstPitch, t->bufAddr,
0, 0,
0, 0,
width, height );
}
else {
/* Data not in agp memory, or bad pitch.
*/
for (done = 0; done < height ; ) {
struct r200_dma_region region;
int lines = MIN2( height - done, RADEON_BUFFER_SIZE / dstPitch );
int src_pitch;
char *tex;
src_pitch = texImage->RowStride * texFormat->TexelBytes;
tex = (char *)texImage->Data + done * src_pitch;
memset(&region, 0, sizeof(region));
r200AllocDmaRegion( rmesa, &region, lines * dstPitch, 64 );
/* Copy texdata to dma:
*/
if (0)
fprintf(stderr, "%s: src_pitch %d dst_pitch %d\n",
__FUNCTION__, src_pitch, dstPitch);
if (src_pitch == dstPitch) {
memcpy( region.address, tex, lines * src_pitch );
}
else {
char *buf = region.address;
int i;
for (i = 0 ; i < lines ; i++) {
memcpy( buf, tex, src_pitch );
buf += dstPitch;
tex += src_pitch;
}
}
r200EmitWait( rmesa, RADEON_WAIT_3D );
/* Blit to framebuffer
*/
r200EmitBlit( rmesa,
blit_format,
dstPitch, GET_START( &region ),
dstPitch, t->bufAddr,
0, 0,
0, done,
width, lines );
r200EmitWait( rmesa, RADEON_WAIT_2D );
r200ReleaseDmaRegion( rmesa, &region, __FUNCTION__ );
done += lines;
}
}
}
/* Upload the texture image associated with texture `t' at level `level'
* at the address relative to `start'.
*/
static void r200UploadSubImage( r200ContextPtr rmesa,
r200TexObjPtr t,
GLint hwlevel,
GLint x, GLint y, GLint width, GLint height,
GLuint face )
{
struct gl_texture_image *texImage = NULL;
const struct gl_texture_format *texFormat;
GLint texelsPerDword = 0;
GLuint format, pitch, offset;
GLint imageWidth, imageHeight;
GLint ret;
drmRadeonTexture tex;
drmRadeonTexImage tmp;
int level = hwlevel + t->firstLevel;
if ( R200_DEBUG & DEBUG_TEXTURE ) {
fprintf( stderr, "%s level %d %dx%d\n", __FUNCTION__,
level, width, height);
}
ASSERT(face < 6);
/* Ensure we have a valid texture to upload */
if ( ( hwlevel < 0 ) || ( hwlevel >= RADEON_MAX_TEXTURE_LEVELS ) ) {
_mesa_problem(NULL, "bad texture level in r200UploadSubimage");
return;
}
switch (face) {
case 0:
texImage = t->tObj->Image[level];
break;
case 1:
texImage = t->tObj->NegX[level];
break;
case 2:
texImage = t->tObj->PosY[level];
break;
case 3:
texImage = t->tObj->NegY[level];
break;
case 4:
texImage = t->tObj->PosZ[level];
break;
case 5:
texImage = t->tObj->NegZ[level];
break;
}
if ( !texImage ) {
if ( R200_DEBUG & DEBUG_TEXTURE )
fprintf( stderr, "%s: texImage %d is NULL!\n", __FUNCTION__, level );
return;
}
if ( !texImage->Data ) {
if ( R200_DEBUG & DEBUG_TEXTURE )
fprintf( stderr, "%s: image data is NULL!\n", __FUNCTION__ );
return;
}
if (t->tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
assert(level == 0);
assert(hwlevel == 0);
if ( R200_DEBUG & DEBUG_TEXTURE )
fprintf( stderr, "%s: image data is rectangular\n", __FUNCTION__);
r200UploadRectSubImage( rmesa, t, texImage, x, y, width, height );
return;
}
else if (texImage->IsClientData) {
if ( R200_DEBUG & DEBUG_TEXTURE )
fprintf( stderr, "%s: image data is in agp client storage\n",
__FUNCTION__);
r200UploadAGPClientSubImage( rmesa, t, texImage, hwlevel,
x, y, width, height );
return;
}
else if ( R200_DEBUG & DEBUG_TEXTURE )
fprintf( stderr, "%s: image data is in normal memory\n",
__FUNCTION__);
texFormat = texImage->TexFormat;
switch ( texFormat->TexelBytes ) {
case 1:
texelsPerDword = 4;
break;
case 2:
texelsPerDword = 2;
break;
case 4:
texelsPerDword = 1;
break;
}
format = t->pp_txformat & R200_TXFORMAT_FORMAT_MASK;
imageWidth = texImage->Width;
imageHeight = texImage->Height;
offset = t->bufAddr;
if (texFormat->TexelBytes == 0)
pitch = (t->image[face][0].width * 1) / 64;
else
pitch = (t->image[face][0].width * texFormat->TexelBytes) / 64;
if ( R200_DEBUG & (DEBUG_TEXTURE|DEBUG_IOCTL) )
{
GLint imageX = 0;
GLint imageY = 0;
GLint blitX = t->image[face][hwlevel].x;
GLint blitY = t->image[face][hwlevel].y;
GLint blitWidth = t->image[face][hwlevel].width;
GLint blitHeight = t->image[face][hwlevel].height;
fprintf( stderr, " upload image: %d,%d at %d,%d\n",
imageWidth, imageHeight, imageX, imageY );
fprintf( stderr, " upload blit: %d,%d at %d,%d\n",
blitWidth, blitHeight, blitX, blitY );
fprintf( stderr, " blit ofs: 0x%07x pitch: 0x%x "
"level: %d/%d format: %x\n",
(GLuint)offset, (GLuint)pitch, hwlevel, level, format );
}
t->image[face][hwlevel].data = texImage->Data;
/* Init the DRM_RADEON_TEXTURE command / drmRadeonTexture struct.
* NOTE: we're always use a 1KB-wide blit and I8 texture format.
* We used to use 1, 2 and 4-byte texels and used to use the texture
* width to dictate the blit width - but that won't work for compressed
* textures. (Brian)
*/
tex.offset = offset;
tex.pitch = BLIT_WIDTH_BYTES / 64;
tex.format = R200_TXFORMAT_I8; /* any 1-byte texel format */
if (texImage->TexFormat->TexelBytes) {
tex.width = imageWidth * texImage->TexFormat->TexelBytes; /* in bytes */
tex.height = imageHeight;
}
else {
tex.width = imageWidth; /* compressed */
tex.height = imageHeight;
if (tex.height < 4)
tex.height = 4;
}
tex.image = &tmp;
/* copy (x,y,width,height,data) */
memcpy( &tmp, &t->image[face][hwlevel], sizeof(drmRadeonTexImage) );
LOCK_HARDWARE( rmesa );
do {
ret = drmCommandWriteRead( rmesa->dri.fd, DRM_RADEON_TEXTURE,
&tex, sizeof(drmRadeonTexture) );
if (ret) {
if (R200_DEBUG & DEBUG_IOCTL)
fprintf(stderr, "DRM_RADEON_TEXTURE: again!\n");
usleep(1);
}
} while ( ret && errno == EAGAIN );
UNLOCK_HARDWARE( rmesa );
if ( ret ) {
fprintf( stderr, "DRM_R200_TEXTURE: return = %d\n", ret );
fprintf( stderr, " offset=0x%08x pitch=0x%x format=%d\n",
offset, pitch, format );
fprintf( stderr, " image width=%d height=%d\n",
imageWidth, imageHeight );
fprintf( stderr, " blit width=%d height=%d data=%p\n",
t->image[face][hwlevel].width, t->image[face][hwlevel].height,
t->image[face][hwlevel].data );
exit( 1 );
}
}
/* Upload the texture images associated with texture `t'. This might
* require removing our own and/or other client's texture objects to
* make room for these images.
*/
int r200UploadTexImages( r200ContextPtr rmesa, r200TexObjPtr t, GLuint face )
{
const int numLevels = t->lastLevel - t->firstLevel + 1;
int heap;
r200TexObjPtr t0 = rmesa->state.texture.unit[0].texobj;
r200TexObjPtr t1 = rmesa->state.texture.unit[1].texobj;
if ( R200_DEBUG & (DEBUG_TEXTURE|DEBUG_IOCTL) ) {
fprintf( stderr, "%s( %p, %p ) sz=%d lvls=%d-%d\n", __FUNCTION__,
rmesa->glCtx, t->tObj, t->totalSize,
t->firstLevel, t->lastLevel );
}
if ( !t || t->totalSize == 0 )
return 0;
if (R200_DEBUG & DEBUG_SYNC) {
fprintf(stderr, "\nSyncing\n\n");
R200_FIREVERTICES( rmesa );
r200Finish( rmesa->glCtx );
}
LOCK_HARDWARE( rmesa );
/* Choose the heap appropriately */
heap = t->heap = RADEON_CARD_HEAP;
/* Do we need to eject LRU texture objects? */
if ( !t->memBlock ) {
/* Allocate a memory block on a 1k boundary (1<<10 == 1024) */
t->memBlock = mmAllocMem( rmesa->texture.heap[heap],
t->totalSize, 10, 0 );
/* Kick out textures until the requested texture fits */
while ( !t->memBlock ) {
if ( rmesa->texture.objects[heap].prev == t0 ||
rmesa->texture.objects[heap].prev == t1 ) {
fprintf( stderr,
"r200UploadTexImages: ran into bound texture\n" );
UNLOCK_HARDWARE( rmesa );
return -1;
}
if ( rmesa->texture.objects[heap].prev ==
&rmesa->texture.objects[heap] ) {
if ( rmesa->r200Screen->IsPCI ) {
fprintf( stderr, "r200UploadTexImages: upload texture "
"failure on local texture heaps, sz=%d\n",
t->totalSize );
UNLOCK_HARDWARE( rmesa );
return -1;
} else {
fprintf( stderr, "r200UploadTexImages: upload texture "
"failure on both local and AGP texture heaps, "
"sz=%d\n",
t->totalSize );
UNLOCK_HARDWARE( rmesa );
return -1;
}
}
r200SwapOutTexObj( rmesa, rmesa->texture.objects[heap].prev );
t->memBlock = mmAllocMem( rmesa->texture.heap[heap],
t->totalSize, 12, 0 );
}
/* Set the base offset of the texture image */
t->bufAddr = rmesa->r200Screen->texOffset[heap] + t->memBlock->ofs;
t->pp_txoffset = t->bufAddr;
/* Mark this texobj as dirty on all units:
*/
t->dirty_state = TEX_ALL;
}
/* Let the world know we've used this memory recently */
r200UpdateTexLRU( rmesa, t );
UNLOCK_HARDWARE( rmesa );
/* Upload any images that are new */
if (t->dirty_images[face]) {
int hwlevel;
for ( hwlevel = 0 ; hwlevel < numLevels ; hwlevel++ ) {
if ( t->dirty_images[face] & (1 << (hwlevel+t->firstLevel)) ) {
r200UploadSubImage( rmesa, t, hwlevel,
0, 0,
t->image[face][hwlevel].width,
t->image[face][hwlevel].height, face );
}
}
t->dirty_images[face] = 0;
}
if (R200_DEBUG & DEBUG_SYNC) {
fprintf(stderr, "\nSyncing\n\n");
r200Finish( rmesa->glCtx );
}
return 0;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,128 @@
/* $XFree86$ */
/*
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
The Weather Channel (TM) funded Tungsten Graphics to develop the
initial release of the Radeon 8500 driver under the XFree86 license.
This notice must be preserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#ifndef __R200_VTXFMT_H__
#define __R200_VTXFMT_H__
#ifdef GLX_DIRECT_RENDERING
#include "r200_context.h"
extern struct r200_vb vb;
extern void r200VtxfmtUpdate( GLcontext *ctx );
extern void r200VtxfmtInit( GLcontext *ctx );
extern void r200VtxfmtInvalidate( GLcontext *ctx );
extern void r200VtxfmtDestroy( GLcontext *ctx );
extern void r200VtxfmtInitChoosers( GLvertexformat *vfmt );
extern void r200VtxfmtMakeCurrent( GLcontext *ctx );
extern void r200VtxfmtUnbindContext( GLcontext *ctx );
extern void r200_copy_to_current( GLcontext *ctx );
#define DFN( FUNC, CACHE) \
do { \
char *start = (char *)&FUNC; \
char *end = (char *)&FUNC##_end; \
insert_at_head( &CACHE, dfn ); \
dfn->key[0] = key[0]; \
dfn->key[1] = key[1]; \
dfn->code = ALIGN_MALLOC( end - start, 16 ); \
memcpy (dfn->code, start, end - start); \
} \
while ( 0 )
#define FIXUP( CODE, OFFSET, CHECKVAL, NEWVAL ) \
do { \
int *icode = (int *)(CODE+OFFSET); \
assert (*icode == CHECKVAL); \
*icode = (int)NEWVAL; \
} while (0)
/* Useful for figuring out the offsets:
*/
#define FIXUP2( CODE, OFFSET, CHECKVAL, NEWVAL ) \
do { \
while (*(int *)(CODE+OFFSET) != CHECKVAL) OFFSET++; \
/*fprintf(stderr, "%s/%d CVAL %x OFFSET %d VAL %x\n", __FUNCTION__,*/ \
/* __LINE__, CHECKVAL, OFFSET, (int)(NEWVAL));*/ \
*(int *)(CODE+OFFSET) = (int)(NEWVAL); \
OFFSET += 4; \
} while (0)
/*
*/
void r200InitCodegen( struct dfn_generators *gen );
void r200InitX86Codegen( struct dfn_generators *gen );
void r200InitSSECodegen( struct dfn_generators *gen );
/* Defined in r200_vtxfmt_x86.c
*/
struct dynfn *r200_makeX86Vertex2f( GLcontext *, const int * );
struct dynfn *r200_makeX86Vertex2fv( GLcontext *, const int * );
struct dynfn *r200_makeX86Vertex3f( GLcontext *, const int * );
struct dynfn *r200_makeX86Vertex3fv( GLcontext *, const int * );
struct dynfn *r200_makeX86Color4ub( GLcontext *, const int * );
struct dynfn *r200_makeX86Color4ubv( GLcontext *, const int * );
struct dynfn *r200_makeX86Color3ub( GLcontext *, const int * );
struct dynfn *r200_makeX86Color3ubv( GLcontext *, const int * );
struct dynfn *r200_makeX86Color4f( GLcontext *, const int * );
struct dynfn *r200_makeX86Color4fv( GLcontext *, const int * );
struct dynfn *r200_makeX86Color3f( GLcontext *, const int * );
struct dynfn *r200_makeX86Color3fv( GLcontext *, const int * );
struct dynfn *r200_makeX86SecondaryColor3ubEXT( GLcontext *, const int * );
struct dynfn *r200_makeX86SecondaryColor3ubvEXT( GLcontext *, const int * );
struct dynfn *r200_makeX86SecondaryColor3fEXT( GLcontext *, const int * );
struct dynfn *r200_makeX86SecondaryColor3fvEXT( GLcontext *, const int * );
struct dynfn *r200_makeX86Normal3f( GLcontext *, const int * );
struct dynfn *r200_makeX86Normal3fv( GLcontext *, const int * );
struct dynfn *r200_makeX86TexCoord2f( GLcontext *, const int * );
struct dynfn *r200_makeX86TexCoord2fv( GLcontext *, const int * );
struct dynfn *r200_makeX86TexCoord1f( GLcontext *, const int * );
struct dynfn *r200_makeX86TexCoord1fv( GLcontext *, const int * );
struct dynfn *r200_makeX86MultiTexCoord2fARB( GLcontext *, const int * );
struct dynfn *r200_makeX86MultiTexCoord2fvARB( GLcontext *, const int * );
struct dynfn *r200_makeX86MultiTexCoord1fARB( GLcontext *, const int * );
struct dynfn *r200_makeX86MultiTexCoord1fvARB( GLcontext *, const int * );
#endif
#endif

View File

@@ -0,0 +1,797 @@
/* $XFree86$ */
/*
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
The Weather Channel (TM) funded Tungsten Graphics to develop the
initial release of the Radeon 8500 driver under the XFree86 license.
This notice must be preserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#include "glheader.h"
#include "imports.h"
#include "mtypes.h"
#include "colormac.h"
#include "simple_list.h"
#include "api_noop.h"
#include "vtxfmt.h"
#include "r200_vtxfmt.h"
/* Fallback versions of all the entrypoints for situations where
* codegen isn't available. This is still a lot faster than the
* vb/pipeline implementation in Mesa.
*/
static void r200_Vertex3f( GLfloat x, GLfloat y, GLfloat z )
{
int i;
*vb.dmaptr++ = *(int *)&x;
*vb.dmaptr++ = *(int *)&y;
*vb.dmaptr++ = *(int *)&z;
for (i = 3; i < vb.vertex_size; i++)
*vb.dmaptr++ = vb.vertex[i].i;
if (--vb.counter == 0)
vb.notify();
}
static void r200_Vertex3fv( const GLfloat *v )
{
int i;
*vb.dmaptr++ = *(int *)&v[0];
*vb.dmaptr++ = *(int *)&v[1];
*vb.dmaptr++ = *(int *)&v[2];
for (i = 3; i < vb.vertex_size; i++)
*vb.dmaptr++ = vb.vertex[i].i;
if (--vb.counter == 0)
vb.notify();
}
static void r200_Vertex2f( GLfloat x, GLfloat y )
{
int i;
*vb.dmaptr++ = *(int *)&x;
*vb.dmaptr++ = *(int *)&y;
*vb.dmaptr++ = 0;
for (i = 3; i < vb.vertex_size; i++)
*vb.dmaptr++ = vb.vertex[i].i;
if (--vb.counter == 0)
vb.notify();
}
static void r200_Vertex2fv( const GLfloat *v )
{
int i;
*vb.dmaptr++ = *(int *)&v[0];
*vb.dmaptr++ = *(int *)&v[1];
*vb.dmaptr++ = 0;
for (i = 3; i < vb.vertex_size; i++)
*vb.dmaptr++ = vb.vertex[i].i;
if (--vb.counter == 0)
vb.notify();
}
/* Color for ubyte (packed) color formats:
*/
static void r200_Color3ub_ub( GLubyte r, GLubyte g, GLubyte b )
{
r200_color_t *dest = vb.colorptr;
dest->red = r;
dest->green = g;
dest->blue = b;
dest->alpha = 0xff;
}
static void r200_Color3ubv_ub( const GLubyte *v )
{
r200_color_t *dest = vb.colorptr;
dest->red = v[0];
dest->green = v[1];
dest->blue = v[2];
dest->alpha = 0xff;
}
static void r200_Color4ub_ub( GLubyte r, GLubyte g, GLubyte b, GLubyte a )
{
r200_color_t *dest = vb.colorptr;
dest->red = r;
dest->green = g;
dest->blue = b;
dest->alpha = a;
}
static void r200_Color4ubv_ub( const GLubyte *v )
{
*(GLuint *)vb.colorptr = LE32_TO_CPU(*(GLuint *)v);
}
static void r200_Color3f_ub( GLfloat r, GLfloat g, GLfloat b )
{
r200_color_t *dest = vb.colorptr;
UNCLAMPED_FLOAT_TO_UBYTE( dest->red, r );
UNCLAMPED_FLOAT_TO_UBYTE( dest->green, g );
UNCLAMPED_FLOAT_TO_UBYTE( dest->blue, b );
dest->alpha = 255;
}
static void r200_Color3fv_ub( const GLfloat *v )
{
r200_color_t *dest = vb.colorptr;
UNCLAMPED_FLOAT_TO_UBYTE( dest->red, v[0] );
UNCLAMPED_FLOAT_TO_UBYTE( dest->green, v[1] );
UNCLAMPED_FLOAT_TO_UBYTE( dest->blue, v[2] );
dest->alpha = 255;
}
static void r200_Color4f_ub( GLfloat r, GLfloat g, GLfloat b, GLfloat a )
{
r200_color_t *dest = vb.colorptr;
UNCLAMPED_FLOAT_TO_UBYTE( dest->red, r );
UNCLAMPED_FLOAT_TO_UBYTE( dest->green, g );
UNCLAMPED_FLOAT_TO_UBYTE( dest->blue, b );
UNCLAMPED_FLOAT_TO_UBYTE( dest->alpha, a );
}
static void r200_Color4fv_ub( const GLfloat *v )
{
r200_color_t *dest = vb.colorptr;
UNCLAMPED_FLOAT_TO_UBYTE( dest->red, v[0] );
UNCLAMPED_FLOAT_TO_UBYTE( dest->green, v[1] );
UNCLAMPED_FLOAT_TO_UBYTE( dest->blue, v[2] );
UNCLAMPED_FLOAT_TO_UBYTE( dest->alpha, v[3] );
}
/* Color for float color+alpha formats:
*/
static void r200_Color3ub_4f( GLubyte r, GLubyte g, GLubyte b )
{
GLfloat *dest = vb.floatcolorptr;
dest[0] = UBYTE_TO_FLOAT(r);
dest[1] = UBYTE_TO_FLOAT(g);
dest[2] = UBYTE_TO_FLOAT(b);
dest[3] = 1.0;
}
static void r200_Color3ubv_4f( const GLubyte *v )
{
GLfloat *dest = vb.floatcolorptr;
dest[0] = UBYTE_TO_FLOAT(v[0]);
dest[1] = UBYTE_TO_FLOAT(v[1]);
dest[2] = UBYTE_TO_FLOAT(v[2]);
dest[3] = 1.0;
}
static void r200_Color4ub_4f( GLubyte r, GLubyte g, GLubyte b, GLubyte a )
{
GLfloat *dest = vb.floatcolorptr;
dest[0] = UBYTE_TO_FLOAT(r);
dest[1] = UBYTE_TO_FLOAT(g);
dest[2] = UBYTE_TO_FLOAT(b);
dest[3] = UBYTE_TO_FLOAT(a);
}
static void r200_Color4ubv_4f( const GLubyte *v )
{
GLfloat *dest = vb.floatcolorptr;
dest[0] = UBYTE_TO_FLOAT(v[0]);
dest[1] = UBYTE_TO_FLOAT(v[1]);
dest[2] = UBYTE_TO_FLOAT(v[2]);
dest[3] = UBYTE_TO_FLOAT(v[3]);
}
static void r200_Color3f_4f( GLfloat r, GLfloat g, GLfloat b )
{
GLfloat *dest = vb.floatcolorptr;
dest[0] = r;
dest[1] = g;
dest[2] = b;
dest[3] = 1.0;
}
static void r200_Color3fv_4f( const GLfloat *v )
{
GLfloat *dest = vb.floatcolorptr;
dest[0] = v[0];
dest[1] = v[1];
dest[2] = v[2];
dest[3] = 1.0;
}
static void r200_Color4f_4f( GLfloat r, GLfloat g, GLfloat b, GLfloat a )
{
GLfloat *dest = vb.floatcolorptr;
dest[0] = r;
dest[1] = g;
dest[2] = b;
dest[3] = a;
}
static void r200_Color4fv_4f( const GLfloat *v )
{
GLfloat *dest = vb.floatcolorptr;
dest[0] = v[0];
dest[1] = v[1];
dest[2] = v[2];
dest[3] = v[3];
}
/* Color for float color formats:
*/
static void r200_Color3ub_3f( GLubyte r, GLubyte g, GLubyte b )
{
GLfloat *dest = vb.floatcolorptr;
dest[0] = UBYTE_TO_FLOAT(r);
dest[1] = UBYTE_TO_FLOAT(g);
dest[2] = UBYTE_TO_FLOAT(b);
}
static void r200_Color3ubv_3f( const GLubyte *v )
{
GLfloat *dest = vb.floatcolorptr;
dest[0] = UBYTE_TO_FLOAT(v[0]);
dest[1] = UBYTE_TO_FLOAT(v[1]);
dest[2] = UBYTE_TO_FLOAT(v[2]);
}
static void r200_Color4ub_3f( GLubyte r, GLubyte g, GLubyte b, GLubyte a )
{
GLfloat *dest = vb.floatcolorptr;
dest[0] = UBYTE_TO_FLOAT(r);
dest[1] = UBYTE_TO_FLOAT(g);
dest[2] = UBYTE_TO_FLOAT(b);
vb.context->Current.Attrib[VERT_ATTRIB_COLOR0][3] = UBYTE_TO_FLOAT(a);
}
static void r200_Color4ubv_3f( const GLubyte *v )
{
GLfloat *dest = vb.floatcolorptr;
dest[0] = UBYTE_TO_FLOAT(v[0]);
dest[1] = UBYTE_TO_FLOAT(v[1]);
dest[2] = UBYTE_TO_FLOAT(v[2]);
vb.context->Current.Attrib[VERT_ATTRIB_COLOR0][3] = UBYTE_TO_FLOAT(v[3]);
}
static void r200_Color3f_3f( GLfloat r, GLfloat g, GLfloat b )
{
GLfloat *dest = vb.floatcolorptr;
dest[0] = r;
dest[1] = g;
dest[2] = b;
}
static void r200_Color3fv_3f( const GLfloat *v )
{
GLfloat *dest = vb.floatcolorptr;
dest[0] = v[0];
dest[1] = v[1];
dest[2] = v[2];
}
static void r200_Color4f_3f( GLfloat r, GLfloat g, GLfloat b, GLfloat a )
{
GLfloat *dest = vb.floatcolorptr;
dest[0] = r;
dest[1] = g;
dest[2] = b;
vb.context->Current.Attrib[VERT_ATTRIB_COLOR0][3] = a;
}
static void r200_Color4fv_3f( const GLfloat *v )
{
GLfloat *dest = vb.floatcolorptr;
dest[0] = v[0];
dest[1] = v[1];
dest[2] = v[2];
vb.context->Current.Attrib[VERT_ATTRIB_COLOR0][3] = v[3];
}
/* Secondary Color:
*/
static void r200_SecondaryColor3ubEXT_ub( GLubyte r, GLubyte g, GLubyte b )
{
r200_color_t *dest = vb.specptr;
dest->red = r;
dest->green = g;
dest->blue = b;
dest->alpha = 0xff;
}
static void r200_SecondaryColor3ubvEXT_ub( const GLubyte *v )
{
r200_color_t *dest = vb.specptr;
dest->red = v[0];
dest->green = v[1];
dest->blue = v[2];
dest->alpha = 0xff;
}
static void r200_SecondaryColor3fEXT_ub( GLfloat r, GLfloat g, GLfloat b )
{
r200_color_t *dest = vb.specptr;
UNCLAMPED_FLOAT_TO_UBYTE( dest->red, r );
UNCLAMPED_FLOAT_TO_UBYTE( dest->green, g );
UNCLAMPED_FLOAT_TO_UBYTE( dest->blue, b );
dest->alpha = 255;
}
static void r200_SecondaryColor3fvEXT_ub( const GLfloat *v )
{
r200_color_t *dest = vb.specptr;
UNCLAMPED_FLOAT_TO_UBYTE( dest->red, v[0] );
UNCLAMPED_FLOAT_TO_UBYTE( dest->green, v[1] );
UNCLAMPED_FLOAT_TO_UBYTE( dest->blue, v[2] );
dest->alpha = 255;
}
static void r200_SecondaryColor3ubEXT_3f( GLubyte r, GLubyte g, GLubyte b )
{
GLfloat *dest = vb.floatspecptr;
dest[0] = UBYTE_TO_FLOAT(r);
dest[1] = UBYTE_TO_FLOAT(g);
dest[2] = UBYTE_TO_FLOAT(b);
dest[3] = 1.0;
}
static void r200_SecondaryColor3ubvEXT_3f( const GLubyte *v )
{
GLfloat *dest = vb.floatspecptr;
dest[0] = UBYTE_TO_FLOAT(v[0]);
dest[1] = UBYTE_TO_FLOAT(v[1]);
dest[2] = UBYTE_TO_FLOAT(v[2]);
dest[3] = 1.0;
}
static void r200_SecondaryColor3fEXT_3f( GLfloat r, GLfloat g, GLfloat b )
{
GLfloat *dest = vb.floatspecptr;
dest[0] = r;
dest[1] = g;
dest[2] = b;
dest[3] = 1.0;
}
static void r200_SecondaryColor3fvEXT_3f( const GLfloat *v )
{
GLfloat *dest = vb.floatspecptr;
dest[0] = v[0];
dest[1] = v[1];
dest[2] = v[2];
dest[3] = 1.0;
}
/* Normal
*/
static void r200_Normal3f( GLfloat n0, GLfloat n1, GLfloat n2 )
{
GLfloat *dest = vb.normalptr;
dest[0] = n0;
dest[1] = n1;
dest[2] = n2;
}
static void r200_Normal3fv( const GLfloat *v )
{
GLfloat *dest = vb.normalptr;
dest[0] = v[0];
dest[1] = v[1];
dest[2] = v[2];
}
/* TexCoord
*/
static void r200_TexCoord1f( GLfloat s )
{
GLfloat *dest = vb.texcoordptr[0];
dest[0] = s;
dest[1] = 0;
}
static void r200_TexCoord1fv( const GLfloat *v )
{
GLfloat *dest = vb.texcoordptr[0];
dest[0] = v[0];
dest[1] = 0;
}
static void r200_TexCoord2f( GLfloat s, GLfloat t )
{
GLfloat *dest = vb.texcoordptr[0];
dest[0] = s;
dest[1] = t;
}
static void r200_TexCoord2fv( const GLfloat *v )
{
GLfloat *dest = vb.texcoordptr[0];
dest[0] = v[0];
dest[1] = v[1];
}
/* MultiTexcoord
*/
static void r200_MultiTexCoord1fARB( GLenum target, GLfloat s )
{
GLfloat *dest = vb.texcoordptr[(target - GL_TEXTURE0_ARB)&1];
dest[0] = s;
dest[1] = 0;
}
static void r200_MultiTexCoord1fvARB( GLenum target, const GLfloat *v )
{
GLfloat *dest = vb.texcoordptr[(target - GL_TEXTURE0_ARB)&1];
dest[0] = v[0];
dest[1] = 0;
}
static void r200_MultiTexCoord2fARB( GLenum target, GLfloat s, GLfloat t )
{
GLfloat *dest = vb.texcoordptr[(target - GL_TEXTURE0_ARB)&1];
dest[0] = s;
dest[1] = t;
}
static void r200_MultiTexCoord2fvARB( GLenum target, const GLfloat *v )
{
GLfloat *dest = vb.texcoordptr[(target - GL_TEXTURE0_ARB)&1];
dest[0] = v[0];
dest[1] = v[1];
}
static struct dynfn *lookup( struct dynfn *l, const int *key )
{
struct dynfn *f;
foreach( f, l ) {
if (f->key[0] == key[0] && f->key[1] == key[1])
return f;
}
return 0;
}
/* Can't use the loopback template for this:
*/
#define CHOOSE(FN, FNTYPE, MASK0, MASK1, ARGS1, ARGS2 ) \
static void choose_##FN ARGS1 \
{ \
r200ContextPtr rmesa = R200_CONTEXT(vb.context); \
int key[2]; \
struct dynfn *dfn; \
\
key[0] = rmesa->vb.vtxfmt_0 & MASK0; \
key[1] = rmesa->vb.vtxfmt_1 & MASK1; \
\
dfn = lookup( &rmesa->vb.dfn_cache.FN, key ); \
if (dfn == 0) \
dfn = rmesa->vb.codegen.FN( vb.context, key ); \
else if (R200_DEBUG & DEBUG_CODEGEN) \
fprintf(stderr, "%s -- cached codegen\n", __FUNCTION__ ); \
\
if (dfn) \
vb.context->Exec->FN = (FNTYPE)(dfn->code); \
else { \
if (R200_DEBUG & DEBUG_CODEGEN) \
fprintf(stderr, "%s -- generic version\n", __FUNCTION__ ); \
vb.context->Exec->FN = r200_##FN; \
} \
\
vb.context->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; \
vb.context->Exec->FN ARGS2; \
}
/* For the _3f case, only allow one color function to be hooked in at
* a time. Eventually, use a similar mechanism to allow selecting the
* color component of the vertex format based on client behaviour.
*
* Note: Perform these actions even if there is a codegen or cached
* codegen version of the chosen function.
*/
#define CHOOSE_COLOR(FN, FNTYPE, NR, MASK0, MASK1, ARGS1, ARGS2 ) \
static void choose_##FN ARGS1 \
{ \
GLcontext *ctx = vb.context; \
r200ContextPtr rmesa = R200_CONTEXT(vb.context); \
int key[2]; \
struct dynfn *dfn; \
\
key[0] = rmesa->vb.vtxfmt_0 & MASK0; \
key[1] = rmesa->vb.vtxfmt_1 & MASK1; \
\
if (VTX_COLOR(rmesa->vb.vtxfmt_0,0) == R200_VTX_PK_RGBA) { \
ctx->Exec->FN = r200_##FN##_ub; \
} \
else if (VTX_COLOR(rmesa->vb.vtxfmt_0,0) == R200_VTX_FP_RGB) { \
\
if (rmesa->vb.installed_color_3f_sz != NR) { \
rmesa->vb.installed_color_3f_sz = NR; \
if (NR == 3) ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3] = 1.0; \
if (ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) { \
r200_copy_to_current( ctx ); \
_mesa_install_exec_vtxfmt( ctx, &rmesa->vb.vtxfmt ); \
ctx->Exec->FN ARGS2; \
return; \
} \
} \
\
ctx->Exec->FN = r200_##FN##_3f; \
} \
else { \
ctx->Exec->FN = r200_##FN##_4f; \
} \
\
\
dfn = lookup( &rmesa->vb.dfn_cache.FN, key ); \
if (!dfn) dfn = rmesa->vb.codegen.FN( ctx, key ); \
\
if (dfn) { \
if (R200_DEBUG & DEBUG_CODEGEN) \
fprintf(stderr, "%s -- codegen version\n", __FUNCTION__ ); \
ctx->Exec->FN = (FNTYPE)dfn->code; \
} \
else if (R200_DEBUG & DEBUG_CODEGEN) \
fprintf(stderr, "%s -- 'c' version\n", __FUNCTION__ ); \
\
ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; \
ctx->Exec->FN ARGS2; \
}
/* Right now there are both _ub and _3f versions of the secondary color
* functions. Currently, we only set-up the hardware to use the _ub versions.
* The _3f versions are needed for the cases where secondary color isn't used
* in the vertex format, but it still needs to be stored in the context
* state vector.
*/
#define CHOOSE_SECONDARY_COLOR(FN, FNTYPE, MASK0, MASK1, ARGS1, ARGS2 ) \
static void choose_##FN ARGS1 \
{ \
r200ContextPtr rmesa = R200_CONTEXT(vb.context); \
int key[2]; \
struct dynfn *dfn; \
\
key[0] = rmesa->vb.vtxfmt_0 & MASK0; \
key[1] = rmesa->vb.vtxfmt_1 & MASK1; \
\
dfn = lookup( &rmesa->vb.dfn_cache.FN, key ); \
if (dfn == 0) \
dfn = rmesa->vb.codegen.FN( vb.context, key ); \
else if (R200_DEBUG & DEBUG_CODEGEN) \
fprintf(stderr, "%s -- cached version\n", __FUNCTION__ ); \
\
if (dfn) \
vb.context->Exec->FN = (FNTYPE)(dfn->code); \
else { \
if (R200_DEBUG & DEBUG_CODEGEN) \
fprintf(stderr, "%s -- generic version\n", __FUNCTION__ ); \
vb.context->Exec->FN = (VTX_COLOR(rmesa->vb.vtxfmt_0,1) == R200_VTX_PK_RGBA) \
? r200_##FN##_ub : r200_##FN##_3f; \
} \
\
vb.context->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; \
vb.context->Exec->FN ARGS2; \
}
/* VTXFMT_0
*/
#define MASK_XYZW (R200_VTX_W0|R200_VTX_Z0)
#define MASK_NORM (MASK_XYZW|R200_VTX_N0)
#define MASK_COLOR (MASK_NORM |(R200_VTX_COLOR_MASK<<R200_VTX_COLOR_0_SHIFT))
#define MASK_SPEC (MASK_COLOR|(R200_VTX_COLOR_MASK<<R200_VTX_COLOR_1_SHIFT))
/* VTXFMT_1
*/
#define MASK_ST0 (0x7 << R200_VTX_TEX0_COMP_CNT_SHIFT)
typedef void (*p4f)( GLfloat, GLfloat, GLfloat, GLfloat );
typedef void (*p3f)( GLfloat, GLfloat, GLfloat );
typedef void (*p2f)( GLfloat, GLfloat );
typedef void (*p1f)( GLfloat );
typedef void (*pe2f)( GLenum, GLfloat, GLfloat );
typedef void (*pe1f)( GLenum, GLfloat );
typedef void (*p4ub)( GLubyte, GLubyte, GLubyte, GLubyte );
typedef void (*p3ub)( GLubyte, GLubyte, GLubyte );
typedef void (*pfv)( const GLfloat * );
typedef void (*pefv)( GLenum, const GLfloat * );
typedef void (*pubv)( const GLubyte * );
CHOOSE(Normal3f, p3f, MASK_NORM, 0,
(GLfloat a,GLfloat b,GLfloat c), (a,b,c))
CHOOSE(Normal3fv, pfv, MASK_NORM, 0,
(const GLfloat *v), (v))
CHOOSE_COLOR(Color4ub, p4ub, 4, MASK_COLOR, 0,
(GLubyte a,GLubyte b, GLubyte c, GLubyte d), (a,b,c,d))
CHOOSE_COLOR(Color4ubv, pubv, 4, MASK_COLOR, 0,
(const GLubyte *v), (v))
CHOOSE_COLOR(Color3ub, p3ub, 3, MASK_COLOR, 0,
(GLubyte a,GLubyte b, GLubyte c), (a,b,c))
CHOOSE_COLOR(Color3ubv, pubv, 3, MASK_COLOR, 0,
(const GLubyte *v), (v))
CHOOSE_COLOR(Color4f, p4f, 4, MASK_COLOR, 0,
(GLfloat a,GLfloat b, GLfloat c, GLfloat d), (a,b,c,d))
CHOOSE_COLOR(Color4fv, pfv, 4, MASK_COLOR, 0,
(const GLfloat *v), (v))
CHOOSE_COLOR(Color3f, p3f, 3, MASK_COLOR, 0,
(GLfloat a,GLfloat b, GLfloat c), (a,b,c))
CHOOSE_COLOR(Color3fv, pfv, 3, MASK_COLOR, 0,
(const GLfloat *v), (v))
CHOOSE_SECONDARY_COLOR(SecondaryColor3ubEXT, p3ub, MASK_SPEC, 0,
(GLubyte a,GLubyte b, GLubyte c), (a,b,c))
CHOOSE_SECONDARY_COLOR(SecondaryColor3ubvEXT, pubv, MASK_SPEC, 0,
(const GLubyte *v), (v))
CHOOSE_SECONDARY_COLOR(SecondaryColor3fEXT, p3f, MASK_SPEC, 0,
(GLfloat a,GLfloat b, GLfloat c), (a,b,c))
CHOOSE_SECONDARY_COLOR(SecondaryColor3fvEXT, pfv, MASK_SPEC, 0,
(const GLfloat *v), (v))
CHOOSE(TexCoord2f, p2f, ~0, MASK_ST0,
(GLfloat a,GLfloat b), (a,b))
CHOOSE(TexCoord2fv, pfv, ~0, MASK_ST0,
(const GLfloat *v), (v))
CHOOSE(TexCoord1f, p1f, ~0, MASK_ST0,
(GLfloat a), (a))
CHOOSE(TexCoord1fv, pfv, ~0, MASK_ST0,
(const GLfloat *v), (v))
CHOOSE(MultiTexCoord2fARB, pe2f, ~0, ~0,
(GLenum u,GLfloat a,GLfloat b), (u,a,b))
CHOOSE(MultiTexCoord2fvARB, pefv, ~0, ~0,
(GLenum u,const GLfloat *v), (u,v))
CHOOSE(MultiTexCoord1fARB, pe1f, ~0, ~0,
(GLenum u,GLfloat a), (u,a))
CHOOSE(MultiTexCoord1fvARB, pefv, ~0, ~0,
(GLenum u,const GLfloat *v), (u,v))
CHOOSE(Vertex3f, p3f, ~0, ~0,
(GLfloat a,GLfloat b,GLfloat c), (a,b,c))
CHOOSE(Vertex3fv, pfv, ~0, ~0,
(const GLfloat *v), (v))
CHOOSE(Vertex2f, p2f, ~0, ~0,
(GLfloat a,GLfloat b), (a,b))
CHOOSE(Vertex2fv, pfv, ~0, ~0,
(const GLfloat *v), (v))
void r200VtxfmtInitChoosers( GLvertexformat *vfmt )
{
vfmt->Color3f = choose_Color3f;
vfmt->Color3fv = choose_Color3fv;
vfmt->Color3ub = choose_Color3ub;
vfmt->Color3ubv = choose_Color3ubv;
vfmt->Color4f = choose_Color4f;
vfmt->Color4fv = choose_Color4fv;
vfmt->Color4ub = choose_Color4ub;
vfmt->Color4ubv = choose_Color4ubv;
vfmt->SecondaryColor3fEXT = choose_SecondaryColor3fEXT;
vfmt->SecondaryColor3fvEXT = choose_SecondaryColor3fvEXT;
vfmt->SecondaryColor3ubEXT = choose_SecondaryColor3ubEXT;
vfmt->SecondaryColor3ubvEXT = choose_SecondaryColor3ubvEXT;
vfmt->MultiTexCoord1fARB = choose_MultiTexCoord1fARB;
vfmt->MultiTexCoord1fvARB = choose_MultiTexCoord1fvARB;
vfmt->MultiTexCoord2fARB = choose_MultiTexCoord2fARB;
vfmt->MultiTexCoord2fvARB = choose_MultiTexCoord2fvARB;
vfmt->Normal3f = choose_Normal3f;
vfmt->Normal3fv = choose_Normal3fv;
vfmt->TexCoord1f = choose_TexCoord1f;
vfmt->TexCoord1fv = choose_TexCoord1fv;
vfmt->TexCoord2f = choose_TexCoord2f;
vfmt->TexCoord2fv = choose_TexCoord2fv;
vfmt->Vertex2f = choose_Vertex2f;
vfmt->Vertex2fv = choose_Vertex2fv;
vfmt->Vertex3f = choose_Vertex3f;
vfmt->Vertex3fv = choose_Vertex3fv;
}
static struct dynfn *codegen_noop( GLcontext *ctx, const int *key )
{
(void) ctx; (void) key;
return 0;
}
void r200InitCodegen( struct dfn_generators *gen )
{
gen->Vertex3f = codegen_noop;
gen->Vertex3fv = codegen_noop;
gen->Color4ub = codegen_noop;
gen->Color4ubv = codegen_noop;
gen->Normal3f = codegen_noop;
gen->Normal3fv = codegen_noop;
gen->TexCoord2f = codegen_noop;
gen->TexCoord2fv = codegen_noop;
gen->MultiTexCoord2fARB = codegen_noop;
gen->MultiTexCoord2fvARB = codegen_noop;
gen->Vertex2f = codegen_noop;
gen->Vertex2fv = codegen_noop;
gen->Color3ub = codegen_noop;
gen->Color3ubv = codegen_noop;
gen->Color4f = codegen_noop;
gen->Color4fv = codegen_noop;
gen->Color3f = codegen_noop;
gen->Color3fv = codegen_noop;
gen->SecondaryColor3fEXT = codegen_noop;
gen->SecondaryColor3fvEXT = codegen_noop;
gen->SecondaryColor3ubEXT = codegen_noop;
gen->SecondaryColor3ubvEXT = codegen_noop;
gen->TexCoord1f = codegen_noop;
gen->TexCoord1fv = codegen_noop;
gen->MultiTexCoord1fARB = codegen_noop;
gen->MultiTexCoord1fvARB = codegen_noop;
if (!getenv("R200_NO_CODEGEN")) {
#if defined(USE_X86_ASM)
r200InitX86Codegen( gen );
#endif
#if defined(USE_SSE_ASM)
r200InitSSECodegen( gen );
#endif
}
}

View File

@@ -0,0 +1,95 @@
/* $XFree86$ */
/*
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
The Weather Channel (TM) funded Tungsten Graphics to develop the
initial release of the Radeon 8500 driver under the XFree86 license.
This notice must be preserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#include "glheader.h"
#include "imports.h"
#include "simple_list.h"
#include "r200_vtxfmt.h"
#if defined(USE_SSE_ASM)
/* Build specialized versions of the immediate calls on the fly for
* the current state. ???P4 SSE2 versions???
*/
static struct dynfn *makeSSENormal3fv( GLcontext *ctx, const int *key )
{
/* Requires P4 (sse2?)
*/
static unsigned char temp[] = {
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */
0xba, 0x78, 0x56, 0x34, 0x12, /* mov $0x12345678,%edx */
0xf3, 0x0f, 0x7e, 0x00, /* movq (%eax),%xmm0 */
0x66, 0x0f, 0x6e, 0x48, 0x08, /* movd 0x8(%eax),%xmm1 */
0x66, 0x0f, 0xd6, 0x42, 0x0c, /* movq %xmm0,0xc(%edx) */
0x66, 0x0f, 0x7e, 0x4a, 0x14, /* movd %xmm1,0x14(%edx) */
0xc3, /* ret */
};
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
r200ContextPtr rmesa = R200_CONTEXT(ctx);
insert_at_head( &rmesa->vb.dfn_cache.Normal3fv, dfn );
dfn->key[0] = key[0];
dfn->key[1] = key[1];
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
memcpy (dfn->code, temp, sizeof(temp));
FIXUP(dfn->code, 5, 0x0, (int)vb.normalptr);
return dfn;
}
void r200InitSSECodegen( struct dfn_generators *gen )
{
/* Need to:
* - check kernel sse support
* - check p4/sse2
*/
(void) makeSSENormal3fv;
}
#else
void r200InitSSECodegen( struct dfn_generators *gen )
{
(void) gen;
}
#endif

View File

@@ -0,0 +1,462 @@
/* $XFree86$ */
/*
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
The Weather Channel (TM) funded Tungsten Graphics to develop the
initial release of the Radeon 8500 driver under the XFree86 license.
This notice must be preserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#include "glheader.h"
#include "imports.h"
#include "mmath.h"
#include "simple_list.h"
#include "r200_vtxfmt.h"
#if defined(USE_X86_ASM)
#define EXTERN( FUNC ) \
extern const char *FUNC; \
extern const char *FUNC##_end
EXTERN ( _x86_Normal3fv );
EXTERN ( _x86_Normal3f );
EXTERN ( _x86_Vertex3fv_6 );
EXTERN ( _x86_Vertex3fv_8 );
EXTERN ( _x86_Vertex3fv );
EXTERN ( _x86_Vertex3f_4 );
EXTERN ( _x86_Vertex3f_6 );
EXTERN ( _x86_Vertex3f );
EXTERN ( _x86_Color4ubv_ub );
EXTERN ( _x86_Color4ubv_4f );
EXTERN ( _x86_Color4ub_ub );
EXTERN ( _x86_Color3fv_3f );
EXTERN ( _x86_Color3f_3f );
EXTERN ( _x86_TexCoord2fv );
EXTERN ( _x86_TexCoord2f );
EXTERN ( _x86_MultiTexCoord2fvARB );
EXTERN ( _x86_MultiTexCoord2fvARB_2 );
EXTERN ( _x86_MultiTexCoord2fARB );
EXTERN ( _x86_MultiTexCoord2fARB_2 );
/* Build specialized versions of the immediate calls on the fly for
* the current state. Generic x86 versions.
*/
struct dynfn *r200_makeX86Vertex3f( GLcontext *ctx, const int *key )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
if (R200_DEBUG & DEBUG_CODEGEN)
fprintf(stderr, "%s 0x%08x 0x%08x %d\n", __FUNCTION__,
key[0], key[1], vb.vertex_size );
switch (vb.vertex_size) {
case 4: {
DFN ( _x86_Vertex3f_4, rmesa->vb.dfn_cache.Vertex3f );
FIXUP(dfn->code, 2, 0x0, (int)&vb.dmaptr);
FIXUP(dfn->code, 25, 0x0, (int)&vb.vertex[3]);
FIXUP(dfn->code, 36, 0x0, (int)&vb.counter);
FIXUP(dfn->code, 46, 0x0, (int)&vb.dmaptr);
FIXUP(dfn->code, 51, 0x0, (int)&vb.counter);
FIXUP(dfn->code, 60, 0x0, (int)&vb.notify);
break;
}
case 6: {
DFN ( _x86_Vertex3f_6, rmesa->vb.dfn_cache.Vertex3f );
FIXUP(dfn->code, 3, 0x0, (int)&vb.dmaptr);
FIXUP(dfn->code, 28, 0x0, (int)&vb.vertex[3]);
FIXUP(dfn->code, 34, 0x0, (int)&vb.vertex[4]);
FIXUP(dfn->code, 40, 0x0, (int)&vb.vertex[5]);
FIXUP(dfn->code, 57, 0x0, (int)&vb.counter);
FIXUP(dfn->code, 63, 0x0, (int)&vb.dmaptr);
FIXUP(dfn->code, 70, 0x0, (int)&vb.counter);
FIXUP(dfn->code, 79, 0x0, (int)&vb.notify);
break;
}
default: {
DFN ( _x86_Vertex3f, rmesa->vb.dfn_cache.Vertex3f );
FIXUP(dfn->code, 3, 0x0, (int)&vb.vertex[3]);
FIXUP(dfn->code, 9, 0x0, (int)&vb.dmaptr);
FIXUP(dfn->code, 37, 0x0, vb.vertex_size-3);
FIXUP(dfn->code, 44, 0x0, (int)&vb.counter);
FIXUP(dfn->code, 50, 0x0, (int)&vb.dmaptr);
FIXUP(dfn->code, 56, 0x0, (int)&vb.counter);
FIXUP(dfn->code, 67, 0x0, (int)&vb.notify);
break;
}
}
return dfn;
}
struct dynfn *r200_makeX86Vertex3fv( GLcontext *ctx, const int *key )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
if (R200_DEBUG & DEBUG_CODEGEN)
fprintf(stderr, "%s 0x%08x 0x%08x %d\n", __FUNCTION__,
key[0], key[1], vb.vertex_size );
switch (vb.vertex_size) {
case 6: {
DFN ( _x86_Vertex3fv_6, rmesa->vb.dfn_cache.Vertex3fv );
FIXUP(dfn->code, 1, 0x00000000, (int)&vb.dmaptr);
FIXUP(dfn->code, 27, 0x0000001c, (int)&vb.vertex[3]);
FIXUP(dfn->code, 33, 0x00000020, (int)&vb.vertex[4]);
FIXUP(dfn->code, 45, 0x00000024, (int)&vb.vertex[5]);
FIXUP(dfn->code, 56, 0x00000000, (int)&vb.dmaptr);
FIXUP(dfn->code, 61, 0x00000004, (int)&vb.counter);
FIXUP(dfn->code, 67, 0x00000004, (int)&vb.counter);
FIXUP(dfn->code, 76, 0x00000008, (int)&vb.notify);
break;
}
case 8: {
DFN ( _x86_Vertex3fv_8, rmesa->vb.dfn_cache.Vertex3fv );
FIXUP(dfn->code, 1, 0x00000000, (int)&vb.dmaptr);
FIXUP(dfn->code, 27, 0x0000001c, (int)&vb.vertex[3]);
FIXUP(dfn->code, 33, 0x00000020, (int)&vb.vertex[4]);
FIXUP(dfn->code, 45, 0x0000001c, (int)&vb.vertex[5]);
FIXUP(dfn->code, 51, 0x00000020, (int)&vb.vertex[6]);
FIXUP(dfn->code, 63, 0x00000024, (int)&vb.vertex[7]);
FIXUP(dfn->code, 74, 0x00000000, (int)&vb.dmaptr);
FIXUP(dfn->code, 79, 0x00000004, (int)&vb.counter);
FIXUP(dfn->code, 85, 0x00000004, (int)&vb.counter);
FIXUP(dfn->code, 94, 0x00000008, (int)&vb.notify);
break;
}
default: {
DFN ( _x86_Vertex3fv, rmesa->vb.dfn_cache.Vertex3fv );
FIXUP(dfn->code, 8, 0x01010101, (int)&vb.dmaptr);
FIXUP(dfn->code, 32, 0x00000006, vb.vertex_size-3);
FIXUP(dfn->code, 37, 0x00000058, (int)&vb.vertex[3]);
FIXUP(dfn->code, 45, 0x01010101, (int)&vb.dmaptr);
FIXUP(dfn->code, 50, 0x02020202, (int)&vb.counter);
FIXUP(dfn->code, 58, 0x02020202, (int)&vb.counter);
FIXUP(dfn->code, 67, 0x0, (int)&vb.notify);
break;
}
}
return dfn;
}
struct dynfn *r200_makeX86Normal3fv( GLcontext *ctx, const int *key )
{
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
r200ContextPtr rmesa = R200_CONTEXT(ctx);
int i = 0;
if (R200_DEBUG & DEBUG_CODEGEN)
fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key[0] );
DFN ( _x86_Normal3fv, rmesa->vb.dfn_cache.Normal3fv );
FIXUP2(dfn->code, i, 0x0, (int)vb.normalptr);
FIXUP2(dfn->code, i, 0x4, 4+(int)vb.normalptr);
FIXUP2(dfn->code, i, 0x8, 8+(int)vb.normalptr);
/*fprintf(stderr, "%s done\n", __FUNCTION__);*/
return dfn;
}
struct dynfn *r200_makeX86Normal3f( GLcontext *ctx, const int *key )
{
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
r200ContextPtr rmesa = R200_CONTEXT(ctx);
if (R200_DEBUG & DEBUG_CODEGEN)
fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key[0] );
DFN ( _x86_Normal3f, rmesa->vb.dfn_cache.Normal3f );
FIXUP(dfn->code, 1, 0x12345678, (int)vb.normalptr);
return dfn;
}
struct dynfn *r200_makeX86Color4ubv( GLcontext *ctx, const int *key )
{
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
r200ContextPtr rmesa = R200_CONTEXT(ctx);
if (R200_DEBUG & DEBUG_CODEGEN)
fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key[0] );
if (VTX_COLOR(key[0],0) == R200_VTX_PK_RGBA) {
DFN ( _x86_Color4ubv_ub, rmesa->vb.dfn_cache.Color4ubv);
FIXUP(dfn->code, 5, 0x12345678, (int)vb.colorptr);
return dfn;
}
else {
DFN ( _x86_Color4ubv_4f, rmesa->vb.dfn_cache.Color4ubv);
FIXUP(dfn->code, 2, 0x00000000, (int)_mesa_ubyte_to_float_color_tab);
FIXUP(dfn->code, 27, 0xdeadbeaf, (int)vb.floatcolorptr);
FIXUP(dfn->code, 33, 0xdeadbeaf, (int)vb.floatcolorptr+4);
FIXUP(dfn->code, 55, 0xdeadbeaf, (int)vb.floatcolorptr+8);
FIXUP(dfn->code, 61, 0xdeadbeaf, (int)vb.floatcolorptr+12);
return dfn;
}
}
struct dynfn *r200_makeX86Color4ub( GLcontext *ctx, const int *key )
{
if (R200_DEBUG & DEBUG_CODEGEN)
fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key[0] );
if (VTX_COLOR(key[0],0) == R200_VTX_PK_RGBA) {
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
r200ContextPtr rmesa = R200_CONTEXT(ctx);
DFN ( _x86_Color4ub_ub, rmesa->vb.dfn_cache.Color4ub );
FIXUP(dfn->code, 18, 0x0, (int)vb.colorptr);
FIXUP(dfn->code, 24, 0x0, (int)vb.colorptr+1);
FIXUP(dfn->code, 30, 0x0, (int)vb.colorptr+2);
FIXUP(dfn->code, 36, 0x0, (int)vb.colorptr+3);
return dfn;
}
else
return 0;
}
struct dynfn *r200_makeX86Color3fv( GLcontext *ctx, const int *key )
{
if (VTX_COLOR(key[0],0) != R200_VTX_FP_RGB)
return 0;
else
{
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
r200ContextPtr rmesa = R200_CONTEXT(ctx);
if (R200_DEBUG & DEBUG_CODEGEN)
fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key[0] );
DFN ( _x86_Color3fv_3f, rmesa->vb.dfn_cache.Color3fv );
FIXUP(dfn->code, 5, 0x0, (int)vb.floatcolorptr);
return dfn;
}
}
struct dynfn *r200_makeX86Color3f( GLcontext *ctx, const int *key )
{
if (VTX_COLOR(key[0],0) != R200_VTX_FP_RGB)
return 0;
else
{
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
r200ContextPtr rmesa = R200_CONTEXT(ctx);
if (R200_DEBUG & DEBUG_CODEGEN)
fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key[0] );
DFN ( _x86_Color3f_3f, rmesa->vb.dfn_cache.Color3f );
FIXUP(dfn->code, 1, 0x12345678, (int)vb.floatcolorptr);
return dfn;
}
}
struct dynfn *r200_makeX86TexCoord2fv( GLcontext *ctx, const int *key )
{
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
r200ContextPtr rmesa = R200_CONTEXT(ctx);
if (R200_DEBUG & DEBUG_CODEGEN)
fprintf(stderr, "%s 0x%08x 0x%08x\n", __FUNCTION__, key[0], key[1] );
DFN ( _x86_TexCoord2fv, rmesa->vb.dfn_cache.TexCoord2fv );
FIXUP(dfn->code, 5, 0x12345678, (int)vb.texcoordptr[0]);
return dfn;
}
struct dynfn *r200_makeX86TexCoord2f( GLcontext *ctx, const int *key )
{
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
r200ContextPtr rmesa = R200_CONTEXT(ctx);
if (R200_DEBUG & DEBUG_CODEGEN)
fprintf(stderr, "%s 0x%08x 0x%08x\n", __FUNCTION__, key[0], key[1] );
DFN ( _x86_TexCoord2f, rmesa->vb.dfn_cache.TexCoord2f );
FIXUP(dfn->code, 1, 0x12345678, (int)vb.texcoordptr[0]);
return dfn;
}
struct dynfn *r200_makeX86MultiTexCoord2fvARB( GLcontext *ctx, const int *key )
{
#if 0
static char temp[] = {
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */
0x8b, 0x4c, 0x24, 0x08, /* mov 0x8(%esp,1),%ecx */
0x2d, 0xc0, 0x84, 0x00, 0x00, /* sub $0x84c0,%eax */
0x83, 0xe0, 0x01, /* and $0x1,%eax */
0x8b, 0x11, /* mov (%ecx),%edx */
0xc1, 0xe0, 0x03, /* shl $0x3,%eax */
0x8b, 0x49, 0x04, /* mov 0x4(%ecx),%ecx */
0x89, 0x90, 0, 0, 0, 0,/* mov %edx,DEST(%eax) */
0x89, 0x88, 0, 0, 0, 0,/* mov %ecx,DEST+8(%eax) */
0xc3, /* ret */
};
static char temp2[] = {
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */
0x8b, 0x4c, 0x24, 0x08, /* mov 0x8(%esp,1),%ecx */
0x2d, 0xc0, 0x84, 0x00, 0x00, /* sub $0x84c0,%eax */
0x83, 0xe0, 0x01, /* and $0x1,%eax */
0x8b, 0x14, 0x85, 0, 0, 0, 0, /* mov DEST(,%eax,4),%edx */
0x8b, 0x01, /* mov (%ecx),%eax */
0x89, 0x02, /* mov %eax,(%edx) */
0x8b, 0x41, 0x04, /* mov 0x4(%ecx),%eax */
0x89, 0x42, 0x04, /* mov %eax,0x4(%edx) */
0xc3, /* ret */
};
#endif
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
r200ContextPtr rmesa = R200_CONTEXT(ctx);
if (R200_DEBUG & DEBUG_CODEGEN)
fprintf(stderr, "%s 0x%08x 0x%08x\n", __FUNCTION__, key[0], key[1] );
if (vb.texcoordptr[1] == vb.texcoordptr[0]+4) {
DFN ( _x86_MultiTexCoord2fvARB, rmesa->vb.dfn_cache.MultiTexCoord2fvARB );
FIXUP(dfn->code, 26, 0xdeadbeef, (int)vb.texcoordptr[0]);
FIXUP(dfn->code, 32, 0xdeadbeef, (int)vb.texcoordptr[0]+4);
} else {
DFN ( _x86_MultiTexCoord2fvARB_2, rmesa->vb.dfn_cache.MultiTexCoord2fvARB );
FIXUP(dfn->code, 19, 0x0, (int)vb.texcoordptr);
}
return dfn;
}
struct dynfn *r200_makeX86MultiTexCoord2fARB( GLcontext *ctx,
const int *key )
{
#if 0
static char temp[] = {
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */
0x8b, 0x54, 0x24, 0x08, /* mov 0x8(%esp,1),%edx */
0x2d, 0xc0, 0x84, 0x00, 0x00, /* sub $0x84c0,%eax */
0x8b, 0x4c, 0x24, 0x0c, /* mov 0xc(%esp,1),%ecx */
0x83, 0xe0, 0x01, /* and $0x1,%eax */
0xc1, 0xe0, 0x03, /* shl $0x3,%eax */
0x89, 0x90, 0, 0, 0, 0, /* mov %edx,DEST(%eax) */
0x89, 0x88, 0, 0, 0, 0, /* mov %ecx,DEST+8(%eax) */
0xc3, /* ret */
};
static char temp2[] = {
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */
0x8b, 0x54, 0x24, 0x08, /* mov 0x8(%esp,1),%edx */
0x2d, 0xc0, 0x84, 0x00, 0x00, /* sub $0x84c0,%eax */
0x8b, 0x4c, 0x24, 0x0c, /* mov 0xc(%esp,1),%ecx */
0x83, 0xe0, 0x01, /* and $0x1,%eax */
0x8b, 0x04, 0x85, 0, 0, 0, 0, /* mov DEST(,%eax,4),%eax */
0x89, 0x10, /* mov %edx,(%eax) */
0x89, 0x48, 0x04, /* mov %ecx,0x4(%eax) */
0xc3, /* ret */
};
#endif
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
r200ContextPtr rmesa = R200_CONTEXT(ctx);
if (R200_DEBUG & DEBUG_CODEGEN)
fprintf(stderr, "%s 0x%08x 0x%08x\n", __FUNCTION__, key[0], key[1] );
if (vb.texcoordptr[1] == vb.texcoordptr[0]+4) {
DFN ( _x86_MultiTexCoord2fARB, rmesa->vb.dfn_cache.MultiTexCoord2fARB );
FIXUP(dfn->code, 25, 0xdeadbeef, (int)vb.texcoordptr[0]);
FIXUP(dfn->code, 31, 0xdeadbeef, (int)vb.texcoordptr[0]+4);
}
else {
/* Note: this might get generated multiple times, even though the
* actual emitted code is the same.
*/
DFN ( _x86_MultiTexCoord2fARB_2, rmesa->vb.dfn_cache.MultiTexCoord2fARB );
FIXUP(dfn->code, 23, 0x0, (int)vb.texcoordptr);
}
return dfn;
}
void r200InitX86Codegen( struct dfn_generators *gen )
{
gen->Vertex3f = r200_makeX86Vertex3f;
gen->Vertex3fv = r200_makeX86Vertex3fv;
gen->Color4ub = r200_makeX86Color4ub; /* PKCOLOR only */
gen->Color4ubv = r200_makeX86Color4ubv; /* PKCOLOR only */
gen->Normal3f = r200_makeX86Normal3f;
gen->Normal3fv = r200_makeX86Normal3fv;
gen->TexCoord2f = r200_makeX86TexCoord2f;
gen->TexCoord2fv = r200_makeX86TexCoord2fv;
gen->MultiTexCoord2fARB = r200_makeX86MultiTexCoord2fARB;
gen->MultiTexCoord2fvARB = r200_makeX86MultiTexCoord2fvARB;
gen->Color3f = r200_makeX86Color3f;
gen->Color3fv = r200_makeX86Color3fv;
/* Not done:
*/
/* gen->Vertex2f = r200_makeX86Vertex2f; */
/* gen->Vertex2fv = r200_makeX86Vertex2fv; */
/* gen->Color3ub = r200_makeX86Color3ub; */
/* gen->Color3ubv = r200_makeX86Color3ubv; */
/* gen->Color4f = r200_makeX86Color4f; */
/* gen->Color4fv = r200_makeX86Color4fv; */
/* gen->TexCoord1f = r200_makeX86TexCoord1f; */
/* gen->TexCoord1fv = r200_makeX86TexCoord1fv; */
/* gen->MultiTexCoord1fARB = r200_makeX86MultiTexCoord1fARB; */
/* gen->MultiTexCoord1fvARB = r200_makeX86MultiTexCoord1fvARB; */
}
#else
void r200InitX86Codegen( struct dfn_generators *gen )
{
(void) gen;
}
#endif

View File

@@ -0,0 +1,410 @@
/* $XFree86: xc/lib/GL/mesa/src/drv/r200/r200_vtxtmp_x86.S,v 1.1 2002/10/30 12:51:53 alanh Exp $ */
/**************************************************************************
Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
#define GLOBL( x ) \
.globl x; \
x:
.data
.align 4
GLOBL( _x86_Normal3fv)
movl 4(%esp), %eax /* load 'v' off stack */
movl (%eax), %ecx /* load v[0] */
movl 4(%eax), %edx /* load v[1] */
movl 8(%eax), %eax /* load v[2] */
movl %ecx, 0 /* store v[0] to current vertex */
movl %edx, 4 /* store v[1] to current vertex */
movl %eax, 8 /* store v[2] to current vertex */
ret
GLOBL ( _x86_Normal3fv_end )
/*
vertex 3f vertex size 4
*/
GLOBL ( _x86_Vertex3f_4 )
movl (0), %ecx
movl 4(%esp), %eax
movl 8(%esp), %edx
movl %eax, (%ecx)
movl %edx, 4(%ecx)
movl 12(%esp), %eax
movl (0), %edx
movl %eax, 8(%ecx)
movl %edx, 12(%ecx)
movl (0), %eax
addl $16, %ecx
dec %eax
movl %ecx, (0)
movl %eax, (0)
je .1
ret
.1: jmp *0
GLOBL ( _x86_Vertex3f_4_end )
/*
vertex 3f vertex size 6
*/
GLOBL ( _x86_Vertex3f_6 )
push %edi
movl (0), %edi
movl 8(%esp), %eax
movl 12(%esp), %edx
movl 16(%esp), %ecx
movl %eax, (%edi)
movl %edx, 4(%edi)
movl %ecx, 8(%edi)
movl (0), %eax
movl (0), %edx
movl (0), %ecx
movl %eax, 12(%edi)
movl %edx, 16(%edi)
movl %ecx, 20(%edi)
addl $24, %edi
movl (0), %eax
movl %edi, (0)
dec %eax
pop %edi
movl %eax, (0)
je .2
ret
.2: jmp *0
GLOBL ( _x86_Vertex3f_6_end )
/*
vertex 3f generic size
*/
GLOBL ( _x86_Vertex3f )
push %edi
push %esi
movl $0, %esi
movl (0), %edi
movl 12(%esp), %eax
movl 16(%esp), %edx
movl 20(%esp), %ecx
movl %eax, (%edi)
movl %edx, 4(%edi)
movl %ecx, 8(%edi)
addl $12, %edi
movl $0, %ecx
repz
movsl %ds:(%esi), %es:(%edi)
movl (0), %eax
movl %edi, (0)
dec %eax
movl %eax, (0)
pop %esi
pop %edi
je .3
ret
.3: jmp *0
GLOBL ( _x86_Vertex3f_end )
/*
Vertex 3fv vertex size 6
*/
GLOBL ( _x86_Vertex3fv_6 )
movl (0), %eax
movl 4(%esp), %ecx
movl (%ecx), %edx
movl %edx, (%eax)
movl 4(%ecx), %edx
movl 8(%ecx), %ecx
movl %edx, 4(%eax)
movl %ecx, 8(%eax)
movl (28), %edx
movl (32), %ecx
movl %edx, 12(%eax)
movl %ecx, 16(%eax)
movl (36), %edx
movl %edx, 20(%eax)
addl $24, %eax
movl %eax, 0
movl 4, %eax
dec %eax
movl %eax, 4
je .4
ret
.4: jmp *8
GLOBL ( _x86_Vertex3fv_6_end )
/*
Vertex 3fv vertex size 8
*/
GLOBL ( _x86_Vertex3fv_8 )
movl (0), %eax
movl 4(%esp), %ecx
movl (%ecx), %edx
movl %edx ,(%eax)
movl 4(%ecx) ,%edx
movl 8(%ecx) ,%ecx
movl %edx, 4(%eax)
movl %ecx, 8(%eax)
movl (28), %edx
movl (32), %ecx
movl %edx, 12(%eax)
movl %ecx, 16(%eax)
movl (28), %edx
movl (32), %ecx
movl %edx, 20(%eax)
movl %ecx, 24(%eax)
movl (36), %edx
movl %edx, 28(%eax)
addl $32, %eax
movl %eax, (0)
movl 4, %eax
dec %eax
movl %eax, (4)
je .5
ret
.5: jmp *8
GLOBL ( _x86_Vertex3fv_8_end )
/*
Vertex 3fv generic vertex size
*/
GLOBL ( _x86_Vertex3fv )
movl 4(%esp), %edx
push %edi
push %esi
movl (0x1010101), %edi
movl (%edx), %eax
movl 4(%edx), %ecx
movl 8(%edx), %esi
movl %eax, (%edi)
movl %ecx, 4(%edi)
movl %esi, 8(%edi)
addl $12, %edi
movl $6, %ecx
movl $0x58, %esi
repz
movsl %ds:(%esi), %es:(%edi)
movl %edi, (0x1010101)
movl (0x2020202), %eax
pop %esi
pop %edi
dec %eax
movl %eax, (0x2020202)
je .6
ret
.6: jmp *0
GLOBL ( _x86_Vertex3fv_end )
/*
Normal 3f
*/
GLOBL ( _x86_Normal3f )
movl $0x12345678, %edx
movl 4(%esp), %eax
movl %eax, (%edx)
movl 8(%esp), %eax
movl %eax, 4(%edx)
movl 12(%esp), %eax
movl %eax, 8(%edx)
ret
GLOBL ( _x86_Normal3f_end )
/*
Color 4ubv_ub
*/
GLOBL ( _x86_Color4ubv_ub )
movl 4(%esp), %eax
movl $0x12345678, %edx
movl (%eax), %eax
movl %eax, (%edx)
ret
GLOBL ( _x86_Color4ubv_ub_end )
/*
Color 4ubv 4f
*/
GLOBL ( _x86_Color4ubv_4f )
push %ebx
movl $0, %edx
xor %eax, %eax
xor %ecx, %ecx
movl 8(%esp), %ebx
movl (%ebx), %ebx
mov %bl, %al
mov %bh, %cl
movl (%edx,%eax,4),%eax
movl (%edx,%ecx,4),%ecx
movl %eax, (0xdeadbeaf)
movl %ecx, (0xdeadbeaf)
xor %eax, %eax
xor %ecx, %ecx
shr $16, %ebx
mov %bl, %al
mov %bh, %cl
movl (%edx,%eax,4), %eax
movl (%edx,%ecx,4), %ecx
movl %eax, (0xdeadbeaf)
movl %ecx, (0xdeadbeaf)
pop %ebx
ret
GLOBL ( _x86_Color4ubv_4f_end )
/*
Color4ub_ub
*/
GLOBL( _x86_Color4ub_ub )
push %ebx
movl 8(%esp), %eax
movl 12(%esp), %edx
movl 16(%esp), %ecx
movl 20(%esp), %ebx
mov %al, (0)
mov %dl, (0)
mov %cl, (0)
mov %bl, (0)
pop %ebx
ret
GLOBL( _x86_Color4ub_ub_end )
/*
Color3fv_3f
*/
GLOBL( _x86_Color3fv_3f )
movl 4(%esp), %eax
movl $0, %edx
movl (%eax), %ecx
movl %ecx, (%edx)
movl 4(%eax), %ecx
movl %ecx, 4(%edx)
movl 8(%eax), %ecx
movl %ecx, 8(%edx)
ret
GLOBL( _x86_Color3fv_3f_end )
/*
Color3f_3f
*/
GLOBL( _x86_Color3f_3f )
movl $0x12345678, %edx
movl 4(%esp), %eax
movl %eax, (%edx)
movl 8(%esp,1), %eax
movl %eax, 4(%edx)
movl 12(%esp), %eax
movl %eax, 8(%edx)
ret
GLOBL( _x86_Color3f_3f_end )
/*
TexCoord2fv
*/
GLOBL( _x86_TexCoord2fv )
movl 4(%esp), %eax
movl $0x12345678, %edx
movl (%eax), %ecx
movl 4(%eax), %eax
movl %ecx, (%edx)
movl %eax, 4(%edx)
ret
GLOBL( _x86_TexCoord2fv_end )
/*
TexCoord2f
*/
GLOBL( _x86_TexCoord2f )
movl $0x12345678, %edx
movl 4(%esp), %eax
movl 8(%esp), %ecx
movl %eax, (%edx)
movl %ecx, 4(%edx)
ret
GLOBL( _x86_TexCoord2f_end )
/*
MultiTexCoord2fvARB st0/st1
*/
GLOBL( _x86_MultiTexCoord2fvARB )
movl 4(%esp), %eax
movl 8(%esp), %ecx
sub $0x84c0, %eax
and $1, %eax
movl (%ecx), %edx
shl $3, %eax
movl 4(%ecx), %ecx
movl %edx, 0xdeadbeef(%eax)
movl %ecx, 0xdeadbeef(%eax)
ret
GLOBL( _x86_MultiTexCoord2fvARB_end )
/*
MultiTexCoord2fvARB
*/
GLOBL( _x86_MultiTexCoord2fvARB_2 )
movl 4(%esp,1), %eax
movl 8(%esp,1), %ecx
sub $0x84c0, %eax
and $0x1, %eax
movl 0(,%eax,4), %edx
movl (%ecx), %eax
movl %eax, (%edx)
movl 4(%ecx), %eax
movl %eax, 4(%edx)
ret
GLOBL( _x86_MultiTexCoord2fvARB_2_end )
/*
MultiTexCoord2fARB st0/st1
*/
GLOBL( _x86_MultiTexCoord2fARB )
movl 4(%esp), %eax
movl 8(%esp), %edx
sub $0x84c0, %eax
movl 12(%esp), %ecx
and $1, %eax
shl $3, %eax
movl %edx, 0xdeadbeef(%eax)
movl %ecx, 0xdeadbeef(%eax)
ret
GLOBL( _x86_MultiTexCoord2fARB_end )
/*
MultiTexCoord2fARB
*/
GLOBL( _x86_MultiTexCoord2fARB_2 )
movl 4(%esp), %eax
movl 8(%esp), %edx
sub $0x84c0, %eax
movl 12(%esp,1), %ecx
and $1,%eax
movl 0(,%eax,4), %eax
movl %edx, (%eax)
movl %ecx, 4(%eax)
ret
GLOBL( _x86_MultiTexCoord2fARB_2_end )

View File

@@ -1,4 +1,4 @@
# $Id: Makefile,v 1.1.2.26 2003/03/04 17:29:56 keithw Exp $
# $Id: Makefile,v 1.1.2.29 2003/03/20 09:21:23 keithw Exp $
# Mesa 3-D graphics library
# Version: 5.0
@@ -102,7 +102,7 @@ else
C_SOURCES = $(DRIVER_SOURCES) \
$(SUBSET_DRIVER_SOURCES) \
$(MINIGLX_SOURCES)
MESA_MODULES = $(FULL_MESA)
MESA_MODULES = $(SUBSET_MESA)
endif

View File

@@ -205,8 +205,8 @@ static void radeonInitDriverFuncs( GLcontext *ctx )
ctx->Driver.Error = NULL;
ctx->Driver.DrawPixels = NULL;
#if !_HAVE_SWRAST
ctx->Driver.Bitmap = radeonPointsBitmap;
ctx->Driver.ReadPixels = radeonReadPixels;
ctx->Exec->Bitmap = radeonPointsBitmap;
ctx->Exec->ReadPixels = radeonReadPixels;
#endif
}
@@ -275,6 +275,8 @@ radeonCreateContext( const __GLcontextModes *glVisual,
rmesa->dri.hwLock = &sPriv->pSAREA->lock;
rmesa->dri.fd = sPriv->fd;
rmesa->glCtx->_RotateMode = radeonScreen->driScreen->display->rotateMode;
/* If we don't have 1.3, fallback to the 1.1 interfaces.
*/
if (getenv("RADEON_COMPAT") || sPriv->drmMinor < 3 )

View File

@@ -879,7 +879,10 @@ void radeonPageFlip( const __DRIdrawablePrivate *dPriv )
b[0] = box[0];
rmesa->sarea->nbox = 1;
}
else {
UNLOCK_HARDWARE( rmesa );
return;
}
/* Throttle the frame rate -- only allow one pending swap buffers
* request at a time.

View File

@@ -109,6 +109,7 @@ radeonUpdatePageFlipping( radeonContextPtr rmesa )
return;
rmesa->doPageFlip = rmesa->sarea->pfAllowPageFlip;
rmesa->doPageFlip = 0;
use_back = (rmesa->glCtx->Color._DrawDestMask == BACK_LEFT_BIT);
use_back ^= (rmesa->sarea->pfCurrentPage == 1);
@@ -127,23 +128,11 @@ radeonUpdatePageFlipping( radeonContextPtr rmesa )
}
/* Update the hardware state. This is called if another context has
* grabbed the hardware lock, which includes the X server. This
* function also updates the driver's window state after the X server
* moves, resizes or restacks a window -- the change will be reflected
* in the drawable position and clip rects. Since the X server grabs
* the hardware lock when it changes the window state, this routine will
* automatically be called after such a change.
*/
void radeonGetLock( radeonContextPtr rmesa, GLuint flags )
static void validate_drawable( radeonContextPtr rmesa )
{
__DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
__DRIscreenPrivate *sPriv = rmesa->dri.screen;
RADEONSAREAPrivPtr sarea = rmesa->sarea;
int i;
drmGetLock( rmesa->dri.fd, rmesa->dri.hwContext, flags );
fprintf(stderr, "%s\n", __FUNCTION__);
/* The window might have moved, so we might need to get new clip
* rects.
@@ -165,14 +154,69 @@ void radeonGetLock( radeonContextPtr rmesa, GLuint flags )
radeonUpdateViewportOffset( rmesa->glCtx );
rmesa->lastStamp = dPriv->lastStamp;
}
}
/* Update the hardware state. This is called if another context has
* grabbed the hardware lock, which includes the X server. This
* function also updates the driver's window state after the X server
* moves, resizes or restacks a window -- the change will be reflected
* in the drawable position and clip rects. Since the X server grabs
* the hardware lock when it changes the window state, this routine will
* automatically be called after such a change.
*/
void radeonGetLock( radeonContextPtr rmesa, GLuint flags )
{
RADEONSAREAPrivPtr sarea = rmesa->sarea;
int i;
while (1) {
drmGetLock( rmesa->dri.fd, rmesa->dri.hwContext, flags );
validate_drawable( rmesa );
fprintf(stderr, "%s %d\n", __FUNCTION__, rmesa->numClipRects);
if (rmesa->numClipRects)
break;
drmUnlock( rmesa->dri.fd, rmesa->dri.hwContext );
sleep(10);
}
if ( sarea->ctxOwner != rmesa->dri.hwContext ) {
sarea->ctxOwner = rmesa->dri.hwContext;
for ( i = 0 ; i < rmesa->texture.numHeaps ; i++ ) {
if ( rmesa->texture.heap[i] && sarea->texAge[i] != rmesa->texture.age[i] ) {
if ( rmesa->texture.heap[i] &&
sarea->texAge[i] != rmesa->texture.age[i] ) {
radeonAgeTextures( rmesa, i );
}
}
}
}
extern void __miniglx_release_vt( void );
/* In the current miniglx, cliprects can change while the lock is
* held... Probably need to fix this.
*/
void radeonUnlock( radeonContextPtr rmesa )
{
fprintf(stderr, "%s\n", __FUNCTION__);
drmUnlock( rmesa->dri.fd, rmesa->dri.hwContext );
validate_drawable( rmesa );
/* This only happens if the VT switch was requested inside the
* locked region.
*/
if (!rmesa->numClipRects)
__miniglx_release_vt();
}

View File

@@ -38,6 +38,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#define __RADEON_LOCK_H__
extern void radeonGetLock( radeonContextPtr rmesa, GLuint flags );
extern void radeonUnlock( radeonContextPtr rmesa );
/* Turn DEBUG_LOCKING on to find locking conflicts.
*/
@@ -99,12 +100,13 @@ extern int prevLockLine;
/* Unlock the hardware.
*/
#define UNLOCK_HARDWARE( rmesa ) \
do { \
DRM_UNLOCK( rmesa->dri.fd, \
rmesa->dri.hwLock, \
rmesa->dri.hwContext ); \
DEBUG_RESET(); \
#define UNLOCK_HARDWARE( rmesa ) \
do { \
DRM_CAS_RESULT(__ret); \
DRM_CAS( rmesa->dri.hwLock,DRM_LOCK_HELD|rmesa->dri.hwContext, \
rmesa->dri.hwContext,__ret); \
if (__ret) radeonUnlock( rmesa ); \
DEBUG_RESET(); \
} while (0)
#endif /* __RADEON_LOCK_H__ */

View File

@@ -38,6 +38,7 @@
#include "api_arrayelt.h"
#include "mmath.h"
#include "enums.h"
#include "context.h"
#include "colormac.h"
#if _HAVE_SWTNL
@@ -475,16 +476,25 @@ void radeonUpdateScissor( GLcontext *ctx )
if ( rmesa->dri.drawable ) {
__DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
int x1,x2,y1,y2;
int x = ctx->Scissor.X;
int y = dPriv->h - ctx->Scissor.Y - ctx->Scissor.Height;
int w = ctx->Scissor.X + ctx->Scissor.Width - 1;
int h = dPriv->h - ctx->Scissor.Y - 1;
if (ctx->_RotateMode) {
x1 = dPriv->w - ctx->Scissor.Y - ctx->Scissor.Height;
x2 = dPriv->w - ctx->Scissor.Y;
y1 = dPriv->h - ctx->Scissor.X - ctx->Scissor.Width;
y2 = dPriv->h - ctx->Scissor.X;
}
else {
x1 = ctx->Scissor.X;
x2 = ctx->Scissor.X + ctx->Scissor.Width;
y1 = dPriv->h - ctx->Scissor.Y - ctx->Scissor.Height;
y2 = dPriv->h - ctx->Scissor.Y;
}
rmesa->state.scissor.rect.x1 = x + dPriv->x;
rmesa->state.scissor.rect.y1 = y + dPriv->y;
rmesa->state.scissor.rect.x2 = w + dPriv->x + 1;
rmesa->state.scissor.rect.y2 = h + dPriv->y + 1;
rmesa->state.scissor.rect.x1 = x1 + dPriv->x;
rmesa->state.scissor.rect.x2 = x2 + dPriv->x;
rmesa->state.scissor.rect.y1 = y1 + dPriv->y;
rmesa->state.scissor.rect.y2 = y2 + dPriv->y;
radeonRecalcScissorRects( rmesa );
}
@@ -986,32 +996,54 @@ void radeonUpdateWindow( GLcontext *ctx )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
__DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
GLfloat xoffset = (GLfloat)dPriv->x;
GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
const GLfloat *v = ctx->Viewport._WindowMap.m;
const GLfloat n = ctx->Viewport.Near;
const GLfloat f = ctx->Viewport.Far;
const GLfloat x = (GLfloat) ctx->Viewport.X;
const GLfloat y = (GLfloat) ctx->Viewport.Y;
const GLfloat width = (GLfloat) ctx->Viewport.Width;
const GLfloat height = (GLfloat) ctx->Viewport.Height;
GLfloat wx = (GLfloat)dPriv->x;
GLfloat ww = (GLfloat)dPriv->w;
GLfloat wy = (GLfloat)dPriv->y;
GLfloat wh = (GLfloat)dPriv->h;
GLfloat sx,sy,sz, tx,ty,tz;
if (ctx->_RotateMode) {
sx = height / 2.0F;
tx = wx - sx + ww - y + SUBPIXEL_X;
sy = - width / 2.0F;
ty = wy + sy + wh - x + SUBPIXEL_Y;
sz = ctx->DepthMaxF * ((f - n) / 2.0F) * rmesa->state.depth.scale;
tz = ctx->DepthMaxF * ((f - n) / 2.0F + n) * rmesa->state.depth.scale;
}
else {
sx = width / 2.0F;
tx = wx + sx + x + SUBPIXEL_X;
sy = -height / 2.0F;
ty = wy + sy + wh - y + SUBPIXEL_Y;
sz = ctx->DepthMaxF * ((f - n) / 2.0F) * rmesa->state.depth.scale;
tz = ctx->DepthMaxF * ((f - n) / 2.0F + n) * rmesa->state.depth.scale;
}
GLfloat sx = v[MAT_SX];
GLfloat tx = v[MAT_TX] + xoffset + SUBPIXEL_X;
GLfloat sy = - v[MAT_SY];
GLfloat ty = (- v[MAT_TY]) + yoffset + SUBPIXEL_Y;
GLfloat sz = v[MAT_SZ] * rmesa->state.depth.scale;
GLfloat tz = v[MAT_TZ] * rmesa->state.depth.scale;
RADEON_FIREVERTICES( rmesa );
RADEON_STATECHANGE( rmesa, vpt );
if (0) fprintf(stderr, "%s: %f %f %f %f\n", __FUNCTION__, sx, tx, sy, ty);
rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE] = *(GLuint *)&sx;
rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = *(GLuint *)&tx;
rmesa->hw.vpt.cmd[VPT_SE_VPORT_YSCALE] = *(GLuint *)&sy;
rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = *(GLuint *)&ty;
rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE] = *(GLuint *)&sz;
rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = *(GLuint *)&tz;
}
/**
* \brief Set the viewport.
*
* \param ctx GL context.
* \param x \e x position of the lower left corner of the viewport rectangle.
* Not used.
* \param y \e y position of the lower left corner of the viewport rectangle.
@@ -1023,8 +1055,8 @@ void radeonUpdateWindow( GLcontext *ctx )
*
* Fires the vertices and updates the window.
*/
static void radeonViewport( GLcontext *ctx, GLint x, GLint y,
GLsizei width, GLsizei height )
static void radeonViewport( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height )
{
/* Don't pipeline viewport changes, conflict with window offset
* setting below. Could apply deltas to rescue pipelined viewport
@@ -1126,7 +1158,9 @@ static void radeonLogicOpCode( GLcontext *ctx, GLenum opcode )
void radeonSetCliprects( radeonContextPtr rmesa, GLenum mode )
{
__DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
fprintf(stderr, "%s\n", __FUNCTION__);
switch ( mode ) {
case GL_FRONT_LEFT:
rmesa->numClipRects = dPriv->numClipRects;
@@ -1153,6 +1187,8 @@ void radeonSetCliprects( radeonContextPtr rmesa, GLenum mode )
return;
}
fprintf(stderr, "%s: %d cliprects\n", __FUNCTION__, rmesa->numClipRects);
if (rmesa->state.scissor.enabled)
radeonRecalcScissorRects( rmesa );
}
@@ -1609,6 +1645,31 @@ void radeonUploadMatrixTranspose( radeonContextPtr rmesa, GLfloat *src,
}
#define A(row,col) a[(col<<2)+row]
#define B(row,col) b[(col<<2)+row]
#define P(row,col) product[(col<<2)+row]
static void matmul4( GLfloat *product, const GLfloat *a, const GLfloat *b )
{
GLint i;
for (i = 0; i < 4; i++) {
const GLfloat ai0=A(i,0), ai1=A(i,1), ai2=A(i,2), ai3=A(i,3);
P(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0) + ai3 * B(3,0);
P(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1) + ai3 * B(3,1);
P(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2) + ai3 * B(3,2);
P(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3 * B(3,3);
}
}
static const GLfloat rot[16] = {
0, 1, 0, 0,
-1, 0, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
};
void radeonValidateState( GLcontext *ctx )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
@@ -1621,8 +1682,16 @@ void radeonValidateState( GLcontext *ctx )
/* Need an event driven matrix update?
*/
if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION))
radeonUploadMatrix( rmesa, ctx->_ModelProjectMatrix.m, MODEL_PROJ );
if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION)) {
if (ctx->_RotateMode) {
GLfloat tmp[16];
matmul4( tmp, rot, ctx->_ModelProjectMatrix.m );
radeonUploadMatrix( rmesa, tmp, MODEL_PROJ );
}
else {
radeonUploadMatrix( rmesa, ctx->_ModelProjectMatrix.m, MODEL_PROJ );
}
}
/* Need these for lighting (shouldn't upload otherwise)
*/
@@ -1726,8 +1795,7 @@ void radeonInitStateFuncs( GLcontext *ctx )
ctx->Driver.StencilFunc = radeonStencilFunc;
ctx->Driver.StencilMask = radeonStencilMask;
ctx->Driver.StencilOp = radeonStencilOp;
ctx->Driver.Viewport = radeonViewport;
ctx->Driver.Viewport = radeonViewport;
}
/*@}*/

View File

@@ -36,16 +36,14 @@
#ifndef __RADEON_SUBSET_H__
#define __RADEON_SUBSET_H__
extern void radeonPointsBitmap( GLcontext *ctx, GLint px, GLint py,
GLsizei width, GLsizei height,
const struct gl_pixelstore_attrib *unpack,
extern void radeonPointsBitmap( GLsizei width, GLsizei height,
GLfloat xorig, GLfloat yorig,
GLfloat xmove, GLfloat ymove,
const GLubyte *bitmap );
extern void radeonReadPixels( GLcontext *ctx,
GLint x, GLint y,
extern void radeonReadPixels( GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *packing,
GLvoid *pixels );
extern void radeon_select_Install( GLcontext *ctx );

View File

@@ -37,11 +37,13 @@
#include "glheader.h"
#include "mtypes.h"
#include "colormac.h"
#include "context.h"
#include "enums.h"
#include "imports.h"
#include "image.h"
#include "mmath.h"
#include "macros.h"
#include "state.h"
#include "radeon_context.h"
#include "radeon_ioctl.h"
@@ -65,45 +67,52 @@
* restores TCL, viewport, texture and color states.
*/
void
radeonPointsBitmap( GLcontext *ctx, GLint px, GLint py,
GLsizei width, GLsizei height,
const struct gl_pixelstore_attrib *unpack,
const GLubyte *bitmap )
radeonPointsBitmap( GLsizei width, GLsizei height,
GLfloat xorig, GLfloat yorig,
GLfloat xmove, GLfloat ymove,
const GLubyte *bitmap )
{
GET_CURRENT_CONTEXT(ctx);
GLsizei bmwidth = width, bmheight = height;
GLint px, py;
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
GLfloat saved_color[4], saved_tex0[2];
GLint row, col;
GLuint orig_se_cntl;
GLuint h;
GLfloat pfz = ctx->Current.RasterPos[3];
GLint skipRows = unpack->SkipRows;
GLint skipPixels = unpack->SkipPixels;
GLuint w, h;
const struct gl_pixelstore_attrib *unpack = &ctx->Unpack;
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
if (width < 0 || height < 0) {
_mesa_error( ctx, GL_INVALID_VALUE, "glBitmap(width or height < 0)" );
return;
}
if (!ctx->Current.RasterPosValid)
return;
/* horizontal clipping */
if (px < 0) {
skipPixels -= px;
width += px;
px = 0;
}
if (px + width > (GLint) ctx->ReadBuffer->Width)
width -= (px + width - (GLint) ctx->ReadBuffer->Width);
if (width <= 0)
return;
if (ctx->NewState)
_mesa_update_state(ctx);
/* vertical clipping */
if (py < 0) {
skipRows -= py;
height += py;
py = 0;
if (ctx->_RotateMode) {
width = bmheight; height = bmwidth;
px = IFLOOR(ctx->Current.RasterPos[0] + yorig);
py = IFLOOR(ctx->Current.RasterPos[1] + xorig);
ctx->Current.RasterPos[0] += ymove;
ctx->Current.RasterPos[1] += xmove;
}
if (py + height > (GLint) ctx->ReadBuffer->Height)
height -= (py + height - (GLint) ctx->ReadBuffer->Height);
if (height <= 0)
return;
else {
px = IFLOOR(ctx->Current.RasterPos[0] - xorig);
py = IFLOOR(ctx->Current.RasterPos[1] - yorig);
ctx->Current.RasterPos[0] += xmove;
ctx->Current.RasterPos[1] += ymove;
}
/* Turn off tcl and the hw viewport transformation so that we can
@@ -119,6 +128,7 @@ radeonPointsBitmap( GLcontext *ctx, GLint px, GLint py,
/* Adjust for window coordinates, flip y values:
*/
h = rmesa->dri.drawable->h + rmesa->dri.drawable->y - 1;
w = rmesa->dri.drawable->w;
px += rmesa->dri.drawable->x;
/* Save current color, texcoord to restore later:
@@ -132,42 +142,48 @@ radeonPointsBitmap( GLcontext *ctx, GLint px, GLint py,
glColor4fv( ctx->Current.RasterColor );
glTexCoord2fv( ctx->Current.RasterTexCoords[0] );
for (row=0; row<height; row++) {
GLuint y = h - (py + row);
const GLubyte *src = (const GLubyte *)
_mesa_image_address( unpack, bitmap, width, height,
GL_COLOR_INDEX, GL_BITMAP, 0, row, 0 );
if (unpack->LsbFirst) {
/* Lsb first */
GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
for (col=0; col<width; col++) {
if (*src & mask)
glVertex3f( px+col, y, pfz );
src += (mask >> 7);
mask = ((mask << 1) & 0xff) | (mask >> 7);
}
/* get ready for next row */
if (mask != 1)
src++;
}
else {
/* Msb first */
GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
for (col=0; col<width; col++) {
if (*src & mask) {
glVertex3f( px+col, y, pfz );
}
if (ctx->_RotateMode) {
for (col=0; col<width; col++) {
const GLubyte *src = (const GLubyte *)
_mesa_image_address( unpack, bitmap, height, width,
GL_COLOR_INDEX, GL_BITMAP, 0, col, 0 );
/* Msb first */
GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
for (row=0; row<height; row++) {
if (*src & mask) {
glVertex2f( px-col, h - (py + row) );
}
src += mask & 1;
mask = ((mask << 7) & 0xff) | (mask >> 1);
}
/* get ready for next row */
if (mask != 128)
src++;
}
/* get ready for next row */
if (mask != 128)
src++;
}
}
else {
for (row=0; row<height; row++) {
const GLubyte *src = (const GLubyte *)
_mesa_image_address( unpack, bitmap, width, height,
GL_COLOR_INDEX, GL_BITMAP, 0, row, 0 );
/* Msb first */
GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
for (col=0; col<width; col++) {
if (*src & mask) {
glVertex2f( px+col, h - (py + row) );
}
src += mask & 1;
mask = ((mask << 7) & 0xff) | (mask >> 1);
}
/* get ready for next row */
if (mask != 128)
src++;
}
}
glEnd();
glColor4fv( saved_color );
glTexCoord2fv( saved_tex0 );
@@ -178,3 +194,4 @@ radeonPointsBitmap( GLcontext *ctx, GLint px, GLint py,
rmesa->hw.set.cmd[SET_SE_CNTL] = orig_se_cntl;
radeonSubsetVtxEnableTCL( rmesa, GL_TRUE );
}

View File

@@ -37,10 +37,12 @@
#include "glheader.h"
#include "mtypes.h"
#include "colormac.h"
#include "context.h"
#include "enums.h"
#include "imports.h"
#include "mmath.h"
#include "macros.h"
#include "state.h"
#include "radeon_context.h"
#include "radeon_ioctl.h"
@@ -96,19 +98,36 @@ static void ReadRGBASpan( const GLcontext *ctx,
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
radeonScreenPtr radeonScreen = rmesa->radeonScreen;
__DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
GLuint pitch = radeonScreen->frontPitch * radeonScreen->cpp;
char *ptr = (char *)(rmesa->dri.screen->pFB +
rmesa->state.pixel.readOffset +
((dPriv->x + x) * radeonScreen->cpp) +
((dPriv->y + (dPriv->h - y - 1)) * pitch));
GLint i = 0;
GLuint cpp = radeonScreen->cpp;
GLuint pitch = radeonScreen->frontPitch * cpp;
GLint i;
if (radeonScreen->cpp == 4)
for (i = 0; i < n; i++, ptr += 4)
READ_RGBA_32( rgba[i], ptr );
else
for (i = 0; i < n; i++, ptr += 2)
READ_RGBA_16( rgba[i], ptr );
if (ctx->_RotateMode) {
char *ptr = (char *)(rmesa->dri.screen->pFB +
rmesa->state.pixel.readOffset +
((dPriv->x + (dPriv->w - y - 1)) * cpp) +
((dPriv->y + (dPriv->h - x - 1)) * pitch));
if (cpp == 4)
for (i = 0; i < n; i++, ptr -= pitch)
READ_RGBA_32( rgba[i], ptr );
else
for (i = 0; i < n; i++, ptr -= pitch)
READ_RGBA_16( rgba[i], ptr );
}
else {
char *ptr = (char *)(rmesa->dri.screen->pFB +
rmesa->state.pixel.readOffset +
((dPriv->x + x) * cpp) +
((dPriv->y + (dPriv->h - y - 1)) * pitch));
if (cpp == 4)
for (i = 0; i < n; i++, ptr += cpp)
READ_RGBA_32( rgba[i], ptr );
else
for (i = 0; i < n; i++, ptr += cpp)
READ_RGBA_16( rgba[i], ptr );
}
}
@@ -131,20 +150,42 @@ static void ReadRGBASpan( const GLcontext *ctx,
* After asserting the above conditions, compensates for clipping and calls
* ReadRGBASpan() to read each row.
*/
void radeonReadPixels( GLcontext *ctx,
GLint x, GLint y,
void radeonReadPixels( GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *packing,
GLvoid *pixels )
{
GET_CURRENT_CONTEXT(ctx);
GLint srcX = x;
GLint srcY = y;
GLint readWidth = width; /* actual width read */
GLint readHeight = height; /* actual height read */
const struct gl_pixelstore_attrib *packing = &ctx->Pack;
GLint skipRows = packing->SkipRows;
GLint skipPixels = packing->SkipPixels;
GLint rowLength;
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
{
GLint tmp, tmps;
tmp = x; x = y; y = tmp;
tmps = width; width = height; height = tmps;
}
if (width < 0 || height < 0) {
_mesa_error( ctx, GL_INVALID_VALUE,
"glReadPixels(width=%d height=%d)", width, height );
return;
}
if (!pixels) {
_mesa_error( ctx, GL_INVALID_VALUE, "glReadPixels(pixels)" );
return;
}
if (ctx->NewState)
_mesa_update_state(ctx);
/* can't do scale, bias, mapping, etc */
assert(!ctx->_ImageTransferState);

View File

@@ -27,7 +27,7 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/* $Id: radeon_subset_select.c,v 1.1.2.4 2003/02/23 16:50:48 jrfonseca Exp $ */
/* $Id: radeon_subset_select.c,v 1.1.2.5 2003/03/17 21:23:00 keithw Exp $ */
#include "glheader.h"
@@ -913,6 +913,7 @@ static void radeon_select_End(void)
ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1;
}
/**
* \brief Flush vertices.
*

Some files were not shown because too many files have changed in this diff Show More