Compare commits
253 Commits
mesa-7.3-r
...
mesa-7.4-r
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
af3c568475 | ||
|
|
7d01429512 | ||
|
|
8d088cd34f | ||
|
|
094d627885 | ||
|
|
17db2db9dc | ||
|
|
dba79af9bc | ||
|
|
b009a32bf4 | ||
|
|
7122490982 | ||
|
|
6ada1d47d9 | ||
|
|
55865335f4 | ||
|
|
918e5221ef | ||
|
|
9feb26584a | ||
|
|
a8528a2e86 | ||
|
|
119360cccd | ||
|
|
ac2216542d | ||
|
|
37e5c057f1 | ||
|
|
4d9b8e0f93 | ||
|
|
c1b71f46b5 | ||
|
|
4a25ac9564 | ||
|
|
35d965b39b | ||
|
|
d0aab00609 | ||
|
|
ef33d0f103 | ||
|
|
349b819768 | ||
|
|
50443db882 | ||
|
|
c503cacb53 | ||
|
|
e862b4e38f | ||
|
|
e9dfc858fb | ||
|
|
5efbca1e21 | ||
|
|
d6d8663a88 | ||
|
|
13990bd98a | ||
|
|
def630d0a2 | ||
|
|
ca2564f1e6 | ||
|
|
711a57f7c7 | ||
|
|
058cf2fff1 | ||
|
|
715f509c5d | ||
|
|
e704e6c6f3 | ||
|
|
01f34e667a | ||
|
|
4d0a7b33c5 | ||
|
|
fb1d2ed34c | ||
|
|
9395fedf98 | ||
|
|
9abc0d80af | ||
|
|
90e89c01df | ||
|
|
790d93e362 | ||
|
|
e9f3783169 | ||
|
|
e41780fedc | ||
|
|
d0edbbb3f3 | ||
|
|
e10119c23e | ||
|
|
208c087f39 | ||
|
|
0c8b40b42b | ||
|
|
5199f451bb | ||
|
|
dd7cde5230 | ||
|
|
ab5746e5d8 | ||
|
|
3bd446c0ab | ||
|
|
9b78402ee4 | ||
|
|
cf1ef0f308 | ||
|
|
fd1f65ba61 | ||
|
|
967345b497 | ||
|
|
41ad853a6a | ||
|
|
842baa29cb | ||
|
|
9556d870a1 | ||
|
|
42ce790086 | ||
|
|
b17769af42 | ||
|
|
9030277b0d | ||
|
|
a37a9bf769 | ||
|
|
8afb8a8145 | ||
|
|
801f933694 | ||
|
|
75ecd6ebbf | ||
|
|
1cd7317fdb | ||
|
|
1865291701 | ||
|
|
3edbcce7d5 | ||
|
|
b1fb34d0ac | ||
|
|
606099f545 | ||
|
|
32e3142071 | ||
|
|
66eea4e104 | ||
|
|
e428cf3afd | ||
|
|
842b5164d2 | ||
|
|
a6f7e909a7 | ||
|
|
ca87e5a7bd | ||
|
|
45c4b4dfbd | ||
|
|
2adaec1226 | ||
|
|
549586c319 | ||
|
|
463ac421a5 | ||
|
|
6801240205 | ||
|
|
a22088b7d5 | ||
|
|
e89c49147f | ||
|
|
67634240d1 | ||
|
|
819b028a8e | ||
|
|
a43c30ef41 | ||
|
|
b65bfde84d | ||
|
|
c39e6917ac | ||
|
|
c79079895f | ||
|
|
4480e631cd | ||
|
|
c32661c3ce | ||
|
|
d5c06bb812 | ||
|
|
9d5aa36239 | ||
|
|
e3050c1777 | ||
|
|
06295ddbdd | ||
|
|
e2092bb23c | ||
|
|
528836d0ad | ||
|
|
3511442e43 | ||
|
|
d20c53b511 | ||
|
|
091cc122ad | ||
|
|
c983abbb9e | ||
|
|
a0a81204c2 | ||
|
|
409d4f839c | ||
|
|
0ab36958ea | ||
|
|
c2445f43a3 | ||
|
|
f3d1c136b7 | ||
|
|
dd10a8b09d | ||
|
|
dd312366da | ||
|
|
d2fe466ef3 | ||
|
|
fe5328bfad | ||
|
|
c0891dde07 | ||
|
|
0e6d9c1a55 | ||
|
|
5f74a66132 | ||
|
|
46f8b62d5f | ||
|
|
3e3e80c431 | ||
|
|
0486d117e4 | ||
|
|
29981c14da | ||
|
|
98d5efb2c5 | ||
|
|
77a44aafaf | ||
|
|
8278c70716 | ||
|
|
ac0955f5e2 | ||
|
|
4130c35ca8 | ||
|
|
d440647eb8 | ||
|
|
7e8f2c56c0 | ||
|
|
a0880a152f | ||
|
|
4608a9172f | ||
|
|
d0e38f7ec0 | ||
|
|
a69bdbbbdd | ||
|
|
88c97a2662 | ||
|
|
ce9c69ddbc | ||
|
|
e430fcb716 | ||
|
|
11a363e632 | ||
|
|
9a3a20b2b9 | ||
|
|
4672811541 | ||
|
|
3cad3d28a5 | ||
|
|
41e63fbdb2 | ||
|
|
b543401a5c | ||
|
|
8c4f08fbad | ||
|
|
f3081a34d2 | ||
|
|
cff0971f87 | ||
|
|
5ac4c69d83 | ||
|
|
a314c40cc4 | ||
|
|
959fd6b8f6 | ||
|
|
937f0da04a | ||
|
|
73bc5967e2 | ||
|
|
7b1d3cf392 | ||
|
|
25515b557e | ||
|
|
51625ff86e | ||
|
|
4d8f661726 | ||
|
|
efa69a2f66 | ||
|
|
a2dce49158 | ||
|
|
e4b28de803 | ||
|
|
30a6dd78d5 | ||
|
|
9f75836308 | ||
|
|
609cc9c139 | ||
|
|
e5aa89386d | ||
|
|
5a45897711 | ||
|
|
faa6d8af59 | ||
|
|
b6c41fd933 | ||
|
|
b8bd0b0ddc | ||
|
|
fc3971d800 | ||
|
|
046e88fc0b | ||
|
|
f5c47105db | ||
|
|
f1939c8685 | ||
|
|
3ac4d678ef | ||
|
|
194d039f1e | ||
|
|
470e10dfaa | ||
|
|
8c7135ee14 | ||
|
|
4683cab29a | ||
|
|
787a001a67 | ||
|
|
dd92f483b0 | ||
|
|
65118a51b6 | ||
|
|
ab9b4e1f59 | ||
|
|
fcfec66865 | ||
|
|
53426d7113 | ||
|
|
39e6d0d810 | ||
|
|
b5da7feee0 | ||
|
|
0f548dbc98 | ||
|
|
9d216be8cf | ||
|
|
eb26cc6cf5 | ||
|
|
bb63a663b1 | ||
|
|
dace4e3e2a | ||
|
|
bbda892c55 | ||
|
|
61a387dca1 | ||
|
|
437fa85ba3 | ||
|
|
b00477acf3 | ||
|
|
7374285f07 | ||
|
|
5c84a1032c | ||
|
|
dbda49a9e6 | ||
|
|
11351f0c8a | ||
|
|
a5b5bc9f95 | ||
|
|
f97792421b | ||
|
|
396711b840 | ||
|
|
dbd8e4066b | ||
|
|
b7f802eca2 | ||
|
|
1d4756de06 | ||
|
|
c1abb821f9 | ||
|
|
a61a1a8181 | ||
|
|
345a08a77f | ||
|
|
12c6d28cc7 | ||
|
|
e442fe5ba5 | ||
|
|
66a4f5cf9a | ||
|
|
a740858fc0 | ||
|
|
e7c988d065 | ||
|
|
4a8356209d | ||
|
|
e1ba29ea19 | ||
|
|
fbf13bcb8a | ||
|
|
8f8435637d | ||
|
|
7d08091767 | ||
|
|
b5f32e1d5a | ||
|
|
0dffd22349 | ||
|
|
947d1c5b2a | ||
|
|
c7f43543af | ||
|
|
5912cdff3e | ||
|
|
03188b09e0 | ||
|
|
fae9604727 | ||
|
|
aac4a0509e | ||
|
|
b5f89e5f17 | ||
|
|
c12d24b513 | ||
|
|
2549c26a8b | ||
|
|
a98dccca36 | ||
|
|
1b3e3e6b84 | ||
|
|
49b53407c7 | ||
|
|
d911e3e24f | ||
|
|
658ab3c3ae | ||
|
|
8f7349dbb4 | ||
|
|
d687476edd | ||
|
|
c157a5bb91 | ||
|
|
14eca6b573 | ||
|
|
ef0e0f2550 | ||
|
|
34d17d2bdc | ||
|
|
01a0938776 | ||
|
|
1f47388dfe | ||
|
|
34500a6da5 | ||
|
|
00c02626d8 | ||
|
|
eeeed45c2c | ||
|
|
3a5463d158 | ||
|
|
de35989cde | ||
|
|
29f603a270 | ||
|
|
7f7fc3e3af | ||
|
|
a0318d7f8e | ||
|
|
06fdb6a74c | ||
|
|
88fdddcbbe | ||
|
|
1598be5083 | ||
|
|
436024561a | ||
|
|
0f0922f93c | ||
|
|
33f6dc3c33 | ||
|
|
356428d4e4 | ||
|
|
b4866f8a52 | ||
|
|
297a9606ea | ||
|
|
44557bf065 |
19
Makefile
19
Makefile
@@ -174,10 +174,11 @@ ultrix-gcc:
|
||||
|
||||
# Rules for making release tarballs
|
||||
|
||||
DIRECTORY = Mesa-7.3-rc1
|
||||
LIB_NAME = MesaLib-7.3-rc1
|
||||
DEMO_NAME = MesaDemos-7.3-rc1
|
||||
GLUT_NAME = MesaGLUT-7.3-rc1
|
||||
VERSION=7.4-rc1
|
||||
DIRECTORY = Mesa-$(VERSION)
|
||||
LIB_NAME = MesaLib-$(VERSION)
|
||||
DEMO_NAME = MesaDemos-$(VERSION)
|
||||
GLUT_NAME = MesaGLUT-$(VERSION)
|
||||
|
||||
MAIN_FILES = \
|
||||
$(DIRECTORY)/Makefile* \
|
||||
@@ -223,6 +224,7 @@ MAIN_FILES = \
|
||||
$(DIRECTORY)/src/mesa/sources \
|
||||
$(DIRECTORY)/src/mesa/descrip.mms \
|
||||
$(DIRECTORY)/src/mesa/gl.pc.in \
|
||||
$(DIRECTORY)/src/mesa/osmesa.pc.in \
|
||||
$(DIRECTORY)/src/mesa/depend \
|
||||
$(DIRECTORY)/src/mesa/main/*.[chS] \
|
||||
$(DIRECTORY)/src/mesa/main/descrip.mms \
|
||||
@@ -297,14 +299,7 @@ MAIN_FILES = \
|
||||
$(DIRECTORY)/vms/analyze_map.com \
|
||||
$(DIRECTORY)/vms/xlib.opt \
|
||||
$(DIRECTORY)/vms/xlib_share.opt \
|
||||
$(DIRECTORY)/windows/VC8/mesa/mesa.sln \
|
||||
$(DIRECTORY)/windows/VC8/mesa/gdi/gdi.vcproj \
|
||||
$(DIRECTORY)/windows/VC8/mesa/glu/glu.vcproj \
|
||||
$(DIRECTORY)/windows/VC8/mesa/mesa/mesa.vcproj \
|
||||
$(DIRECTORY)/windows/VC8/mesa/osmesa/osmesa.vcproj \
|
||||
$(DIRECTORY)/windows/VC8/progs/progs.sln \
|
||||
$(DIRECTORY)/windows/VC8/progs/demos/gears.vcproj \
|
||||
$(DIRECTORY)/windows/VC8/progs/glut/glut.vcproj
|
||||
$(DIRECTORY)/windows/VC8/
|
||||
|
||||
|
||||
DRI_FILES = \
|
||||
|
||||
23
configure.ac
23
configure.ac
@@ -22,7 +22,7 @@ AC_CONFIG_AUX_DIR([bin])
|
||||
AC_CANONICAL_HOST
|
||||
|
||||
dnl Versions for external dependencies
|
||||
LIBDRM_REQUIRED=2.3.1
|
||||
LIBDRM_REQUIRED=2.4.3
|
||||
DRI2PROTO_REQUIRED=1.99.3
|
||||
|
||||
dnl Check for progs
|
||||
@@ -46,10 +46,14 @@ esac
|
||||
MKDEP_OPTIONS=-fdepend
|
||||
dnl Ask gcc where it's keeping its secret headers
|
||||
if test "x$GCC" = xyes; then
|
||||
GCC_INCLUDES=`$CC -print-file-name=include`
|
||||
if test "x$GCC_INCLUDES" != x; then
|
||||
MKDEP_OPTIONS="$MKDEP_OPTIONS -I$GCC_INCLUDES"
|
||||
fi
|
||||
for dir in include include-fixed; do
|
||||
GCC_INCLUDES=`$CC -print-file-name=$dir`
|
||||
if test "x$GCC_INCLUDES" != x && \
|
||||
test "$GCC_INCLUDES" != "$dir" && \
|
||||
test -d "$GCC_INCLUDES"; then
|
||||
MKDEP_OPTIONS="$MKDEP_OPTIONS -I$GCC_INCLUDES"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
AC_SUBST([MKDEP_OPTIONS])
|
||||
|
||||
@@ -83,11 +87,8 @@ dnl Compiler macros
|
||||
DEFINES=""
|
||||
AC_SUBST([DEFINES])
|
||||
case "$host_os" in
|
||||
*-gnu)
|
||||
if test "x$GCC" = xyes; then
|
||||
DEFINES="$DEFINES -D_POSIX_SOURCE -D_POSIX_C_SOURCE=199309L -D_BSD_SOURCE"
|
||||
fi
|
||||
DEFINES="$DEFINES -D_SVID_SOURCE -D_GNU_SOURCE -DPTHREADS"
|
||||
linux*|*-gnu*)
|
||||
DEFINES="$DEFINES -D_GNU_SOURCE -DPTHREADS"
|
||||
;;
|
||||
solaris*)
|
||||
DEFINES="$DEFINES -DPTHREADS -DSVR4"
|
||||
@@ -365,7 +366,7 @@ default_driver="xlib"
|
||||
case "$host_os" in
|
||||
linux*)
|
||||
case "$host_cpu" in
|
||||
i*86|x86_64|powerpc*) default_driver="dri";;
|
||||
i*86|x86_64|powerpc*|sparc*) default_driver="dri";;
|
||||
esac
|
||||
;;
|
||||
*freebsd* | dragonfly*)
|
||||
|
||||
34
debian/changelog
vendored
34
debian/changelog
vendored
@@ -1,3 +1,37 @@
|
||||
mesa (7.4~rc1-1) experimental; urgency=low
|
||||
|
||||
* New upstream release candidate.
|
||||
* Fix watch file to make uscan not consider release candidates as newer than
|
||||
actual releases.
|
||||
* debian/control: add lpia to the Architecture field for
|
||||
libgl1-mesa-dri{,-dbg} to match Ubuntu.
|
||||
* debian/rules: on lpia, only build the i915 and i965 dri drivers (based on
|
||||
Ubuntu changes).
|
||||
* Build-depend on linux-libc-dev >= 2.6.29 on linux archs.
|
||||
|
||||
-- Julien Cristau <jcristau@debian.org> Wed, 25 Mar 2009 11:34:42 +0100
|
||||
|
||||
mesa (7.3-1) experimental; urgency=low
|
||||
|
||||
[ Timo Aaltonen ]
|
||||
* New upstream release.
|
||||
|
||||
[ Julien Cristau ]
|
||||
* Try to make the diff a bit smaller by removing directories that are in
|
||||
upstream git but not in tarballs.
|
||||
|
||||
-- Julien Cristau <jcristau@debian.org> Fri, 30 Jan 2009 20:00:34 +0100
|
||||
|
||||
mesa (7.3~rc3-1) experimental; urgency=low
|
||||
|
||||
[ Timo Aaltonen ]
|
||||
* New upstream release candidate.
|
||||
|
||||
[ Julien Cristau ]
|
||||
* Refresh patches 03 and 04.
|
||||
|
||||
-- Julien Cristau <jcristau@debian.org> Wed, 21 Jan 2009 19:01:21 +0100
|
||||
|
||||
mesa (7.3~rc1-1) experimental; urgency=low
|
||||
|
||||
* New upstream release candidate.
|
||||
|
||||
7
debian/control
vendored
7
debian/control
vendored
@@ -8,7 +8,8 @@ Build-Depends: debhelper (>= 5), quilt (>= 0.40), pkg-config,
|
||||
libdrm-dev (>= 2.4.3) [!hurd-i386], libx11-dev, xutils-dev,
|
||||
x11proto-gl-dev (>= 1.4.8), libxxf86vm-dev,
|
||||
libexpat1-dev, lesstif2-dev, dpkg-dev (>= 1.13.19), libxfixes-dev,
|
||||
libxdamage-dev, libxext-dev, autoconf, automake, x11proto-dri2-dev (>= 1.99.3)
|
||||
libxdamage-dev, libxext-dev, autoconf, automake, x11proto-dri2-dev (>= 1.99.3),
|
||||
linux-libc-dev (>= 2.6.29) [!hurd-i386 !kfreebsd-amd64 !kfreebsd-i386]
|
||||
Vcs-Git: git://git.debian.org/git/pkg-xorg/lib/mesa
|
||||
Vcs-Browser: http://git.debian.org/?p=pkg-xorg/lib/mesa.git
|
||||
Homepage: http://mesa3d.sourceforge.net/
|
||||
@@ -162,7 +163,7 @@ Description: Debugging symbols for the Mesa GLX runtime
|
||||
Package: libgl1-mesa-dri
|
||||
Section: libs
|
||||
Priority: optional
|
||||
Architecture: alpha amd64 arm armeb armel hppa i386 ia64 kfreebsd-i386 kfreebsd-amd64 m68k mips mipsel powerpc s390 sparc
|
||||
Architecture: alpha amd64 arm armeb armel hppa i386 ia64 kfreebsd-i386 kfreebsd-amd64 lpia m68k mips mipsel powerpc s390 sparc
|
||||
Depends: ${shlibs:Depends}, libgl1-mesa-glx (= ${binary:Version})
|
||||
Suggests: libglide3
|
||||
Conflicts: xlibmesa-dri (<< 1:7.0.0)
|
||||
@@ -183,7 +184,7 @@ Description: A free implementation of the OpenGL API -- DRI modules
|
||||
Package: libgl1-mesa-dri-dbg
|
||||
Section: libdevel
|
||||
Priority: extra
|
||||
Architecture: alpha amd64 arm armeb armel hppa i386 ia64 kfreebsd-i386 kfreebsd-amd64 m68k mips mipsel powerpc s390 sparc
|
||||
Architecture: alpha amd64 arm armeb armel hppa i386 ia64 kfreebsd-i386 kfreebsd-amd64 lpia m68k mips mipsel powerpc s390 sparc
|
||||
Depends: libgl1-mesa-dri (= ${binary:Version})
|
||||
Description: Debugging symbols for the Mesa DRI modules
|
||||
This version of Mesa provides GLX and DRI capabilities: it is capable of
|
||||
|
||||
@@ -12,8 +12,8 @@ and we don't actually build it at this point.
|
||||
|
||||
Index: mesa/progs/xdemos/Makefile
|
||||
===================================================================
|
||||
--- mesa.orig/progs/xdemos/Makefile 2008-07-01 15:26:56.000000000 +0300
|
||||
+++ mesa/progs/xdemos/Makefile 2008-07-01 15:48:47.000000000 +0300
|
||||
--- mesa.orig/progs/xdemos/Makefile
|
||||
+++ mesa/progs/xdemos/Makefile
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
LIBS = -L$(TOP)/$(LIB_DIR) -l$(GL_LIB) $(APP_LIB_DEPS)
|
||||
@@ -21,9 +21,9 @@ Index: mesa/progs/xdemos/Makefile
|
||||
-PROGS = \
|
||||
+PROGS ?= \
|
||||
corender \
|
||||
glsync \
|
||||
glthreads \
|
||||
glxdemo \
|
||||
@@ -60,6 +60,11 @@
|
||||
@@ -61,6 +61,11 @@
|
||||
extra: $(EXTRA_PROGS)
|
||||
|
||||
|
||||
@@ -37,8 +37,8 @@ Index: mesa/progs/xdemos/Makefile
|
||||
-rm -f *.o *~
|
||||
Index: mesa/progs/Makefile
|
||||
===================================================================
|
||||
--- mesa.orig/progs/Makefile 2008-07-01 15:26:56.000000000 +0300
|
||||
+++ mesa/progs/Makefile 2008-07-01 15:48:07.000000000 +0300
|
||||
--- mesa.orig/progs/Makefile
|
||||
+++ mesa/progs/Makefile
|
||||
@@ -21,8 +21,12 @@
|
||||
fi \
|
||||
done
|
||||
|
||||
10
debian/patches/04_osmesa_version.diff
vendored
10
debian/patches/04_osmesa_version.diff
vendored
@@ -1,17 +1,17 @@
|
||||
Index: mesa/src/mesa/drivers/osmesa/Makefile
|
||||
===================================================================
|
||||
--- mesa.orig/src/mesa/drivers/osmesa/Makefile 2008-09-12 10:44:02.000000000 +0300
|
||||
+++ mesa/src/mesa/drivers/osmesa/Makefile 2008-09-23 16:07:40.000000000 +0300
|
||||
@@ -46,7 +46,7 @@
|
||||
--- mesa.orig/src/mesa/drivers/osmesa/Makefile
|
||||
+++ mesa/src/mesa/drivers/osmesa/Makefile
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
$(TOP)/lib/$(OSMESA_LIB_NAME): $(OBJECTS)
|
||||
$(TOP)/$(LIB_DIR)/$(OSMESA_LIB_NAME): $(OBJECTS)
|
||||
$(MKLIB) -o $(OSMESA_LIB) -linker '$(CC)' -ldflags '$(LDFLAGS)' \
|
||||
- -major $(MESA_MAJOR) -minor $(MESA_MINOR) -patch $(MESA_TINY) \
|
||||
+ -major 6 -minor 5 -patch 3 \
|
||||
-install $(TOP)/$(LIB_DIR) $(MKLIB_OPTIONS) \
|
||||
-id $(INSTALL_LIB_DIR)/lib$(OSMESA_LIB).$(MESA_MAJOR).dylib \
|
||||
$(OSMESA_LIB_DEPS) $(OBJECTS)
|
||||
@@ -58,7 +58,7 @@
|
||||
@@ -57,7 +57,7 @@
|
||||
# with all the other Mesa sources (compiled with -DCHAN_BITS=16/32
|
||||
osmesa16: $(OBJECTS) $(CORE_MESA)
|
||||
$(MKLIB) -o $(OSMESA_LIB) -linker '$(CC)' -ldflags '$(LDFLAGS)' \
|
||||
|
||||
13
debian/rules
vendored
13
debian/rules
vendored
@@ -63,15 +63,18 @@ ifeq ($(DEB_HOST_ARCH_OS), hurd)
|
||||
DIRECT_RENDERING = --disable-driglx-direct
|
||||
else
|
||||
DIRECT_RENDERING = --enable-driglx-direct
|
||||
ifeq ($(DEB_HOST_ARCH), lpia)
|
||||
DRI_DRIVERS += i915 i965
|
||||
else
|
||||
DRI_DRIVERS += mach64 mga r128 r200 r300 radeon s3v savage tdfx trident
|
||||
endif
|
||||
|
||||
ifeq ($(DEB_HOST_GNU_CPU), i486)
|
||||
ifeq ($(DEB_HOST_GNU_CPU), i486)
|
||||
DRI_DRIVERS += i810 i915 i965 sis unichrome
|
||||
else ifeq ($(DEB_HOST_GNU_CPU), x86_64)
|
||||
else ifeq ($(DEB_HOST_GNU_CPU), x86_64)
|
||||
DRI_DRIVERS += i915 i965 sis unichrome
|
||||
else ifeq ($(DEB_HOST_ARCH), sparc)
|
||||
else ifeq ($(DEB_HOST_ARCH), sparc)
|
||||
DRI_DRIVERS += ffb
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
confflags-dri = \
|
||||
|
||||
1
debian/watch
vendored
1
debian/watch
vendored
@@ -1,2 +1,3 @@
|
||||
version=3
|
||||
opts="uversionmangle=s/-rc/~rc/" \
|
||||
http://sf.net/mesa3d/MesaLib-(.*)\.tar\.gz
|
||||
|
||||
@@ -16,7 +16,7 @@ Status
|
||||
|
||||
Version
|
||||
|
||||
Last Modified Date: 8 June 2000
|
||||
Last Modified Date: 12 January 2009
|
||||
|
||||
Number
|
||||
|
||||
@@ -69,6 +69,12 @@ Additions to Chapter 3 of the GLX 1.3 Specification (Functions and Errors)
|
||||
<width> and <height> indicate the size in pixels. Coordinate (0,0)
|
||||
corresponds to the lower-left pixel of the window, like glReadPixels.
|
||||
|
||||
If dpy and drawable are the display and drawable for the calling
|
||||
thread's current context, glXCopySubBufferMESA performs an
|
||||
implicit glFlush before it returns. Subsequent OpenGL commands
|
||||
may be issued immediately after calling glXCopySubBufferMESA, but
|
||||
are not executed until the copy is completed.
|
||||
|
||||
GLX Protocol
|
||||
|
||||
None at this time. The extension is implemented in terms of ordinary
|
||||
@@ -84,5 +90,7 @@ New State
|
||||
|
||||
Revision History
|
||||
|
||||
8 June 2000 - initial specification
|
||||
12 January 2009 Ian Romanick - Added language about implicit flush
|
||||
and command completion.
|
||||
8 June 2000 Brian Paul - initial specification
|
||||
|
||||
|
||||
@@ -1,230 +0,0 @@
|
||||
Name
|
||||
|
||||
MESA_packed_depth_stencil
|
||||
|
||||
Name Strings
|
||||
|
||||
GL_MESA_packed_depth_stencil
|
||||
|
||||
Contact
|
||||
|
||||
Keith Whitwell, VA Linux Systems Inc. (keithw 'at' valinux.com)
|
||||
Brian Paul, VA Linux Systems Inc. (brianp 'at' valinux.com)
|
||||
|
||||
Status
|
||||
|
||||
Obsolete.
|
||||
|
||||
Version
|
||||
|
||||
|
||||
Number
|
||||
|
||||
???
|
||||
|
||||
Dependencies
|
||||
|
||||
EXT_abgr affects the definition of this extension
|
||||
SGIS_texture4D affects the definition of this extension
|
||||
EXT_cmyka affects the definition of this extension
|
||||
ARB_packed_pixels affects the definition of this extension
|
||||
|
||||
Overview
|
||||
|
||||
Provides a mechanism for DrawPixels and ReadPixels to efficiently
|
||||
transfer depth and stencil image data. Specifically, we defined new
|
||||
packed pixel formats and types which pack both stencil and depth
|
||||
into one value.
|
||||
|
||||
Issues:
|
||||
|
||||
1. Is this the right way to distinguish between 24/8 and 8/24
|
||||
pixel formats? Should we instead provide both:
|
||||
|
||||
GL_DEPTH_STENCIL_MESA
|
||||
GL_STENCIL_DEPTH_MESA
|
||||
|
||||
And perhaps just use GL_UNSIGNED_INT, GL_UNSIGNED_SHORT ?
|
||||
|
||||
2. If not, is it correct to use _REV to indicate that stencil
|
||||
preceeds depth in the 1_15 and 8_24 formats?
|
||||
|
||||
3. Do we really want the GL_UNSIGNED_SHORT formats?
|
||||
|
||||
|
||||
New Procedures and Functions
|
||||
|
||||
None.
|
||||
|
||||
New Tokens
|
||||
|
||||
Accepted by the <format> parameter of ReadPixels and DrawPixels:
|
||||
|
||||
GL_DEPTH_STENCIL_MESA 0x8750
|
||||
|
||||
Accepted by the <type> parameter of ReadPixels and DrawPixels:
|
||||
|
||||
GL_UNSIGNED_INT_24_8_MESA 0x8751
|
||||
GL_UNSIGNED_INT_8_24_REV_MESA 0x8752
|
||||
GL_UNSIGNED_SHORT_15_1_MESA 0x8753
|
||||
GL_UNSIGNED_SHORT_1_15_REV_MESA 0x8754
|
||||
|
||||
Additions to Chapter 2 of the 1.1 Specification (OpenGL Operation)
|
||||
|
||||
None
|
||||
|
||||
Additions to Chapter 3 of the 1.1 Specification (Rasterization)
|
||||
|
||||
One entry is added to table 3.5 (DrawPixels and ReadPixels formats).
|
||||
The new table is:
|
||||
|
||||
Target
|
||||
Format Name Buffer Element Meaning and Order
|
||||
----------- ------ -------------------------
|
||||
COLOR_INDEX Color Color index
|
||||
STENCIL_INDEX Stencil Stencil index
|
||||
DEPTH_COMPONENT Depth Depth component
|
||||
RED Color R component
|
||||
GREEN Color G component
|
||||
BLUE Color B component
|
||||
ALPHA Color A component
|
||||
RGB Color R, G, B components
|
||||
RGBA Color R, G, B, A components
|
||||
BGRA Color B, G, R, A components
|
||||
ABGR_EXT Color A, B, G, R components
|
||||
CMYK_EXT Color Cyan, Magenta, Yellow, Black components
|
||||
CMYKA_EXT Color Cyan, Magenta, Yellow, Black, A components
|
||||
LUMINANCE Color Luminance component
|
||||
LUMINANCE_ALPHA Color Luminance, A components
|
||||
DEPTH_STENCIL Depth, Depth component, stencil index.
|
||||
Stencil
|
||||
|
||||
Table 3.5: DrawPixels and ReadPixels formats. The third column
|
||||
gives a description of and the number and order of elements in a
|
||||
group.
|
||||
|
||||
Add to the description of packed pixel formats:
|
||||
|
||||
<type> Parameter Data of Matching
|
||||
Token Name Type Elements Pixel Formats
|
||||
---------------- ---- -------- -------------
|
||||
|
||||
UNSIGNED_BYTE_3_3_2 ubyte 3 RGB
|
||||
UNSIGNED_BYTE_2_3_3_REV ubyte 3 RGB
|
||||
UNSIGNED_SHORT_5_6_5 ushort 3 RGB
|
||||
UNSIGNED_SHORT_5_6_5_REV ushort 3 RGB
|
||||
UNSIGNED_SHORT_4_4_4_4 ushort 4 RGBA,BGRA,ABGR_EXT,CMYK_EXT
|
||||
UNSIGNED_SHORT_4_4_4_4_REV ushort 4 RGBA,BGRA
|
||||
UNSIGNED_SHORT_5_5_5_1 ushort 4 RGBA,BGRA,ABGR_EXT,CMYK_EXT
|
||||
UNSIGNED_SHORT_1_5_5_5_REV ushort 4 RGBA,BGRA
|
||||
UNSIGNED_INT_8_8_8_8 uint 4 RGBA,BGRA,ABGR_EXT,CMYK_EXT
|
||||
UNSIGNED_INT_8_8_8_8_REV uint 4 RGBA,BGRA
|
||||
UNSIGNED_INT_10_10_10_2 uint 4 RGBA,BGRA,ABGR_EXT,CMYK_EXT
|
||||
UNSIGNED_INT_2_10_10_10_REV uint 4 RGBA,BGRA
|
||||
UNSIGNED_SHORT_15_1_MESA ushort 2 DEPTH_STENCIL_MESA
|
||||
UNSIGNED_SHORT_1_15_REV_MESA ushort 2 DEPTH_STENCIL_MESA
|
||||
UNSIGNED_SHORT_24_8_MESA ushort 2 DEPTH_STENCIL_MESA
|
||||
UNSIGNED_SHORT_8_24_REV_MESA ushort 2 DEPTH_STENCIL_MESA
|
||||
|
||||
UNSIGNED_INT_8_24:
|
||||
|
||||
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
+-----------------------+-----------------------------------------------------------------------+
|
||||
| | |
|
||||
+-----------------------+-----------------------------------------------------------------------+
|
||||
|
||||
first second
|
||||
element element
|
||||
|
||||
|
||||
UNSIGNED_INT_24_8:
|
||||
|
||||
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
+----------------------------------------------------------------------+------------------------+
|
||||
| | |
|
||||
+----------------------------------------------------------------------+------------------------+
|
||||
|
||||
first second
|
||||
element element
|
||||
|
||||
UNSIGNED_SHORT_15_1:
|
||||
|
||||
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
+-----------------------------------------------------------+---+
|
||||
| | |
|
||||
+-----------------------------------------------------------+---+
|
||||
|
||||
first second
|
||||
element element
|
||||
|
||||
|
||||
UNSIGNED_SHORT_1_15_REV:
|
||||
|
||||
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
+---+-----------------------------------------------------------+
|
||||
| | |
|
||||
+---+-----------------------------------------------------------+
|
||||
|
||||
second first
|
||||
element element
|
||||
|
||||
The assignment of elements to fields in the packed pixel is as
|
||||
described in the table below:
|
||||
|
||||
First Second Third Fourth
|
||||
Format Element Element Element Element
|
||||
------ ------- ------- ------- -------
|
||||
RGB red green blue
|
||||
RGBA red green blue alpha
|
||||
BGRA blue green red alpha
|
||||
ABGR_EXT alpha blue green red
|
||||
CMYK_EXT cyan magenta yellow black
|
||||
DEPTH_STENCIL_MESA depth stencil
|
||||
|
||||
Additions to Chapter 4 of the 1.1 Specification (Per-Fragment Operations
|
||||
and the Frame Buffer)
|
||||
|
||||
The new format is added to the discussion of Obtaining Pixels from the
|
||||
Framebuffer. It should read " If the <format> is one of RED, GREEN,
|
||||
BLUE, ALPHA, RGB, RGBA, ABGR_EXT, LUMINANCE, or LUMINANCE_ALPHA, and
|
||||
the GL is in color index mode, then the color index is obtained."
|
||||
|
||||
The new format is added to the discussion of Index Lookup. It should
|
||||
read "If <format> is one of RED, GREEN, BLUE, ALPHA, RGB, RGBA,
|
||||
ABGR_EXT, LUMINANCE, or LUMINANCE_ALPHA, then the index is used to
|
||||
reference 4 tables of color components: PIXEL_MAP_I_TO_R,
|
||||
PIXEL_MAP_I_TO_G, PIXEL_MAP_I_TO_B, and PIXEL_MAP_I_TO_A."
|
||||
|
||||
|
||||
Additions to Chapter 5 of the 1.1 Specification (Special Functions)
|
||||
|
||||
None
|
||||
|
||||
Additions to Chapter 6 of the 1.1 Specification (State and State Requests)
|
||||
|
||||
None
|
||||
|
||||
Additions to the GLX Specification
|
||||
|
||||
None
|
||||
|
||||
GLX Protocol
|
||||
|
||||
TBD
|
||||
|
||||
Errors
|
||||
|
||||
None
|
||||
|
||||
New State
|
||||
|
||||
None
|
||||
|
||||
Revision History
|
||||
|
||||
Version 1.0 - 23 Sep 2000
|
||||
Keith's original version.
|
||||
|
||||
Version 1.1 - 3 Nov 2000
|
||||
Brian's edits, assigned values to new enums.
|
||||
|
||||
@@ -1,356 +0,0 @@
|
||||
Name
|
||||
|
||||
MESA_program_debug
|
||||
|
||||
Name Strings
|
||||
|
||||
GL_MESA_program_debug
|
||||
|
||||
Contact
|
||||
|
||||
Brian Paul (brian.paul 'at' tungstengraphics.com)
|
||||
|
||||
Status
|
||||
|
||||
XXX - Not complete yet!!!
|
||||
|
||||
Version
|
||||
|
||||
Last Modified Date: July 20, 2003
|
||||
Author Revision: 1.0
|
||||
|
||||
Number
|
||||
|
||||
TBD
|
||||
|
||||
Dependencies
|
||||
|
||||
OpenGL 1.4 is required
|
||||
The extension is written against the OpenGL 1.4 specification.
|
||||
ARB_vertex_program or ARB_fragment_program or NV_vertex_program
|
||||
or NV_fragment_program is required.
|
||||
|
||||
Overview
|
||||
|
||||
The extension provides facilities for implementing debuggers for
|
||||
vertex and fragment programs.
|
||||
|
||||
The concept is that vertex and fragment program debuggers will be
|
||||
implemented outside of the GL as a utility package. This extension
|
||||
only provides the minimal hooks required to implement a debugger.
|
||||
|
||||
There are facilities to do the following:
|
||||
1. Have the GL call a user-specified function prior to executing
|
||||
each vertex or fragment instruction.
|
||||
2. Query the current program string's execution position.
|
||||
3. Query the current values of intermediate program values.
|
||||
|
||||
The main feature is the ProgramCallbackMESA function. It allows the
|
||||
user to register a callback function with the GL. The callback will
|
||||
be called prior to executing each vertex or fragment program instruction.
|
||||
|
||||
From within the callback, the user may issue Get* commands to
|
||||
query current GL state. The GetProgramRegisterfvMESA function allows
|
||||
current program values to be queried (such as temporaries, input
|
||||
attributes, and result registers).
|
||||
|
||||
There are flags for enabling/disabling the program callbacks.
|
||||
|
||||
The current execution position (as an offset from the start of the
|
||||
program string) can be queried with
|
||||
GetIntegerv(GL_FRAGMENT_PROGRAM_POSITION_MESA, &pos) or
|
||||
GetIntegerv(GL_VERTEX_PROGRAM_POSITION_MESA, &pos).
|
||||
|
||||
|
||||
IP Status
|
||||
|
||||
None
|
||||
|
||||
Issues
|
||||
|
||||
1. Is this the right model for a debugger?
|
||||
|
||||
It seems prudent to minimize the scope of this extension and leave
|
||||
it up to the developer (or developer community) to write debuggers
|
||||
that layer on top of this extension.
|
||||
|
||||
If the debugger were fully implemented within the GL it's not
|
||||
clear how terminal and GUI-based interfaces would work, for
|
||||
example.
|
||||
|
||||
2. There aren't any other extensions that register callbacks with
|
||||
the GL. Isn't there another solution?
|
||||
|
||||
If we want to be able to single-step through vertex/fragment
|
||||
programs I don't see another way to do it.
|
||||
|
||||
3. How do we prevent the user from doing something crazy in the
|
||||
callback function, like trying to call glBegin (leading to
|
||||
recursion)?
|
||||
|
||||
The rule is that the callback function can only issue glGet*()
|
||||
functions and no other GL commands. It could be difficult to
|
||||
enforce this, however. Therefore, calling any non-get GL
|
||||
command from within the callback will result in undefined
|
||||
results.
|
||||
|
||||
4. Is this extension amenable to hardware implementation?
|
||||
|
||||
Hopefully, but if not, the GL implementation will have to fall
|
||||
back to a software path when debugging. This may be acceptable
|
||||
for debugging.
|
||||
|
||||
5. What's the <data> parameter to ProgramCallbackMESA for?
|
||||
|
||||
It's a common programming practice to associate a user-supplied
|
||||
value with callback functions.
|
||||
|
||||
6. Debuggers often allow one to modify intermediate program values,
|
||||
then continue. Does this extension support that?
|
||||
|
||||
No.
|
||||
|
||||
|
||||
New Procedures and Functions (and datatypes)
|
||||
|
||||
typedef void (*programcallbackMESA)(enum target, void *data)
|
||||
|
||||
void ProgramCallbackMESA(enum target, programcallbackMESA callback,
|
||||
void *data)
|
||||
|
||||
void GetProgramRegisterfvMESA(enum target, sizei len,
|
||||
const ubyte *registerName, float *v)
|
||||
|
||||
New Tokens
|
||||
|
||||
Accepted by the <cap> parameter of Enable, Disable, IsEnabled,
|
||||
GetBooleanv, GetDoublev, GetFloatv and GetIntegerv:
|
||||
|
||||
FRAGMENT_PROGRAM_CALLBACK_MESA 0x8bb1
|
||||
VERTEX_PROGRAM_CALLBACK_MESA 0x8bb4
|
||||
|
||||
Accepted by the <pname> parameter GetBooleanv, GetDoublev,
|
||||
GetFloatv and GetIntegerv:
|
||||
|
||||
FRAGMENT_PROGRAM_POSITION_MESA 0x8bb0
|
||||
VERTEX_PROGRAM_POSITION_MESA 0x8bb4
|
||||
|
||||
Accepted by the <pname> parameter of GetPointerv:
|
||||
|
||||
FRAGMENT_PROGRAM_CALLBACK_FUNC_MESA 0x8bb2
|
||||
FRAGMENT_PROGRAM_CALLBACK_DATA_MESA 0x8bb3
|
||||
VERTEX_PROGRAM_CALLBACK_FUNC_MESA 0x8bb6
|
||||
VERTEX_PROGRAM_CALLBACK_DATA_MESA 0x8bb7
|
||||
|
||||
Additions to Chapter 2 of the OpenGL 1.4 Specification (OpenGL Operation)
|
||||
|
||||
None.
|
||||
|
||||
Additions to Chapter 3 of the OpenGL 1.4 Specification (Rasterization)
|
||||
|
||||
None.
|
||||
|
||||
Additions to Chapter 4 of the OpenGL 1.4 Specification (Per-Fragment
|
||||
Operations and the Frame Buffer)
|
||||
|
||||
None.
|
||||
|
||||
Additions to Chapter 5 of the OpenGL 1.4 Specification (Special Functions)
|
||||
|
||||
In section 5.4 "Display Lists", page 202, add the following command
|
||||
to the list of those that are not compiled into display lists:
|
||||
|
||||
ProgramCallbackMESA.
|
||||
|
||||
|
||||
Add a new section 5.7 "Callback Functions"
|
||||
|
||||
The function
|
||||
|
||||
void ProgramCallbackMESA(enum target, programcallbackMESA callback,
|
||||
void *data)
|
||||
|
||||
registers a user-defined callback function with the GL. <target>
|
||||
may be FRAGMENT_PROGRAM_ARB or VERTEX_PROGRAM_ARB. The enabled
|
||||
callback functions registered with these targets will be called
|
||||
prior to executing each instruction in the current fragment or
|
||||
vertex program, respectively. The callbacks are enabled and
|
||||
disabled by calling Enable or Disable with <cap>
|
||||
FRAGMENT_PROGRAM_ARB or VERTEX_PROGRAM_ARB.
|
||||
|
||||
The callback function's signature must match the typedef
|
||||
|
||||
typedef void (*programcallbackMESA)(enum target, void *data)
|
||||
|
||||
When the callback function is called, <target> will either be
|
||||
FRAGMENT_PROGRAM_ARB or VERTEX_PROGRAM_ARB to indicate which
|
||||
program is currently executing and <data> will be the value
|
||||
specified when ProgramCallbackMESA was called.
|
||||
|
||||
From within the callback function, only the following GL commands
|
||||
may be called:
|
||||
|
||||
GetBooleanv
|
||||
GetDoublev
|
||||
GetFloatv
|
||||
GetIntegerv
|
||||
GetProgramLocalParameter
|
||||
GetProgramEnvParameter
|
||||
GetProgramRegisterfvMESA
|
||||
GetProgramivARB
|
||||
GetProgramStringARB
|
||||
GetError
|
||||
|
||||
Calling any other command from within the callback results in
|
||||
undefined behaviour.
|
||||
|
||||
|
||||
Additions to Chapter 6 of the OpenGL 1.4 Specification (State and
|
||||
State Requests)
|
||||
|
||||
Add a new section 6.1.3 "Program Value Queries":
|
||||
|
||||
The command
|
||||
|
||||
void GetProgramRegisterfvMESA(enum target, sizei len,
|
||||
const ubyte *registerName,
|
||||
float *v)
|
||||
|
||||
Is used to query the value of program variables and registers
|
||||
during program execution. GetProgramRegisterfvMESA may only be
|
||||
called from within a callback function registered with
|
||||
ProgramCallbackMESA.
|
||||
|
||||
<registerName> and <len> specify the name a variable, input
|
||||
attribute, temporary, or result register in the program string.
|
||||
The current value of the named variable is returned as four
|
||||
values in <v>. If <name> doesn't exist in the program string,
|
||||
the error INVALID_OPERATION is generated.
|
||||
|
||||
Additions to Appendix A of the OpenGL 1.4 Specification (Invariance)
|
||||
|
||||
None.
|
||||
|
||||
Additions to the AGL/GLX/WGL Specifications
|
||||
|
||||
None.
|
||||
|
||||
GLX Protocol
|
||||
|
||||
XXX TBD
|
||||
|
||||
Dependencies on NV_vertex_program and NV_fragment_program
|
||||
|
||||
If NV_vertex_program and/or NV_fragment_program are supported,
|
||||
vertex and/or fragment programs defined by those extensions may
|
||||
be debugged as well. Register queries will use the syntax used
|
||||
by those extensions (i.e. "v[X]" to query vertex attributes,
|
||||
"o[X]" for vertex outputs, etc.)
|
||||
|
||||
Errors
|
||||
|
||||
INVALID_OPERATION is generated if ProgramCallbackMESA is called
|
||||
between Begin and End.
|
||||
|
||||
INVALID_ENUM is generated by ProgramCallbackMESA if <target> is not
|
||||
a supported vertex or fragment program type.
|
||||
|
||||
Note: INVALID_OPERAION IS NOT generated by GetProgramRegisterfvMESA,
|
||||
GetBooleanv, GetDoublev, GetFloatv, or GetIntegerv if called between
|
||||
Begin and End when a vertex or fragment program is currently executing.
|
||||
|
||||
INVALID_ENUM is generated by ProgramCallbackMESA,
|
||||
GetProgramRegisterfvMESA if <target> is not a program target supported
|
||||
by ARB_vertex_program, ARB_fragment_program (or NV_vertex_program or
|
||||
NV_fragment_program).
|
||||
|
||||
INVALID_VALUE is generated by GetProgramRegisterfvMESA if <registerName>
|
||||
does not name a known program register or variable.
|
||||
|
||||
INVALID_OPERATION is generated by GetProgramRegisterfvMESA when a
|
||||
register query is attempted for a program target that's not currently
|
||||
being executed.
|
||||
|
||||
|
||||
New State
|
||||
|
||||
XXX finish
|
||||
|
||||
(table 6.N, p. ###)
|
||||
Initial
|
||||
Get Value Type Get Command Value Description Sec. Attribute
|
||||
--------- ---- ----------- ----- ----------- ---- ---------
|
||||
FRAGMENT_PROGRAM_CALLBACK_MESA B IsEnabled FALSE XXX XXX enable
|
||||
VERTEX_PROGRAM_CALLBACK_MESA B IsEnabled FALSE XXX XXX enable
|
||||
FRAGMENT_PROGRAM_POSITION_MESA Z+ GetIntegerv -1 XXX XXX -
|
||||
VERTEX_PROGRAM_POSITION_MESA Z+ GetIntegerv -1 XXX XXX -
|
||||
FRAGMENT_PROGRAM_CALLBACK_FUNC_MESA P GetPointerv NULL XXX XXX -
|
||||
VERTEX_PROGRAM_CALLBACK_FUNC_MESA P GetPointerv NULL XXX XXX -
|
||||
FRAGMENT_PROGRAM_CALLBACK_DATA_MESA P GetPointerv NULL XXX XXX -
|
||||
VERTEX_PROGRAM_CALLBACK_DATA_MESA P GetPointerv NULL XXX XXX -
|
||||
|
||||
XXX more?
|
||||
|
||||
New Implementation Dependent State
|
||||
|
||||
None.
|
||||
|
||||
Revision History
|
||||
|
||||
8 July 2003
|
||||
Initial draft. (Brian Paul)
|
||||
11 July 2003
|
||||
Second draft. (Brian Paul)
|
||||
20 July 2003
|
||||
Third draft. Lots of fundamental changes. (Brian Paul)
|
||||
23 July 2003
|
||||
Added chapter 5 and 6 spec language. (Brian Paul)
|
||||
|
||||
Example Usage
|
||||
|
||||
The following is a very simple example of how this extension may
|
||||
be used to print the values of R0, R1, R2 and R3 while executing
|
||||
vertex programs.
|
||||
|
||||
|
||||
/* This is called by the GL when the vertex program is executing.
|
||||
* We can only make glGet* calls from within this function!
|
||||
*/
|
||||
void DebugCallback(GLenum target, GLvoid *data)
|
||||
{
|
||||
GLint pos;
|
||||
GLuint i;
|
||||
|
||||
/* Get PC and current instruction string */
|
||||
glGetIntegerv(GL_VERTEX_PROGRAM_POSITION_ARB, &pos);
|
||||
|
||||
printf("Current position: %d\n", pos);
|
||||
|
||||
printf("Current temporary registers:\n");
|
||||
for (i = 0; i < 4; i++) {
|
||||
GLfloat v[4];
|
||||
char s[10];
|
||||
sprintf(s, "R%d", i);
|
||||
glGetProgramRegisterfvMESA(GL_VERTEX_PROGRAM_ARB, strlen(s), s, v);
|
||||
printf("R%d = %g, %g, %g, %g\n", i, v[0], v[1], v[2], v[3]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* elsewhere...
|
||||
*/
|
||||
|
||||
/* Register our debugger callback function */
|
||||
glProgramCallbackMESA(GL_VERTEX_PROGRAM_ARB, DebugCallback, NULL);
|
||||
glEnable(GL_VERTEX_PROGRAM_CALLBACK_MESA);
|
||||
|
||||
/* define/bind a vertex program */
|
||||
|
||||
glEnable(GL_VERTEX_PROGRAM);
|
||||
|
||||
/* render something */
|
||||
glBegin(GL_POINTS);
|
||||
glVertex2f(0, 0);
|
||||
glEnd();
|
||||
|
||||
@@ -1,190 +0,0 @@
|
||||
Name
|
||||
|
||||
MESA_sprite_point
|
||||
|
||||
Name Strings
|
||||
|
||||
GL_MESA_sprite_point
|
||||
|
||||
Contact
|
||||
|
||||
Brian Paul, VA Linux Systems Inc. (brianp 'at' valinux.com)
|
||||
|
||||
Status
|
||||
|
||||
Obsolete - see GL_ARB_point_sprite.
|
||||
|
||||
Version
|
||||
|
||||
|
||||
Number
|
||||
|
||||
???
|
||||
|
||||
Dependencies
|
||||
|
||||
GL_EXT_point_parameters effects the definition of this extension
|
||||
GL_ARB_multitexture effects the definition of this extension
|
||||
|
||||
Overview
|
||||
|
||||
This extension modifies the way in which points are rendered,
|
||||
specifically when they're textured. When SPRITE_POINT_MESA is enabled
|
||||
a point is rendered as if it were a quadrilateral with unique texture
|
||||
coordinates at each vertex. This extension effectively turns points
|
||||
into sprites which may be rendered more easily and quickly than using
|
||||
conventional textured quadrilaterals.
|
||||
|
||||
When using point size > 1 or attenuated points this extension is an
|
||||
effective way to render many small sprite images for particle systems
|
||||
or other effects.
|
||||
|
||||
Issues:
|
||||
|
||||
1. How are the texture coordinates computed?
|
||||
|
||||
The lower-left corner has texture coordinate (0,0,r,q).
|
||||
The lower-right, (1,0,r,q). The upper-right, (1,1,r,q).
|
||||
The upper-left, (0,1,r,q).
|
||||
|
||||
2. What about texgen and texture matrices?
|
||||
|
||||
Texgen and the texture matrix have no effect on the point's s and t
|
||||
texture coordinates. The r and q coordinates may have been computed
|
||||
by texgen or the texture matrix. Note that with a 3D texture and/or
|
||||
texgen that the r coordinate could be used to select a slice in the
|
||||
3D texture.
|
||||
|
||||
3. What about point smoothing?
|
||||
|
||||
When point smoothing is enabled, a triangle fan could be rendered
|
||||
to approximate a circular point. This could be problematic to
|
||||
define and implement so POINT_SMOOTH is ignored when drawing sprite
|
||||
points.
|
||||
|
||||
Smoothed points can be approximated by using an appropriate texture
|
||||
images, alpha testing and blending.
|
||||
|
||||
POLYGON_SMOOTH does effect the rendering of the quadrilateral, however.
|
||||
|
||||
4. What about sprite rotation?
|
||||
|
||||
There is none. Sprite points are always rendered as window-aligned
|
||||
squares. One could define rotated texture images if desired. A 3D
|
||||
texture and appropriate texture r coordinates could be used to
|
||||
effectively specify image rotation per point.
|
||||
|
||||
5. What about POLYGON_MODE?
|
||||
|
||||
POLYGON_MODE does not effect the rasterization of the quadrilateral.
|
||||
|
||||
6. What about POLYGON_CULL?
|
||||
|
||||
TBD. Polygon culling is normally specified and implemented in the
|
||||
transformation stage of OpenGL. However, some rasterization hardware
|
||||
implements it later during triangle setup.
|
||||
|
||||
Polygon culling wouldn't be useful for sprite points since the
|
||||
quadrilaterals are always defined in counter-clockwise order in
|
||||
window space. For that reason, polygon culling should probably be
|
||||
ignored.
|
||||
|
||||
7. Should sprite points be alpha-attenuated if their size is below the
|
||||
point parameter's threshold size?
|
||||
|
||||
8. Should there be an advertisized maximum sprite point size?
|
||||
|
||||
No. Since we're rendering the point as a quadrilateral there's no
|
||||
need to limit the size.
|
||||
|
||||
|
||||
New Procedures and Functions
|
||||
|
||||
None.
|
||||
|
||||
New Tokens
|
||||
|
||||
Accepted by the <pname> parameter of Enable, Disable, IsEnabled,
|
||||
GetIntegerv, GetBooleanv, GetFloatv and GetDoublev:
|
||||
|
||||
SPRITE_POINT_MESA 0x????
|
||||
MAX_SPRITE_POINT_SIZE_MESA 0x???? (need this?)
|
||||
|
||||
Additions to Chapter 2 of the 1.1 Specification (OpenGL Operation)
|
||||
|
||||
None
|
||||
|
||||
Additions to Chapter 3 of the 1.1 Specification (Rasterization)
|
||||
|
||||
Section ???.
|
||||
|
||||
When SPRITE_POINT_MESA is enabled points are rasterized as screen-
|
||||
aligned quadrilaterals. If the four vertices of the quadrilateral
|
||||
are labeled A, B, C, and D, starting at the lower-left corner and moving
|
||||
counter-clockwise around the quadrilateral, then the vertex and
|
||||
texture coordinates are computed as follows:
|
||||
|
||||
vertex window coordinate texture coordinate
|
||||
A (x-r, y-r, z, w) (0, 0, r, q)
|
||||
B (x+r, y-r, z, w) (1, 0, r, q)
|
||||
C (x+r, y+r, z, w) (1, 1, r, q)
|
||||
D (x-r, y+r, z, w) (0, 1, r, q)
|
||||
|
||||
where x, y, z, w are the point's window coordinates, r and q are the
|
||||
point's 3rd and 4th texture coordinates and r is half the point's
|
||||
size. The other vertex attributes (such as the color and fog coordinate)
|
||||
are simply duplicated from the original point vertex.
|
||||
|
||||
Point size may either be specified with PointSize or computed
|
||||
according to the EXT_point_parameters extension.
|
||||
|
||||
The new texture coordinates are not effected by texgen or the texture
|
||||
matrix. Note, however, that the texture r and q coordinates are passed
|
||||
unchanged and may have been computed with texgen and/or the texture
|
||||
matrix.
|
||||
|
||||
If multiple texture units are present the same texture coordinate is
|
||||
used for all texture units.
|
||||
|
||||
The point is then rendered as if it were a quadrilateral using the
|
||||
normal point sampling rules. POLYGON_MODE does not effect the
|
||||
rasterization of the quadrilateral but POLYGON_SMOOTH does.
|
||||
|
||||
POINT_SMOOTH has no effect when SPRITE_POINT_MESA is enabled.
|
||||
|
||||
Additions to Chapter 4 of the 1.1 Specification (Per-Fragment Operations
|
||||
and the Frame Buffer)
|
||||
|
||||
None.
|
||||
|
||||
Additions to Chapter 5 of the 1.1 Specification (Special Functions)
|
||||
|
||||
None
|
||||
|
||||
Additions to Chapter 6 of the 1.1 Specification (State and State Requests)
|
||||
|
||||
None
|
||||
|
||||
Additions to the GLX Specification
|
||||
|
||||
None
|
||||
|
||||
GLX Protocol
|
||||
|
||||
TBD
|
||||
|
||||
Errors
|
||||
|
||||
None
|
||||
|
||||
New State
|
||||
|
||||
Add boolean variable SPRITE_POINT_MESA to the point attribute group.
|
||||
|
||||
Revision History
|
||||
|
||||
Version 1.0 - 4 Dec 2000
|
||||
Original draft.
|
||||
|
||||
|
||||
|
||||
@@ -1,359 +0,0 @@
|
||||
Name
|
||||
|
||||
MESA_trace
|
||||
|
||||
Name Strings
|
||||
|
||||
GL_MESA_trace
|
||||
|
||||
Contact
|
||||
|
||||
Bernd Kreimeier, Loki Entertainment, bk 'at' lokigames.com
|
||||
Brian Paul, VA Linux Systems, Inc., brianp 'at' valinux.com
|
||||
|
||||
Status
|
||||
|
||||
Obsolete.
|
||||
|
||||
Version
|
||||
|
||||
|
||||
Number
|
||||
|
||||
none yet
|
||||
|
||||
Dependencies
|
||||
|
||||
OpenGL 1.2 is required.
|
||||
The extension is written against the OpenGL 1.2 Specification
|
||||
|
||||
Overview
|
||||
|
||||
Provides the application with means to enable and disable logging
|
||||
of GL calls including parameters as readable text. The verbosity
|
||||
of the generated log can be controlled. The resulting logs are
|
||||
valid (but possibly incomplete) C code and can be compiled and
|
||||
linked for standalone test programs. The set of calls and the
|
||||
amount of static data that is logged can be controlled at runtime.
|
||||
The application can add comments and enable or disable tracing of GL
|
||||
operations at any time. The data flow from the application to GL
|
||||
and back is unaffected except for timing.
|
||||
|
||||
Application-side implementation of these features raises namespace
|
||||
and linkage issues. In the driver dispatch table a simple
|
||||
"chain of responsibility" pattern (aka "composable piepline")
|
||||
can be added.
|
||||
|
||||
IP Status
|
||||
|
||||
The extension spec is in the public domain. The current implementation
|
||||
in Mesa is covered by Mesa's XFree86-style copyright by the authors above.
|
||||
This extension is partially inspired by the Quake2 QGL wrapper.
|
||||
|
||||
Issues
|
||||
|
||||
|
||||
(1) Is this Extension obsolete because it can
|
||||
be implemented as a wrapper DLL?
|
||||
|
||||
RESOLVED: No. While certain operating systems (Win32) provide linkers
|
||||
that facilitate this kind of solution, other operating systems
|
||||
(Linux) do not support hierarchical linking, so a wrapper solution
|
||||
would result in symbol collisions.
|
||||
Further, IHV's might have builtin support for tracing GL execution
|
||||
that enjoys privileged access, or that they do not wish to separate
|
||||
the tracing code from their driver code base.
|
||||
|
||||
(2) Should the Trace API explicitely support the notion of "frames?
|
||||
This would require hooking into glXSwapBuffers calls as well.
|
||||
|
||||
RESOLVED: No. The application can use NewTraceMESA/EndTraceMESA
|
||||
and TraceComment along with external parsing tools to split the
|
||||
trace into frames, in whatever way considered adequate.
|
||||
|
||||
(2a) Should GLX calls be traced?
|
||||
|
||||
PBuffers and other render-to-texture solutions demonstrate that
|
||||
context level commands beyond SwapBuffers might have to be
|
||||
traced. The GL DLL exports the entry points, so this would not
|
||||
be out of the question.
|
||||
|
||||
(3) Should the specification mandate the actual output format?
|
||||
|
||||
RESOLVED: No. It is sufficient to guarantee that all data and commands
|
||||
will be traced as requested by Enable/DisableTraceMESA, in the order
|
||||
encountered. Whether the resulting trace is available as a readable
|
||||
text file, binary metafile, compilable source code, much less which
|
||||
indentation and formatting has been used, is up to the implementation.
|
||||
For the same reason this specification does not enforce or prohibit
|
||||
additional information added to the trace (statistics, profiling/timing,
|
||||
warnings on possible error conditions).
|
||||
|
||||
(4) Should the comment strings associated with names and pointer (ranges)
|
||||
be considered persistent state?
|
||||
|
||||
RESOLVED: No. The implementation is not forced to use this information
|
||||
on subsequent occurences of name/pointer, and is free to consider it
|
||||
transient state.
|
||||
|
||||
(5) Should comment commands be prohibited between Begin/End?
|
||||
|
||||
RESOLVED: Yes, with the exception of TraceCommentMESA. TraceCommentMESA
|
||||
is transient, the other commands might cause storage of persistent
|
||||
data in the context. There is no need to have the ability mark names
|
||||
or pointers between Begin and End.
|
||||
|
||||
|
||||
New Procedures and Functions
|
||||
|
||||
void NewTraceMESA( bitfield mask, const ubyte * traceName )
|
||||
|
||||
void EndTraceMESA( void )
|
||||
|
||||
void EnableTraceMESA( bitfield mask )
|
||||
|
||||
void DisableTraceMESA( bitfield mask )
|
||||
|
||||
void TraceAssertAttribMESA( bitfield attribMask )
|
||||
|
||||
void TraceCommentMESA( const ubyte* comment )
|
||||
|
||||
void TraceTextureMESA( uint name, const ubyte* comment )
|
||||
|
||||
void TraceListMESA( uint name, const ubyte* comment )
|
||||
|
||||
void TracePointerMESA( void* pointer, const ubyte* comment )
|
||||
|
||||
void TracePointerRangeMESA( const void* first,
|
||||
const void* last,
|
||||
const ubyte* comment )
|
||||
|
||||
New Tokens
|
||||
|
||||
Accepted by the <mask> parameter of EnableTrace and DisableTrace:
|
||||
|
||||
TRACE_ALL_BITS_MESA 0xFFFF
|
||||
TRACE_OPERATIONS_BIT_MESA 0x0001
|
||||
TRACE_PRIMITIVES_BIT_MESA 0x0002
|
||||
TRACE_ARRAYS_BIT_MESA 0x0004
|
||||
TRACE_TEXTURES_BIT_MESA 0x0008
|
||||
TRACE_PIXELS_BIT_MESA 0x0010
|
||||
TRACE_ERRORS_BIT_MESA 0x0020
|
||||
|
||||
Accepted by the <pname> parameter of GetIntegerv, GetBooleanv,
|
||||
GetFloatv, and GetDoublev:
|
||||
|
||||
TRACE_MASK_MESA 0x8755
|
||||
|
||||
Accepted by the <pname> parameter to GetString:
|
||||
|
||||
TRACE_NAME_MESA 0x8756
|
||||
|
||||
|
||||
Additions to Chapter 2 of the OpenGL 1.2.1 Specification (OpenGL Operation)
|
||||
|
||||
None.
|
||||
|
||||
Additions to Chapter 3 of the OpenGL 1.2.1 Specification (OpenGL Operation)
|
||||
|
||||
None.
|
||||
|
||||
Additions to Chapter 4 of the OpenGL 1.2.1 Specification (OpenGL Operation)
|
||||
|
||||
None.
|
||||
|
||||
Additions to Chapter 5 of the OpenGL 1.2.1 Specification (Special Functions)
|
||||
|
||||
Add a new section:
|
||||
|
||||
5.7 Tracing
|
||||
|
||||
The tracing facility is used to record the execution of a GL program
|
||||
to a human-readable log. The log appears as a sequence of GL commands
|
||||
using C syntax. The primary intention of tracing is to aid in program
|
||||
debugging.
|
||||
|
||||
A trace is started with the command
|
||||
|
||||
void NewTraceMESA( bitfield mask, const GLubyte * traceName )
|
||||
|
||||
<mask> may be any value accepted by PushAttrib and specifies a set of
|
||||
attribute groups. The state values included in those attribute groups
|
||||
is written to the trace as a sequence of GL commands.
|
||||
|
||||
<traceName> specifies a name or label for the trace. It is expected
|
||||
that <traceName> will be interpreted as a filename in most implementations.
|
||||
|
||||
A trace is ended by calling the command
|
||||
|
||||
void EndTraceMESA( void )
|
||||
|
||||
It is illegal to call NewTraceMESA or EndTraceMESA between Begin and End.
|
||||
|
||||
The commands
|
||||
|
||||
void EnableTraceMESA( bitfield mask )
|
||||
void DisableTraceMESA( bitfield mask )
|
||||
|
||||
enable or disable tracing of different classes of GL commands.
|
||||
<mask> may be the union of any of TRACE_OPERATIONS_BIT_MESA,
|
||||
TRACE_PRIMITIVES_BIT_MESA, TRACE_ARRAYS_BIT_MESA, TRACE_TEXTURES_BIT_MESA,
|
||||
and TRACE_PIXELS_BIT_MESA. The special token TRACE_ALL_BITS_MESA
|
||||
indicates all classes of commands are to be logged.
|
||||
|
||||
TRACE_OPERATIONS_BIT_MESA controls logging of all commands outside of
|
||||
Begin/End, including Begin/End.
|
||||
|
||||
TRACE_PRIMITIVES_BIT_MESA controls logging of all commands inside of
|
||||
Begin/End, including Begin/End.
|
||||
|
||||
TRACE_ARRAYS_BIT_MESA controls logging of VertexPointer, NormalPointer,
|
||||
ColorPointer, IndexPointer, TexCoordPointer and EdgeFlagPointer commands.
|
||||
|
||||
TRACE_TEXTURES_BIT_MESA controls logging of texture data dereferenced by
|
||||
TexImage1D, TexImage2D, TexImage3D, TexSubImage1D, TexSubImage2D, and
|
||||
TexSubImage3D commands.
|
||||
|
||||
TRACE_PIXELS_BIT_MESA controls logging of image data dereferenced by
|
||||
Bitmap and DrawPixels commands.
|
||||
|
||||
TRACE_ERRORS_BIT_MESA controls logging of all errors. If this bit is
|
||||
set, GetError will be executed whereever applicable, and the result will
|
||||
be added to the trace as a comment. The error returns are cached and
|
||||
returned to the application on its GetError calls. If the user does not
|
||||
wish the additional GetError calls to be performed, this bit should not
|
||||
be set.
|
||||
|
||||
The command
|
||||
|
||||
void TraceCommentMESA( const ubyte* comment )
|
||||
|
||||
immediately adds the <comment> string to the trace output, surrounded
|
||||
by C-style comment delimiters.
|
||||
|
||||
The commands
|
||||
|
||||
void TraceTextureMESA( uint name, const ubyte* comment )
|
||||
void TraceListMESA( uint name, const ubyte* comment )
|
||||
|
||||
associates <comment> with the texture object or display list specified
|
||||
by <name>. Logged commands which reference the named texture object or
|
||||
display list will be annotated with <comment>. If IsTexture(name) or
|
||||
IsList(name) fail (respectively) the command is quietly ignored.
|
||||
|
||||
The commands
|
||||
|
||||
void TracePointerMESA( void* pointer, const ubyte* comment )
|
||||
|
||||
void TracePointerRangeMESA( const void* first,
|
||||
const void* last,
|
||||
const ubyte* comment )
|
||||
|
||||
associate <comment> with the address specified by <pointer> or with
|
||||
a range of addresses specified by <first> through <last>.
|
||||
Any logged commands which reference <pointer> or an address between
|
||||
<first> and <last> will be annotated with <comment>.
|
||||
|
||||
The command
|
||||
|
||||
void TraceAssertAttribMESA( bitfield attribMask )
|
||||
|
||||
will add GL state queries and assertion statements to the log to
|
||||
confirm that the current state at the time TraceAssertAttrib is
|
||||
executed matches the current state when the trace log is executed
|
||||
in the future.
|
||||
|
||||
<attribMask> is any value accepted by PushAttrib and specifies
|
||||
the groups of state variables which are to be asserted.
|
||||
|
||||
The commands NewTraceMESA, EndTraceMESA, EnableTraceMESA, DisableTraceMESA,
|
||||
TraceAssertAttribMESA, TraceCommentMESA, TraceTextureMESA, TraceListMESA,
|
||||
TracePointerMESA and TracePointerRangeMESA are not compiled into display lists.
|
||||
|
||||
|
||||
Examples:
|
||||
|
||||
The command NewTraceMESA(DEPTH_BUFFER_BIT, "log") will query the state
|
||||
variables DEPTH_TEST, DEPTH_FUNC, DEPTH_WRITEMASK, and DEPTH_CLEAR_VALUE
|
||||
to get the values <test>, <func>, <mask>, and <clear> respectively.
|
||||
Statements equivalent to the following will then be logged:
|
||||
|
||||
glEnable(GL_DEPTH_TEST); (if <test> is true)
|
||||
glDisable(GL_DEPTH_TEST); (if <test> is false)
|
||||
glDepthFunc(<func>);
|
||||
glDepthMask(<mask>);
|
||||
glClearDepth(<clear>);
|
||||
|
||||
|
||||
The command TraceAssertAttribMESA(DEPTH_BUFFER_BIT) will query the state
|
||||
variables DEPTH_TEST, DEPTH_FUNC, DEPTH_WRITEMASK, and DEPTH_CLEAR_VALUE
|
||||
to get the values <test>, <func>, <mask>, and <clear> respectively.
|
||||
The resulting trace might then look will like this:
|
||||
|
||||
{
|
||||
GLboolean b;
|
||||
GLint i;
|
||||
GLfloat f;
|
||||
b = glIsEnabled(GL_DEPTH_TEST);
|
||||
assert(b == <test>);
|
||||
glGetIntegerv(GL_DEPTH_FUNC, &i);
|
||||
assert(i == <func>);
|
||||
glGetIntegerv(GL_DEPTH_MASK, &i);
|
||||
assert(i == <mask>);
|
||||
glGetFloatv(GL_DEPTH_CLEAR_VALUE, &f);
|
||||
assert(f == <clear>);
|
||||
}
|
||||
|
||||
|
||||
Additions to Chapter 6 of the OpenGL 1.2.1 Specification
|
||||
(State and State Requests)
|
||||
|
||||
Querying TRACE_MASK_MESA with GetIntegerv, GetFloatv, GetBooleanv or
|
||||
GetDoublev returns the current command class trace mask.
|
||||
|
||||
Querying TRACE_NAME_MESA with GetString returns the current trace name.
|
||||
|
||||
|
||||
Additions to Appendix A of the OpenGL 1.2.1 Specification (Invariance)
|
||||
|
||||
The MESA_trace extension can be used in a way that does not affect data
|
||||
flow from application to OpenGL, as well as data flow from OpenGL to
|
||||
application, except for timing, possible print I/O. TRACE_ERRORS_BIT_MESA
|
||||
will add additional GetError queries. Setting a trace mask with NewTraceMESA
|
||||
as well as use of TraceAssertAttribMESA might cause additional state queries.
|
||||
With the possible exception of performance, OpenGL rendering should not be
|
||||
affected at all by a properly chosen logging operation.
|
||||
|
||||
Additions to the AGL/GLX/WGL Specifications
|
||||
|
||||
None.
|
||||
|
||||
GLX Protocol
|
||||
|
||||
None. The logging operation is carried out client-side, by exporting
|
||||
entry points to the wrapper functions that execute the logging operation.
|
||||
|
||||
Errors
|
||||
|
||||
INVALID_OPERATION is generated if any trace command except TraceCommentMESA
|
||||
is called between Begin and End.
|
||||
|
||||
New State
|
||||
|
||||
The current trace name and current command class mask are stored
|
||||
per-context.
|
||||
|
||||
New Implementation Dependent State
|
||||
|
||||
None.
|
||||
|
||||
Revision History
|
||||
|
||||
* Revision 0.1 - Initial draft from template (bk000415)
|
||||
* Revision 0.2 - Draft (bk000906)
|
||||
* Revision 0.3 - Draft (bk000913)
|
||||
* Revision 0.4 - Reworked text, fixed typos (bp000914)
|
||||
* Revision 0.5 - Assigned final GLenum values (bp001103)
|
||||
* Revision 0.6 - TRACE_ERRORS_BIT_MESA (bk000916)
|
||||
* Revision 0.7 - Added MESA postfix (bk010126)
|
||||
|
||||
@@ -48,7 +48,7 @@ a:visited {
|
||||
<li><a href="lists.html" target="MainFrame">Mailing Lists</a>
|
||||
<li><a href="bugs.html" target="MainFrame">Bug Database</a>
|
||||
<li><a href="webmaster.html" target="MainFrame">Webmaster</a>
|
||||
<li><a href="http://dri.freedesktop.org/" target="MainFrame">Wiki</a>
|
||||
<li><a href="http://dri.freedesktop.org/" target="_parent">Mesa/DRI Wiki</a>
|
||||
</ul>
|
||||
|
||||
<b>User Topics</b>
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
<H1>Downloading</H1>
|
||||
|
||||
<p>
|
||||
Current development release: <b>7.3</b>
|
||||
Current stable release: <b>7.4</b>
|
||||
<br>
|
||||
Last stable release: <b>7.2</b>
|
||||
Last unstable/development release: <b>7.3</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
||||
@@ -29,7 +29,7 @@ Setting this variable automatically sets the MESA_TEX_PROG variable as well.
|
||||
|
||||
<p>
|
||||
The following are only applicable to the Xlib software driver.
|
||||
See <A HREF="README.X11">README.X11</A> for details.
|
||||
See the <A HREF="xlibdriver.html">Xlib software driver page</A> for details.
|
||||
</p>
|
||||
<ul>
|
||||
<li>MESA_RGB_VISUAL - specifies the X visual and depth for RGB mode
|
||||
|
||||
@@ -15,17 +15,40 @@ Here are some specific ideas and areas where help would be appreciated:
|
||||
|
||||
<ol>
|
||||
<li>
|
||||
Enable -Wstrict-aliasing=2 -fstrict-aliasing and track down aliasing
|
||||
<b>Driver patching and testing.</b>
|
||||
Patches are often posted to the mesa3d-dev mailing list, but aren't
|
||||
immediately checked into git because not enough people are testing them.
|
||||
Just applying patches, testing and reporting back is helpful.
|
||||
<li>
|
||||
<b>Driver debugging.</b>
|
||||
There are plenty of open bugs in the bug database.
|
||||
<li>
|
||||
<b>Remove aliasing warnings.</b>
|
||||
Enable gcc -Wstrict-aliasing=2 -fstrict-aliasing and track down aliasing
|
||||
issues in the code.
|
||||
<li>
|
||||
Windows 98/NT driver building, maintenance and testing
|
||||
<b>Windows driver building, testing and maintenance.</b>
|
||||
The Visual Studio project files aren't always updated in a timely manner
|
||||
when new source files are added or old ones are removed.
|
||||
Fixing these tends to delay new Mesa releases.
|
||||
<li>
|
||||
Maintenance and testing of lesser-used drivers, such as DOS/DJGPP, GGI, etc.
|
||||
<b>Maintenance and testing of lesser-used drivers.</b>
|
||||
Drivers such as DOS/DJGPP, GGI, etc that aren't being maintained are being
|
||||
deprecated starting in Mesa 7.3.
|
||||
<li>
|
||||
<b>Contribute more tests to
|
||||
<a href="http://glean.sourceforge.net/" target="_parent">glean</a>.</b>
|
||||
<li>
|
||||
<b>Automatic testing.
|
||||
</b>
|
||||
It would be great if someone would set up an automated system for grabbing
|
||||
the latest Mesa code and run tests (such as glean) then report issues to
|
||||
the mailing list.
|
||||
</ol>
|
||||
|
||||
|
||||
<p>
|
||||
If you want to help with Mesa, first join the Mesa developer's
|
||||
If you want to do something new in Mesa, first join the Mesa developer's
|
||||
mailing list.
|
||||
Then post a message to propose what you want to do, just to make sure
|
||||
there's no issues.
|
||||
|
||||
@@ -11,10 +11,18 @@
|
||||
<H1>News</H1>
|
||||
|
||||
|
||||
<h2>January TBD, 2009</h2>
|
||||
<h2>March ??, 2009</h2>
|
||||
<p>
|
||||
<a href="relnotes-7.4.html">Mesa 7.4</a> is released.
|
||||
This is a stable release fixing bugs since the 7.3 release.
|
||||
</p>
|
||||
|
||||
|
||||
<h2>January 22, 2009</h2>
|
||||
<p>
|
||||
<a href="relnotes-7.3.html">Mesa 7.3</a> is released.
|
||||
This is a new development release.
|
||||
Mesa 7.4 will follow and will have bug fixes relative to 7.3.
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
<body bgcolor="#eeeeee">
|
||||
|
||||
<H1>Mesa 7.3 Release Notes / TBD January 2009</H1>
|
||||
<H1>Mesa 7.3 Release Notes / 22 January 2009</H1>
|
||||
|
||||
<p>
|
||||
Mesa 7.3 is a new development release.
|
||||
@@ -22,13 +22,21 @@ Some drivers don't support all the features required in OpenGL 2.1.
|
||||
</p>
|
||||
<p>
|
||||
See the <a href="install.html">Compiling/Installing page</a> for prerequisites
|
||||
for DRI ardware acceleration.
|
||||
for DRI hardware acceleration.
|
||||
</p>
|
||||
|
||||
|
||||
<h2>MD5 checksums</h2>
|
||||
<pre>
|
||||
tbd
|
||||
8ed03191432b22d118d88d6db497f304 MesaLib-7.3.tar.gz
|
||||
781e7811a6ed5c97b2b8defefc8ffbc9 MesaLib-7.3.tar.bz2
|
||||
3ccba9a1734ed6d4b3389e1535d90fbf MesaLib-7.3.zip
|
||||
d312e974b31043b13b61bac5fbf00b87 MesaDemos-7.3.tar.gz
|
||||
3f0741394069bdf2329565a387396cda MesaDemos-7.3.tar.bz2
|
||||
4d0887fd4c66a824295cdd619f6d34cb MesaDemos-7.3.zip
|
||||
2d7661b66022bcb8878728f3d5bd33ab MesaGLUT-7.3.tar.gz
|
||||
abe8036a724c1a483bdad6b5a55ddc1a MesaGLUT-7.3.tar.bz2
|
||||
5f247819b47e2a7c62d07a6afe5262fb MesaGLUT-7.3.zip
|
||||
</pre>
|
||||
|
||||
|
||||
@@ -43,6 +51,12 @@ tbd
|
||||
<ul>
|
||||
<li>Assorted GLSL bug fixes
|
||||
<li>Assorted i965 driver fixes
|
||||
<li>Fix for wglCreateLayerContext() in WGL/Windows driver
|
||||
<li>Build fixes for OpenBSD and gcc 2.95
|
||||
<li>GLSL preprocessor handles #pragma now
|
||||
<li>Fix incorrect transformation of GL_SPOT_DIRECTION
|
||||
<li>Fixed several bugs (#18367 and #19625) in glXMakeContextCurrent()
|
||||
<li>Assorted Windows build fixes
|
||||
</ul>
|
||||
|
||||
<h2>Changes</h2>
|
||||
|
||||
80
docs/relnotes-7.4.html
Normal file
80
docs/relnotes-7.4.html
Normal file
@@ -0,0 +1,80 @@
|
||||
<HTML>
|
||||
|
||||
<TITLE>Mesa Release Notes</TITLE>
|
||||
|
||||
<head><link rel="stylesheet" type="text/css" href="mesa.css"></head>
|
||||
|
||||
<BODY>
|
||||
|
||||
<body bgcolor="#eeeeee">
|
||||
|
||||
<H1>Mesa 7.4 Release Notes / date TBD</H1>
|
||||
|
||||
<p>
|
||||
Mesa 7.4 is a stable development release fixing bugs since the 7.3 release.
|
||||
</p>
|
||||
<p>
|
||||
Mesa 7.4 implements the OpenGL 2.1 API, but the version reported by
|
||||
glGetString(GL_VERSION) depends on the particular driver being used.
|
||||
Some drivers don't support all the features required in OpenGL 2.1.
|
||||
</p>
|
||||
<p>
|
||||
See the <a href="install.html">Compiling/Installing page</a> for prerequisites
|
||||
for DRI ardware acceleration.
|
||||
</p>
|
||||
|
||||
|
||||
<h2>MD5 checksums</h2>
|
||||
<pre>
|
||||
tbd
|
||||
</pre>
|
||||
|
||||
|
||||
<h2>New features</h2>
|
||||
<ul>
|
||||
<li>Added MESA_GLX_FORCE_DIRECT env var for Xlib/software driver
|
||||
<li>GLSL version 1.20 is returnd by the GL_SHADING_LANGUAGE_VERSION query
|
||||
</ul>
|
||||
|
||||
|
||||
<h2>Bug fixes</h2>
|
||||
<ul>
|
||||
<li>glGetActiveUniform() returned wrong size for some array types
|
||||
<li>Fixed some error checking in glUniform()
|
||||
<li>Fixed a potential glTexImage('proxy target') segfault
|
||||
<li>Fixed bad reference counting for 1D/2D texture arrays
|
||||
<li>Fixed VBO + glPush/PopClientAttrib() bug #19835
|
||||
<li>Assorted i965 driver bug fixes
|
||||
<li>Fixed a Windows compilation failure in s_triangle.c
|
||||
<li>Fixed a GLSL array indexing bug
|
||||
<li>Fixes for building on Haiku
|
||||
</ul>
|
||||
|
||||
<h2>Changes</h2>
|
||||
<ul>
|
||||
<li>Updated GL/glxext.h to version 46
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
<h2>Driver Status</h2>
|
||||
|
||||
<pre>
|
||||
Driver Status
|
||||
---------------------- ----------------------
|
||||
DRI drivers varies with the driver
|
||||
XMesa/GLX (on Xlib) implements OpenGL 2.1
|
||||
OSMesa (off-screen) implements OpenGL 2.1
|
||||
Windows/Win32 implements OpenGL 2.1
|
||||
Glide (3dfx Voodoo1/2) implements OpenGL 1.3
|
||||
SVGA unsupported
|
||||
Wind River UGL unsupported
|
||||
DJGPP unsupported
|
||||
GGI unsupported
|
||||
BeOS unsupported
|
||||
Allegro unsupported
|
||||
D3D unsupported
|
||||
</pre>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -20,6 +20,7 @@ The release notes summarize what's new or changed in each Mesa release.
|
||||
</p>
|
||||
|
||||
<UL>
|
||||
<LI><A HREF="relnotes-7.4.html">7.4 release notes</A>
|
||||
<LI><A HREF="relnotes-7.3.html">7.3 release notes</A>
|
||||
<LI><A HREF="relnotes-7.2.html">7.2 release notes</A>
|
||||
<LI><A HREF="relnotes-7.1.html">7.1 release notes</A>
|
||||
|
||||
@@ -27,16 +27,27 @@ the Amiga, Apple Macintosh, BeOS, NeXT, OS/2, MS-DOS, VMS, Windows
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Details about particular drivers follows.
|
||||
Be warned that some drivers may be out of date and no longer function.
|
||||
Details about particular drivers follows:
|
||||
</p>
|
||||
|
||||
<UL>
|
||||
<LI><a href="xlibdriver.html">Xlib driver</a> for the X Window System
|
||||
<li><a href="http://dri.freedesktop.org/" target="_parent">
|
||||
DRI hardware drivers</a> for the X window system
|
||||
<li><a href="http://dri.freedesktop.org/" target="_parent"> DRI hardware
|
||||
drivers</a> for the X Window System
|
||||
<LI><a href="xlibdriver.html">Xlib software driver</a> for the X Window System
|
||||
and Unix-like operating systems
|
||||
<LI>Microsoft Windows <A HREF="README.WIN32">(README.WIN32)</A>
|
||||
<LI>DEC VMS <A HREF="README.VMS">(README.VMS)</A>
|
||||
</UL>
|
||||
|
||||
|
||||
<h2>Deprecated Systems</h2>
|
||||
|
||||
<p>
|
||||
These drivers have not been maintained and are being deprecated.
|
||||
They can be saved if someone steps up to help.
|
||||
</p>
|
||||
|
||||
<UL>
|
||||
<LI>3dfx/Glide <A HREF="README.3DFX">(README.3DFX)</A>
|
||||
<LI>GGI <A HREF="README.GGI">(README.GGI)</A>
|
||||
<LI>Amiga Amiwin <A HREF="README.AMIWIN">(README.AMIWIN)</A>
|
||||
@@ -49,6 +60,10 @@ DRI hardware drivers</a> for the X window system
|
||||
<LI>OpenStep <A HREF="README.OpenStep">(README.OpenStep)</A>
|
||||
<LI>OS/2 <A HREF="README.OS2">(README.OS2)</A>
|
||||
<LI>WindML <A HREF="README.WINDML">(README.WINDML)</A>
|
||||
</UL>
|
||||
|
||||
And for historical reference:
|
||||
<UL>
|
||||
<LI><a href="http://utah-glx.sourceforge.net/" target="_parent">Utah GLX drivers</a>
|
||||
</UL>
|
||||
|
||||
|
||||
@@ -169,6 +169,20 @@ the Gamma FAQ</a>
|
||||
</p>
|
||||
|
||||
|
||||
<H2>Direct Rendering Flag</H2>
|
||||
<p>
|
||||
Some applications won't run with indirect rendering contexts (which is
|
||||
what the Xlib driver supports).
|
||||
To force the glXIsDirect() query to return True, set the MESA_GLX_FORCE_DIRECT
|
||||
environment variable.
|
||||
For example:
|
||||
</p>
|
||||
<pre>
|
||||
$ export MESA_GLX_FORCE_DIRECT=1
|
||||
</pre>
|
||||
|
||||
|
||||
|
||||
<H2>Overlay Planes</H2>
|
||||
<p>
|
||||
Hardware overlay planes are supported by the Xlib driver. To
|
||||
@@ -268,6 +282,8 @@ This extension was added in Mesa 2.6
|
||||
MESA_BACK_BUFFER - specifies how to implement the back color buffer (X only)
|
||||
MESA_PRIVATE_CMAP - force aux/tk libraries to use private colormaps (X only)
|
||||
MESA_GAMMA - gamma correction coefficients (X only)
|
||||
MESA_GLX_FORCE_DIRECT - report that the driver is direct rendering, even
|
||||
though it's not.
|
||||
</pre>
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Mesa 3-D graphics library
|
||||
* Version: 6.5.1
|
||||
* Version: 7.4
|
||||
*
|
||||
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
|
||||
*
|
||||
|
||||
@@ -46,9 +46,9 @@ extern "C" {
|
||||
/*************************************************************/
|
||||
|
||||
/* Header file version number, required by OpenGL ABI for Linux */
|
||||
/* glext.h last updated 2008/11/14 */
|
||||
/* glext.h last updated 2009/03/04 */
|
||||
/* Current version at http://www.opengl.org/registry/ */
|
||||
#define GL_GLEXT_VERSION 44
|
||||
#define GL_GLEXT_VERSION 46
|
||||
|
||||
#ifndef GL_VERSION_1_2
|
||||
#define GL_UNSIGNED_BYTE_3_3_2 0x8032
|
||||
@@ -3862,6 +3862,22 @@ extern "C" {
|
||||
#define GL_TRANSFORM_FEEDBACK_BINDING_NV 0x8E25
|
||||
#endif
|
||||
|
||||
#ifndef GL_ATI_meminfo
|
||||
#define GL_VBO_FREE_MEMORY_ATI 0x87FB
|
||||
#define GL_TEXTURE_FREE_MEMORY_ATI 0x87FC
|
||||
#define GL_RENDERBUFFER_FREE_MEMORY_ATI 0x87FD
|
||||
#endif
|
||||
|
||||
#ifndef GL_AMD_performance_monitor
|
||||
#define GL_COUNTER_TYPE_AMD 0x8BC0
|
||||
#define GL_COUNTER_RANGE_AMD 0x8BC1
|
||||
#define GL_UNSIGNED_INT64_AMD 0x8BC2
|
||||
#define GL_PERCENTAGE_AMD 0x8BC3
|
||||
#define GL_PERFMON_RESULT_AVAILABLE_AMD 0x8BC4
|
||||
#define GL_PERFMON_RESULT_SIZE_AMD 0x8BC5
|
||||
#define GL_PERFMON_RESULT_AMD 0x8BC6
|
||||
#endif
|
||||
|
||||
|
||||
/*************************************************************/
|
||||
|
||||
@@ -5268,10 +5284,10 @@ typedef void (APIENTRYP PFNGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint divi
|
||||
#ifndef GL_ARB_map_buffer_range
|
||||
#define GL_ARB_map_buffer_range 1
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glMapBufferRange (GLenum, GLintptr, GLsizeiptr, GLbitfield);
|
||||
GLAPI GLvoid* APIENTRY glMapBufferRange (GLenum, GLintptr, GLsizeiptr, GLbitfield);
|
||||
GLAPI void APIENTRY glFlushMappedBufferRange (GLenum, GLintptr, GLsizeiptr);
|
||||
#endif /* GL_GLEXT_PROTOTYPES */
|
||||
typedef void (APIENTRYP PFNGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
|
||||
typedef GLvoid* (APIENTRYP PFNGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
|
||||
typedef void (APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length);
|
||||
#endif
|
||||
|
||||
@@ -8011,6 +8027,22 @@ typedef void (APIENTRYP PFNGLENDCONDITIONALRENDERNVPROC) (void);
|
||||
|
||||
#ifndef GL_NV_present_video
|
||||
#define GL_NV_present_video 1
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glPresentFrameKeyedNV (GLuint, GLuint64EXT, GLuint, GLuint, GLenum, GLenum, GLuint, GLuint, GLenum, GLuint, GLuint);
|
||||
GLAPI void APIENTRY glPresentFrameDualFillNV (GLuint, GLuint64EXT, GLuint, GLuint, GLenum, GLenum, GLuint, GLenum, GLuint, GLenum, GLuint, GLenum, GLuint);
|
||||
GLAPI void APIENTRY glGetVideoivNV (GLuint, GLenum, GLint *);
|
||||
GLAPI void APIENTRY glGetVideouivNV (GLuint, GLenum, GLuint *);
|
||||
GLAPI void APIENTRY glGetVideoi64vNV (GLuint, GLenum, GLint64EXT *);
|
||||
GLAPI void APIENTRY glGetVideoui64vNV (GLuint, GLenum, GLuint64EXT *);
|
||||
GLAPI void APIENTRY glVideoParameterivNV (GLuint, GLenum, const GLint *);
|
||||
#endif /* GL_GLEXT_PROTOTYPES */
|
||||
typedef void (APIENTRYP PFNGLPRESENTFRAMEKEYEDNVPROC) (GLuint video_slot, GLuint64EXT minPresentTime, GLuint beginPresentTimeId, GLuint presentDurationId, GLenum type, GLenum target0, GLuint fill0, GLuint key0, GLenum target1, GLuint fill1, GLuint key1);
|
||||
typedef void (APIENTRYP PFNGLPRESENTFRAMEDUALFILLNVPROC) (GLuint video_slot, GLuint64EXT minPresentTime, GLuint beginPresentTimeId, GLuint presentDurationId, GLenum type, GLenum target0, GLuint fill0, GLenum target1, GLuint fill1, GLenum target2, GLuint fill2, GLenum target3, GLuint fill3);
|
||||
typedef void (APIENTRYP PFNGLGETVIDEOIVNVPROC) (GLuint video_slot, GLenum pname, GLint *params);
|
||||
typedef void (APIENTRYP PFNGLGETVIDEOUIVNVPROC) (GLuint video_slot, GLenum pname, GLuint *params);
|
||||
typedef void (APIENTRYP PFNGLGETVIDEOI64VNVPROC) (GLuint video_slot, GLenum pname, GLint64EXT *params);
|
||||
typedef void (APIENTRYP PFNGLGETVIDEOUI64VNVPROC) (GLuint video_slot, GLenum pname, GLuint64EXT *params);
|
||||
typedef void (APIENTRYP PFNGLVIDEOPARAMETERIVNVPROC) (GLuint video_slot, GLenum pname, const GLint *params);
|
||||
#endif
|
||||
|
||||
#ifndef GL_EXT_transform_feedback
|
||||
@@ -8451,6 +8483,38 @@ typedef void (APIENTRYP PFNGLRESUMETRANSFORMFEEDBACKNVPROC) (void);
|
||||
typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKNVPROC) (GLenum mode, GLuint id);
|
||||
#endif
|
||||
|
||||
#ifndef GL_ATI_meminfo
|
||||
#define GL_ATI_meminfo 1
|
||||
#endif
|
||||
|
||||
#ifndef GL_AMD_performance_monitor
|
||||
#define GL_AMD_performance_monitor 1
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glGetPerfMonitorGroupsAMD (GLint *, GLsizei, GLuint *);
|
||||
GLAPI void APIENTRY glGetPerfMonitorCountersAMD (GLuint, GLint *, GLint *, GLsizei, GLuint *);
|
||||
GLAPI void APIENTRY glGetPerfMonitorGroupStringAMD (GLuint, GLsizei, GLsizei *, GLchar *);
|
||||
GLAPI void APIENTRY glGetPerfMonitorCounterStringAMD (GLuint, GLuint, GLsizei, GLsizei *, GLchar *);
|
||||
GLAPI void APIENTRY glGetPerfMonitorCounterInfoAMD (GLuint, GLuint, GLenum, void *);
|
||||
GLAPI void APIENTRY glGenPerfMonitorsAMD (GLsizei, GLuint *);
|
||||
GLAPI void APIENTRY glDeletePerfMonitorsAMD (GLsizei, GLuint *);
|
||||
GLAPI void APIENTRY glSelectPerfMonitorCountersAMD (GLuint, GLboolean, GLuint, GLint, GLuint *);
|
||||
GLAPI void APIENTRY glBeginPerfMonitorAMD (GLuint);
|
||||
GLAPI void APIENTRY glEndPerfMonitorAMD (GLuint);
|
||||
GLAPI void APIENTRY glGetPerfMonitorCounterDataAMD (GLuint, GLenum, GLsizei, GLuint *, GLint *);
|
||||
#endif /* GL_GLEXT_PROTOTYPES */
|
||||
typedef void (APIENTRYP PFNGLGETPERFMONITORGROUPSAMDPROC) (GLint *numGroups, GLsizei groupsSize, GLuint *groups);
|
||||
typedef void (APIENTRYP PFNGLGETPERFMONITORCOUNTERSAMDPROC) (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters);
|
||||
typedef void (APIENTRYP PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString);
|
||||
typedef void (APIENTRYP PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString);
|
||||
typedef void (APIENTRYP PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, void *data);
|
||||
typedef void (APIENTRYP PFNGLGENPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors);
|
||||
typedef void (APIENTRYP PFNGLDELETEPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors);
|
||||
typedef void (APIENTRYP PFNGLSELECTPERFMONITORCOUNTERSAMDPROC) (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *counterList);
|
||||
typedef void (APIENTRYP PFNGLBEGINPERFMONITORAMDPROC) (GLuint monitor);
|
||||
typedef void (APIENTRYP PFNGLENDPERFMONITORAMDPROC) (GLuint monitor);
|
||||
typedef void (APIENTRYP PFNGLGETPERFMONITORCOUNTERDATAAMDPROC) (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten);
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -624,6 +624,8 @@ struct __DRIswrastExtensionRec {
|
||||
#define __DRI_BUFFER_DEPTH 4
|
||||
#define __DRI_BUFFER_STENCIL 5
|
||||
#define __DRI_BUFFER_ACCUM 6
|
||||
#define __DRI_BUFFER_FAKE_FRONT_LEFT 7
|
||||
#define __DRI_BUFFER_FAKE_FRONT_RIGHT 8
|
||||
|
||||
struct __DRIbufferRec {
|
||||
unsigned int attachment;
|
||||
|
||||
54
progs/fbdev/Makefile
Normal file
54
progs/fbdev/Makefile
Normal file
@@ -0,0 +1,54 @@
|
||||
# Makefile for miniglx demo programs
|
||||
|
||||
TOP = ../..
|
||||
|
||||
include $(TOP)/configs/current
|
||||
|
||||
|
||||
SOURCES = glfbdevtest.c
|
||||
|
||||
OBJECTS = $(SOURCES:.c=.o)
|
||||
|
||||
PROGS = $(SOURCES:%.c=%)
|
||||
|
||||
INCLUDES = \
|
||||
-I. \
|
||||
-I$(TOP)/include
|
||||
|
||||
LIBS = -L$(TOP)/$(LIB_DIR) -l$(GLU_LIB) -l$(GL_LIB) $(APP_LIB_DEPS)
|
||||
|
||||
##### RULES #####
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c
|
||||
|
||||
.c:
|
||||
$(CC) $(INCLUDES) $(CFLAGS) $(LDFLAGS) $< $(LIBS) -o $@
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(INCLUDES) $(CFLAGS) $< -o $@
|
||||
|
||||
.S.o:
|
||||
$(CC) -c $(INCLUDES) $(CFLAGS) $< -o $@
|
||||
|
||||
|
||||
##### TARGETS #####
|
||||
|
||||
default: depend $(PROGS)
|
||||
|
||||
clean:
|
||||
-rm -f $(PROGS)
|
||||
-rm -f *.o
|
||||
|
||||
|
||||
depend: $(SOURCES)
|
||||
touch depend
|
||||
$(MKDEP) $(MKDEP_OPTIONS) $(INCLUDES) $(SOURCES) > /dev/null
|
||||
|
||||
|
||||
# Emacs tags
|
||||
tags:
|
||||
etags `find . -name \*.[ch]` `find ../include`
|
||||
|
||||
|
||||
include depend
|
||||
599
progs/fbdev/glfbdevtest.c
Normal file
599
progs/fbdev/glfbdevtest.c
Normal file
@@ -0,0 +1,599 @@
|
||||
/*
|
||||
* Test the GLFBDev interface. Only tested with radeonfb driver!!!!
|
||||
*
|
||||
* Written by Brian Paul
|
||||
*/
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/kd.h>
|
||||
#include <linux/vt.h>
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glfbdev.h>
|
||||
#include <math.h>
|
||||
|
||||
|
||||
/**
|
||||
* Choose one of these modes
|
||||
*/
|
||||
/*static const int XRes = 1280, YRes = 1024, Hz = 75;*/
|
||||
/*static const int XRes = 1280, YRes = 1024, Hz = 70;*/
|
||||
/*static const int XRes = 1280, YRes = 1024, Hz = 60;*/
|
||||
static const int XRes = 1024, YRes = 768, Hz = 70;
|
||||
|
||||
static int DesiredDepth = 32;
|
||||
|
||||
static int NumFrames = 100;
|
||||
|
||||
static struct fb_fix_screeninfo FixedInfo;
|
||||
static struct fb_var_screeninfo VarInfo, OrigVarInfo;
|
||||
static int OriginalVT = -1;
|
||||
static int ConsoleFD = -1;
|
||||
static int FrameBufferFD = -1;
|
||||
static caddr_t FrameBuffer = (caddr_t) -1;
|
||||
static caddr_t MMIOAddress = (caddr_t) -1;
|
||||
|
||||
|
||||
static void
|
||||
print_fixed_info(const struct fb_fix_screeninfo *fixed, const char *s)
|
||||
{
|
||||
static const char *visuals[] = {
|
||||
"MONO01", "MONO10", "TRUECOLOR", "PSEUDOCOLOR",
|
||||
"DIRECTCOLOR", "STATIC_PSEUDOCOLOR"
|
||||
};
|
||||
|
||||
printf("%s info -----------------------\n", s);
|
||||
printf("id = %16s\n", fixed->id);
|
||||
printf("smem_start = 0x%lx\n", fixed->smem_start);
|
||||
printf("smem_len = %d (0x%x)\n", fixed->smem_len, fixed->smem_len);
|
||||
printf("type = 0x%x\n", fixed->type);
|
||||
printf("type_aux = 0x%x\n", fixed->type_aux);
|
||||
printf("visual = 0x%x (%s)\n", fixed->visual, visuals[fixed->visual]);
|
||||
printf("xpanstep = %d\n", fixed->xpanstep);
|
||||
printf("ypanstep = %d\n", fixed->ypanstep);
|
||||
printf("ywrapstep = %d\n", fixed->ywrapstep);
|
||||
printf("line_length = %d\n", fixed->line_length);
|
||||
printf("mmio_start = 0x%lx\n", fixed->mmio_start);
|
||||
printf("mmio_len = %d (0x%x)\n", fixed->mmio_len, fixed->mmio_len);
|
||||
printf("accel = 0x%x\n", fixed->accel);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
print_var_info(const struct fb_var_screeninfo *var, const char *s)
|
||||
{
|
||||
printf("%s info -----------------------\n", s);
|
||||
printf("xres = %d\n", var->xres);
|
||||
printf("yres = %d\n", var->yres);
|
||||
printf("xres_virtual = %d\n", var->xres_virtual);
|
||||
printf("yres_virtual = %d\n", var->yres_virtual);
|
||||
printf("xoffset = %d\n", var->xoffset);
|
||||
printf("yoffset = %d\n", var->yoffset);
|
||||
printf("bits_per_pixel = %d\n", var->bits_per_pixel);
|
||||
printf("grayscale = %d\n", var->grayscale);
|
||||
|
||||
printf("red.offset = %d length = %d msb_right = %d\n",
|
||||
var->red.offset, var->red.length, var->red.msb_right);
|
||||
printf("green.offset = %d length = %d msb_right = %d\n",
|
||||
var->green.offset, var->green.length, var->green.msb_right);
|
||||
printf("blue.offset = %d length = %d msb_right = %d\n",
|
||||
var->blue.offset, var->blue.length, var->blue.msb_right);
|
||||
printf("transp.offset = %d length = %d msb_right = %d\n",
|
||||
var->transp.offset, var->transp.length, var->transp.msb_right);
|
||||
|
||||
printf("nonstd = %d\n", var->nonstd);
|
||||
printf("activate = %d\n", var->activate);
|
||||
printf("height = %d mm\n", var->height);
|
||||
printf("width = %d mm\n", var->width);
|
||||
printf("accel_flags = 0x%x\n", var->accel_flags);
|
||||
printf("pixclock = %d\n", var->pixclock);
|
||||
printf("left_margin = %d\n", var->left_margin);
|
||||
printf("right_margin = %d\n", var->right_margin);
|
||||
printf("upper_margin = %d\n", var->upper_margin);
|
||||
printf("lower_margin = %d\n", var->lower_margin);
|
||||
printf("hsync_len = %d\n", var->hsync_len);
|
||||
printf("vsync_len = %d\n", var->vsync_len);
|
||||
printf("sync = %d\n", var->sync);
|
||||
printf("vmode = %d\n", var->vmode);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
signal_handler(int signumber)
|
||||
{
|
||||
signal(signumber, SIG_IGN); /* prevent recursion! */
|
||||
fprintf(stderr, "error: got signal %d (exiting)\n", signumber);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
initialize_fbdev( void )
|
||||
{
|
||||
char ttystr[1000];
|
||||
int fd, vtnumber, ttyfd;
|
||||
int sz;
|
||||
|
||||
(void) sz;
|
||||
|
||||
if (geteuid()) {
|
||||
fprintf(stderr, "error: you need to be root\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#if 1
|
||||
/* open the framebuffer device */
|
||||
FrameBufferFD = open("/dev/fb0", O_RDWR);
|
||||
if (FrameBufferFD < 0) {
|
||||
fprintf(stderr, "Error opening /dev/fb0: %s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* open /dev/tty0 and get the vt number */
|
||||
if ((fd = open("/dev/tty0", O_WRONLY, 0)) < 0) {
|
||||
fprintf(stderr, "error opening /dev/tty0\n");
|
||||
exit(1);
|
||||
}
|
||||
if (ioctl(fd, VT_OPENQRY, &vtnumber) < 0 || vtnumber < 0) {
|
||||
fprintf(stderr, "error: couldn't get a free vt\n");
|
||||
exit(1);
|
||||
}
|
||||
close(fd);
|
||||
|
||||
/* open the console tty */
|
||||
sprintf(ttystr, "/dev/tty%d", vtnumber); /* /dev/tty1-64 */
|
||||
ConsoleFD = open(ttystr, O_RDWR | O_NDELAY, 0);
|
||||
if (ConsoleFD < 0) {
|
||||
fprintf(stderr, "error couldn't open console fd\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* save current vt number */
|
||||
{
|
||||
struct vt_stat vts;
|
||||
if (ioctl(ConsoleFD, VT_GETSTATE, &vts) == 0)
|
||||
OriginalVT = vts.v_active;
|
||||
}
|
||||
|
||||
/* disconnect from controlling tty */
|
||||
ttyfd = open("/dev/tty", O_RDWR);
|
||||
if (ttyfd >= 0) {
|
||||
ioctl(ttyfd, TIOCNOTTY, 0);
|
||||
close(ttyfd);
|
||||
}
|
||||
|
||||
/* some magic to restore the vt when we exit */
|
||||
{
|
||||
struct vt_mode vt;
|
||||
if (ioctl(ConsoleFD, VT_ACTIVATE, vtnumber) != 0)
|
||||
printf("ioctl VT_ACTIVATE: %s\n", strerror(errno));
|
||||
if (ioctl(ConsoleFD, VT_WAITACTIVE, vtnumber) != 0)
|
||||
printf("ioctl VT_WAITACTIVE: %s\n", strerror(errno));
|
||||
|
||||
if (ioctl(ConsoleFD, VT_GETMODE, &vt) < 0) {
|
||||
fprintf(stderr, "error: ioctl VT_GETMODE: %s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
vt.mode = VT_PROCESS;
|
||||
vt.relsig = SIGUSR1;
|
||||
vt.acqsig = SIGUSR1;
|
||||
if (ioctl(ConsoleFD, VT_SETMODE, &vt) < 0) {
|
||||
fprintf(stderr, "error: ioctl(VT_SETMODE) failed: %s\n",
|
||||
strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* go into graphics mode */
|
||||
if (ioctl(ConsoleFD, KDSETMODE, KD_GRAPHICS) < 0) {
|
||||
fprintf(stderr, "error: ioctl(KDSETMODE, KD_GRAPHICS) failed: %s\n",
|
||||
strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/* open the framebuffer device */
|
||||
FrameBufferFD = open("/dev/fb0", O_RDWR);
|
||||
if (FrameBufferFD < 0) {
|
||||
fprintf(stderr, "Error opening /dev/fb0: %s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Get the fixed screen info */
|
||||
if (ioctl(FrameBufferFD, FBIOGET_FSCREENINFO, &FixedInfo)) {
|
||||
fprintf(stderr, "error: ioctl(FBIOGET_FSCREENINFO) failed: %s\n",
|
||||
strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
print_fixed_info(&FixedInfo, "Fixed");
|
||||
|
||||
|
||||
/* get the variable screen info */
|
||||
if (ioctl(FrameBufferFD, FBIOGET_VSCREENINFO, &OrigVarInfo)) {
|
||||
fprintf(stderr, "error: ioctl(FBIOGET_VSCREENINFO) failed: %s\n",
|
||||
strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
print_var_info(&OrigVarInfo, "Orig Var");
|
||||
|
||||
/* operate on a copy */
|
||||
VarInfo = OrigVarInfo;
|
||||
|
||||
/* set the depth, resolution, etc */
|
||||
if (DesiredDepth)
|
||||
VarInfo.bits_per_pixel = DesiredDepth;
|
||||
|
||||
if (VarInfo.bits_per_pixel == 16) {
|
||||
VarInfo.red.offset = 11;
|
||||
VarInfo.green.offset = 5;
|
||||
VarInfo.blue.offset = 0;
|
||||
VarInfo.red.length = 5;
|
||||
VarInfo.green.length = 6;
|
||||
VarInfo.blue.length = 5;
|
||||
VarInfo.transp.offset = 0;
|
||||
VarInfo.transp.length = 0;
|
||||
}
|
||||
else if (VarInfo.bits_per_pixel == 32) {
|
||||
VarInfo.red.offset = 16;
|
||||
VarInfo.green.offset = 8;
|
||||
VarInfo.blue.offset = 0;
|
||||
VarInfo.transp.offset = 24;
|
||||
VarInfo.red.length = 8;
|
||||
VarInfo.green.length = 8;
|
||||
VarInfo.blue.length = 8;
|
||||
VarInfo.transp.length = 8;
|
||||
}
|
||||
|
||||
/* timing values taken from /etc/fb.modes */
|
||||
if (XRes == 1280 && YRes == 1024) {
|
||||
VarInfo.xres_virtual = VarInfo.xres = XRes;
|
||||
VarInfo.yres_virtual = VarInfo.yres = YRes;
|
||||
if (Hz == 75) {
|
||||
VarInfo.pixclock = 7408;
|
||||
VarInfo.left_margin = 248;
|
||||
VarInfo.right_margin = 16;
|
||||
VarInfo.upper_margin = 38;
|
||||
VarInfo.lower_margin = 1;
|
||||
VarInfo.hsync_len = 144;
|
||||
VarInfo.vsync_len = 3;
|
||||
}
|
||||
else if (Hz == 70) {
|
||||
VarInfo.pixclock = 7937;
|
||||
VarInfo.left_margin = 216;
|
||||
VarInfo.right_margin = 80;
|
||||
VarInfo.upper_margin = 36;
|
||||
VarInfo.lower_margin = 1;
|
||||
VarInfo.hsync_len = 112;
|
||||
VarInfo.vsync_len = 5;
|
||||
}
|
||||
else if (Hz == 60) {
|
||||
VarInfo.pixclock = 9260;
|
||||
VarInfo.left_margin = 248;
|
||||
VarInfo.right_margin = 48;
|
||||
VarInfo.upper_margin = 38;
|
||||
VarInfo.lower_margin = 1;
|
||||
VarInfo.hsync_len = 112;
|
||||
VarInfo.vsync_len = 3;
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "invalid rate for 1280x1024\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else if (XRes == 1024 && YRes == 768 && Hz == 70) {
|
||||
VarInfo.xres_virtual = VarInfo.xres = XRes;
|
||||
VarInfo.yres_virtual = VarInfo.yres = YRes;
|
||||
if (Hz == 70) {
|
||||
VarInfo.pixclock = 13334;
|
||||
VarInfo.left_margin = 144;
|
||||
VarInfo.right_margin = 24;
|
||||
VarInfo.upper_margin = 29;
|
||||
VarInfo.lower_margin = 3;
|
||||
VarInfo.hsync_len = 136;
|
||||
VarInfo.vsync_len = 6;
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "invalid rate for 1024x768\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
VarInfo.xoffset = 0;
|
||||
VarInfo.yoffset = 0;
|
||||
VarInfo.nonstd = 0;
|
||||
VarInfo.vmode &= ~FB_VMODE_YWRAP; /* turn off scrolling */
|
||||
|
||||
/* set new variable screen info */
|
||||
if (ioctl(FrameBufferFD, FBIOPUT_VSCREENINFO, &VarInfo)) {
|
||||
fprintf(stderr, "ioctl(FBIOPUT_VSCREENINFO failed): %s\n",
|
||||
strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
print_var_info(&VarInfo, "New Var");
|
||||
|
||||
if (FixedInfo.visual != FB_VISUAL_TRUECOLOR &&
|
||||
FixedInfo.visual != FB_VISUAL_DIRECTCOLOR) {
|
||||
fprintf(stderr, "non-TRUE/DIRECT-COLOR visuals (0x%x) not supported by this demo.\n", FixedInfo.visual);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* initialize colormap */
|
||||
if (FixedInfo.visual == FB_VISUAL_DIRECTCOLOR) {
|
||||
struct fb_cmap cmap;
|
||||
unsigned short red[256], green[256], blue[256];
|
||||
int i;
|
||||
|
||||
/* we're assuming 256 entries here */
|
||||
printf("initializing directcolor colormap\n");
|
||||
cmap.start = 0;
|
||||
cmap.len = 256;
|
||||
cmap.red = red;
|
||||
cmap.green = green;
|
||||
cmap.blue = blue;
|
||||
cmap.transp = NULL;
|
||||
for (i = 0; i < cmap.len; i++) {
|
||||
red[i] = green[i] = blue[i] = (i << 8) | i;
|
||||
}
|
||||
if (ioctl(FrameBufferFD, FBIOPUTCMAP, (void *) &cmap) < 0) {
|
||||
fprintf(stderr, "ioctl(FBIOPUTCMAP) failed [%d]\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* fbdev says the frame buffer is at offset zero, and the mmio region
|
||||
* is immediately after.
|
||||
*/
|
||||
|
||||
/* mmap the framebuffer into our address space */
|
||||
FrameBuffer = (caddr_t) mmap(0, /* start */
|
||||
FixedInfo.smem_len, /* bytes */
|
||||
PROT_READ | PROT_WRITE, /* prot */
|
||||
MAP_SHARED, /* flags */
|
||||
FrameBufferFD, /* fd */
|
||||
0 /* offset */);
|
||||
if (FrameBuffer == (caddr_t) - 1) {
|
||||
fprintf(stderr, "error: unable to mmap framebuffer: %s\n",
|
||||
strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
printf("FrameBuffer = %p\n", FrameBuffer);
|
||||
|
||||
#if 1
|
||||
/* mmap the MMIO region into our address space */
|
||||
MMIOAddress = (caddr_t) mmap(0, /* start */
|
||||
FixedInfo.mmio_len, /* bytes */
|
||||
PROT_READ | PROT_WRITE, /* prot */
|
||||
MAP_SHARED, /* flags */
|
||||
FrameBufferFD, /* fd */
|
||||
FixedInfo.smem_len /* offset */);
|
||||
if (MMIOAddress == (caddr_t) - 1) {
|
||||
fprintf(stderr, "error: unable to mmap mmio region: %s\n",
|
||||
strerror(errno));
|
||||
}
|
||||
printf("MMIOAddress = %p\n", MMIOAddress);
|
||||
|
||||
/* try out some simple MMIO register reads */
|
||||
if (0)
|
||||
{
|
||||
typedef unsigned int CARD32;
|
||||
typedef unsigned char CARD8;
|
||||
#define RADEON_CONFIG_MEMSIZE 0x00f8
|
||||
#define RADEON_MEM_SDRAM_MODE_REG 0x0158
|
||||
#define MMIO_IN32(base, offset) \
|
||||
*(volatile CARD32 *)(void *)(((CARD8*)(base)) + (offset))
|
||||
#define INREG(addr) MMIO_IN32(MMIOAddress, addr)
|
||||
int sz, type;
|
||||
const char *typeStr[] = {"SDR", "DDR", "64-bit SDR"};
|
||||
sz = INREG(RADEON_CONFIG_MEMSIZE);
|
||||
type = INREG(RADEON_MEM_SDRAM_MODE_REG);
|
||||
printf("RADEON_CONFIG_MEMSIZE = %d (%d MB)\n", sz, sz / 1024 / 1024);
|
||||
printf("RADEON_MEM_SDRAM_MODE_REG >> 30 = %d (%s)\n",
|
||||
type >> 30, typeStr[type>>30]);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
shutdown_fbdev( void )
|
||||
{
|
||||
struct vt_mode VT;
|
||||
|
||||
printf("cleaning up...\n");
|
||||
/* restore original variable screen info */
|
||||
if (ioctl(FrameBufferFD, FBIOPUT_VSCREENINFO, &OrigVarInfo)) {
|
||||
fprintf(stderr, "ioctl(FBIOPUT_VSCREENINFO failed): %s\n",
|
||||
strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
munmap(MMIOAddress, FixedInfo.mmio_len);
|
||||
munmap(FrameBuffer, FixedInfo.smem_len);
|
||||
close(FrameBufferFD);
|
||||
|
||||
/* restore text mode */
|
||||
ioctl(ConsoleFD, KDSETMODE, KD_TEXT);
|
||||
|
||||
/* set vt */
|
||||
if (ioctl(ConsoleFD, VT_GETMODE, &VT) != -1) {
|
||||
VT.mode = VT_AUTO;
|
||||
ioctl(ConsoleFD, VT_SETMODE, &VT);
|
||||
}
|
||||
|
||||
/* restore original vt */
|
||||
if (OriginalVT >= 0) {
|
||||
ioctl(ConsoleFD, VT_ACTIVATE, OriginalVT);
|
||||
OriginalVT = -1;
|
||||
}
|
||||
|
||||
close(ConsoleFD);
|
||||
}
|
||||
|
||||
|
||||
/* Borrowed from GLUT */
|
||||
static void
|
||||
doughnut(GLfloat r, GLfloat R, GLint nsides, GLint rings)
|
||||
{
|
||||
int i, j;
|
||||
GLfloat theta, phi, theta1;
|
||||
GLfloat cosTheta, sinTheta;
|
||||
GLfloat cosTheta1, sinTheta1;
|
||||
GLfloat ringDelta, sideDelta;
|
||||
|
||||
ringDelta = 2.0 * M_PI / rings;
|
||||
sideDelta = 2.0 * M_PI / nsides;
|
||||
|
||||
theta = 0.0;
|
||||
cosTheta = 1.0;
|
||||
sinTheta = 0.0;
|
||||
for (i = rings - 1; i >= 0; i--) {
|
||||
theta1 = theta + ringDelta;
|
||||
cosTheta1 = cos(theta1);
|
||||
sinTheta1 = sin(theta1);
|
||||
glBegin(GL_QUAD_STRIP);
|
||||
phi = 0.0;
|
||||
for (j = nsides; j >= 0; j--) {
|
||||
GLfloat cosPhi, sinPhi, dist;
|
||||
|
||||
phi += sideDelta;
|
||||
cosPhi = cos(phi);
|
||||
sinPhi = sin(phi);
|
||||
dist = R + r * cosPhi;
|
||||
|
||||
glNormal3f(cosTheta1 * cosPhi, -sinTheta1 * cosPhi, sinPhi);
|
||||
glVertex3f(cosTheta1 * dist, -sinTheta1 * dist, r * sinPhi);
|
||||
glNormal3f(cosTheta * cosPhi, -sinTheta * cosPhi, sinPhi);
|
||||
glVertex3f(cosTheta * dist, -sinTheta * dist, r * sinPhi);
|
||||
}
|
||||
glEnd();
|
||||
theta = theta1;
|
||||
cosTheta = cosTheta1;
|
||||
sinTheta = sinTheta1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gltest( void )
|
||||
{
|
||||
static const int attribs[] = {
|
||||
GLFBDEV_DOUBLE_BUFFER,
|
||||
GLFBDEV_DEPTH_SIZE, 16,
|
||||
GLFBDEV_NONE
|
||||
};
|
||||
GLFBDevContextPtr ctx;
|
||||
GLFBDevBufferPtr buf;
|
||||
GLFBDevVisualPtr vis;
|
||||
int bytes, r, g, b, a;
|
||||
float ang;
|
||||
int i;
|
||||
|
||||
printf("GLFBDEV_VENDOR = %s\n", glFBDevGetString(GLFBDEV_VENDOR));
|
||||
printf("GLFBDEV_VERSION = %s\n", glFBDevGetString(GLFBDEV_VERSION));
|
||||
|
||||
/* framebuffer size */
|
||||
bytes = VarInfo.xres_virtual * VarInfo.yres_virtual * VarInfo.bits_per_pixel / 8;
|
||||
|
||||
vis = glFBDevCreateVisual( &FixedInfo, &VarInfo, attribs );
|
||||
assert(vis);
|
||||
|
||||
buf = glFBDevCreateBuffer( &FixedInfo, &VarInfo, vis, FrameBuffer, NULL, bytes );
|
||||
assert(buf);
|
||||
|
||||
ctx = glFBDevCreateContext( vis, NULL );
|
||||
assert(buf);
|
||||
|
||||
b = glFBDevMakeCurrent( ctx, buf, buf );
|
||||
assert(b);
|
||||
|
||||
/*printf("GL_EXTENSIONS: %s\n", glGetString(GL_EXTENSIONS));*/
|
||||
glGetIntegerv(GL_RED_BITS, &r);
|
||||
glGetIntegerv(GL_GREEN_BITS, &g);
|
||||
glGetIntegerv(GL_BLUE_BITS, &b);
|
||||
glGetIntegerv(GL_ALPHA_BITS, &a);
|
||||
printf("RED_BITS=%d GREEN_BITS=%d BLUE_BITS=%d ALPHA_BITS=%d\n",
|
||||
r, g, b, a);
|
||||
|
||||
glClearColor(0.5, 0.5, 1.0, 0);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glFrustum(-1, 1, -1, 1, 2, 30);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glTranslatef(0, 0, -15);
|
||||
glViewport(0, 0, VarInfo.xres_virtual, VarInfo.yres_virtual);
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_LIGHT0);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
printf("Drawing %d frames...\n", NumFrames);
|
||||
|
||||
ang = 0.0;
|
||||
for (i = 0; i < NumFrames; i++) {
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glPushMatrix();
|
||||
glRotatef(ang, 1, 0, 0);
|
||||
doughnut(1, 3, 40, 20);
|
||||
glPopMatrix();
|
||||
glFBDevSwapBuffers(buf);
|
||||
ang += 15.0;
|
||||
}
|
||||
|
||||
/* clean up */
|
||||
b = glFBDevMakeCurrent( NULL, NULL, NULL);
|
||||
assert(b);
|
||||
|
||||
glFBDevDestroyContext(ctx);
|
||||
glFBDevDestroyBuffer(buf);
|
||||
glFBDevDestroyVisual(vis);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
parse_args(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-f") == 0) {
|
||||
NumFrames = atoi(argv[i+1]);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main( int argc, char *argv[] )
|
||||
{
|
||||
signal(SIGUSR1, signal_handler); /* exit if someone tries a vt switch */
|
||||
signal(SIGSEGV, signal_handler); /* catch segfaults */
|
||||
|
||||
parse_args(argc, argv);
|
||||
|
||||
printf("Setting mode to %d x %d @ %d Hz, %d bpp\n", XRes, YRes, Hz, DesiredDepth);
|
||||
initialize_fbdev();
|
||||
gltest();
|
||||
shutdown_fbdev();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -47,9 +47,12 @@ static const char *TexFiles[2] =
|
||||
|
||||
static GLuint Program;
|
||||
|
||||
static GLfloat Xrot = -90.0, Yrot = .0, Zrot = 0.0;
|
||||
static GLfloat Xrot = 0.0, Yrot = .0, Zrot = 0.0;
|
||||
static GLfloat EyeDist = 10;
|
||||
static GLboolean Anim = GL_TRUE;
|
||||
static GLboolean UseArrays = GL_TRUE;
|
||||
|
||||
static GLint VertCoord_attr = -1, TexCoord0_attr = -1, TexCoord1_attr = -1;
|
||||
|
||||
|
||||
/* value[0] = tex unit */
|
||||
@@ -60,32 +63,62 @@ static struct uniform_info Uniforms[] = {
|
||||
};
|
||||
|
||||
|
||||
static const GLfloat Tex0Coords[4][2] = {
|
||||
{ 0.0, 0.0 }, { 2.0, 0.0 }, { 2.0, 2.0 }, { 0.0, 2.0 }
|
||||
};
|
||||
|
||||
static const GLfloat Tex1Coords[4][2] = {
|
||||
{ 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 0.0, 1.0 }
|
||||
};
|
||||
|
||||
static const GLfloat VertCoords[4][2] = {
|
||||
{ -3.0, -3.0 }, { 3.0, -3.0 }, { 3.0, 3.0 }, { -3.0, 3.0 }
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
DrawPolygon(GLfloat size)
|
||||
DrawPolygonArray(void)
|
||||
{
|
||||
glPushMatrix();
|
||||
glRotatef(90, 1, 0, 0);
|
||||
glNormal3f(0, 0, 1);
|
||||
glBegin(GL_POLYGON);
|
||||
if (VertCoord_attr >= 0) {
|
||||
glVertexAttribPointer_func(VertCoord_attr, 2, GL_FLOAT, GL_FALSE,
|
||||
0, VertCoords);
|
||||
glEnableVertexAttribArray_func(VertCoord_attr);
|
||||
}
|
||||
else {
|
||||
glVertexPointer(2, GL_FLOAT, 0, VertCoords);
|
||||
glEnable(GL_VERTEX_ARRAY);
|
||||
}
|
||||
|
||||
glMultiTexCoord2f(GL_TEXTURE0, 0, 0);
|
||||
glMultiTexCoord2f(GL_TEXTURE1, 0, 0);
|
||||
glVertex2f(-size, -size);
|
||||
glVertexAttribPointer_func(TexCoord0_attr, 2, GL_FLOAT, GL_FALSE,
|
||||
0, Tex0Coords);
|
||||
glEnableVertexAttribArray_func(TexCoord0_attr);
|
||||
|
||||
glMultiTexCoord2f(GL_TEXTURE0, 2, 0);
|
||||
glMultiTexCoord2f(GL_TEXTURE1, 1, 0);
|
||||
glVertex2f( size, -size);
|
||||
glVertexAttribPointer_func(TexCoord1_attr, 2, GL_FLOAT, GL_FALSE,
|
||||
0, Tex1Coords);
|
||||
glEnableVertexAttribArray_func(TexCoord1_attr);
|
||||
|
||||
glMultiTexCoord2f(GL_TEXTURE0, 2, 2);
|
||||
glMultiTexCoord2f(GL_TEXTURE1, 1, 1);
|
||||
glVertex2f( size, size);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
}
|
||||
|
||||
glMultiTexCoord2f(GL_TEXTURE0, 0, 2);
|
||||
glMultiTexCoord2f(GL_TEXTURE1, 0, 1);
|
||||
glVertex2f(-size, size);
|
||||
|
||||
static void
|
||||
DrawPolygonVert(void)
|
||||
{
|
||||
GLuint i;
|
||||
|
||||
glBegin(GL_TRIANGLE_FAN);
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
glVertexAttrib2fv_func(TexCoord0_attr, Tex0Coords[i]);
|
||||
glVertexAttrib2fv_func(TexCoord1_attr, Tex1Coords[i]);
|
||||
|
||||
if (VertCoord_attr >= 0)
|
||||
glVertexAttrib2fv_func(VertCoord_attr, VertCoords[i]);
|
||||
else
|
||||
glVertex2fv(VertCoords[i]);
|
||||
}
|
||||
|
||||
glEnd();
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
@@ -100,7 +133,10 @@ draw(void)
|
||||
glRotatef(Yrot, 0, 1, 0);
|
||||
glRotatef(Xrot, 1, 0, 0);
|
||||
|
||||
DrawPolygon(3.0);
|
||||
if (UseArrays)
|
||||
DrawPolygonArray();
|
||||
else
|
||||
DrawPolygonVert();
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
@@ -123,8 +159,11 @@ key(unsigned char k, int x, int y)
|
||||
(void) x;
|
||||
(void) y;
|
||||
switch (k) {
|
||||
case ' ':
|
||||
case 'a':
|
||||
UseArrays = !UseArrays;
|
||||
printf("Arrays: %d\n", UseArrays);
|
||||
break;
|
||||
case ' ':
|
||||
Anim = !Anim;
|
||||
if (Anim)
|
||||
glutIdleFunc(idle);
|
||||
@@ -232,6 +271,13 @@ CreateProgram(const char *vertProgFile, const char *fragProgFile,
|
||||
|
||||
InitUniforms(program, uniforms);
|
||||
|
||||
TexCoord0_attr = glGetAttribLocation_func(program, "TexCoord0");
|
||||
TexCoord1_attr = glGetAttribLocation_func(program, "TexCoord1");
|
||||
VertCoord_attr = glGetAttribLocation_func(program, "VertCoord");
|
||||
printf("TexCoord0_attr = %d\n", TexCoord0_attr);
|
||||
printf("TexCoord1_attr = %d\n", TexCoord1_attr);
|
||||
printf("VertCoord_attr = %d\n", VertCoord_attr);
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,9 +2,13 @@
|
||||
// Brian Paul
|
||||
|
||||
|
||||
attribute vec4 TexCoord0, TexCoord1;
|
||||
attribute vec4 VertCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||
gl_TexCoord[1] = gl_MultiTexCoord1;
|
||||
gl_Position = ftransform();
|
||||
gl_TexCoord[0] = TexCoord0;
|
||||
gl_TexCoord[1] = TexCoord1;
|
||||
// note: may use gl_Vertex or VertCoord here for testing:
|
||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||
}
|
||||
|
||||
@@ -46,6 +46,13 @@ static PFNGLVERTEXATTRIB1FPROC glVertexAttrib1f_func = NULL;
|
||||
static PFNGLVERTEXATTRIB2FPROC glVertexAttrib2f_func = NULL;
|
||||
static PFNGLVERTEXATTRIB3FPROC glVertexAttrib3f_func = NULL;
|
||||
static PFNGLVERTEXATTRIB4FPROC glVertexAttrib4f_func = NULL;
|
||||
static PFNGLVERTEXATTRIB1FVPROC glVertexAttrib1fv_func = NULL;
|
||||
static PFNGLVERTEXATTRIB2FVPROC glVertexAttrib2fv_func = NULL;
|
||||
static PFNGLVERTEXATTRIB3FVPROC glVertexAttrib3fv_func = NULL;
|
||||
static PFNGLVERTEXATTRIB4FVPROC glVertexAttrib4fv_func = NULL;
|
||||
static PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer_func = NULL;
|
||||
static PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray_func = NULL;
|
||||
static PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray_func = NULL;
|
||||
|
||||
/* OpenGL 2.1 */
|
||||
static PFNGLUNIFORMMATRIX2X3FVPROC glUniformMatrix2x3fv_func = NULL;
|
||||
@@ -126,6 +133,14 @@ GetExtensionFuncs(void)
|
||||
glVertexAttrib2f_func = (PFNGLVERTEXATTRIB2FPROC) glutGetProcAddress("glVertexAttrib2f");
|
||||
glVertexAttrib3f_func = (PFNGLVERTEXATTRIB3FPROC) glutGetProcAddress("glVertexAttrib3f");
|
||||
glVertexAttrib4f_func = (PFNGLVERTEXATTRIB4FPROC) glutGetProcAddress("glVertexAttrib4f");
|
||||
glVertexAttrib1fv_func = (PFNGLVERTEXATTRIB1FVPROC) glutGetProcAddress("glVertexAttrib1fv");
|
||||
glVertexAttrib2fv_func = (PFNGLVERTEXATTRIB2FVPROC) glutGetProcAddress("glVertexAttrib2fv");
|
||||
glVertexAttrib3fv_func = (PFNGLVERTEXATTRIB3FVPROC) glutGetProcAddress("glVertexAttrib3fv");
|
||||
glVertexAttrib4fv_func = (PFNGLVERTEXATTRIB4FVPROC) glutGetProcAddress("glVertexAttrib4fv");
|
||||
|
||||
glVertexAttribPointer_func = (PFNGLVERTEXATTRIBPOINTERPROC) glutGetProcAddress("glVertexAttribPointer");
|
||||
glEnableVertexAttribArray_func = (PFNGLENABLEVERTEXATTRIBARRAYPROC) glutGetProcAddress("glEnableVertexAttribArray");
|
||||
glDisableVertexAttribArray_func = (PFNGLDISABLEVERTEXATTRIBARRAYPROC) glutGetProcAddress("glDisableVertexAttribArray");
|
||||
|
||||
/* OpenGL 2.1 */
|
||||
glUniformMatrix2x3fv_func = (PFNGLUNIFORMMATRIX2X3FVPROC) glutGetProcAddress("glUniformMatrix2x3fv");
|
||||
|
||||
@@ -39,6 +39,9 @@
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glx.h>
|
||||
|
||||
static int is_glx_extension_supported(Display *dpy, const char *query);
|
||||
|
||||
static void query_vsync(Display *dpy);
|
||||
|
||||
#define BENCHMARK
|
||||
|
||||
@@ -560,6 +563,73 @@ make_window( Display *dpy, const char *name,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine whether or not a GLX extension is supported.
|
||||
*/
|
||||
int
|
||||
is_glx_extension_supported(Display *dpy, const char *query)
|
||||
{
|
||||
const int scrnum = DefaultScreen(dpy);
|
||||
const char *glx_extensions = NULL;
|
||||
const size_t len = strlen(query);
|
||||
const char *ptr;
|
||||
|
||||
if (glx_extensions == NULL) {
|
||||
glx_extensions = glXQueryExtensionsString(dpy, scrnum);
|
||||
}
|
||||
|
||||
ptr = strstr(glx_extensions, query);
|
||||
return ((ptr != NULL) && ((ptr[len] == ' ') || (ptr[len] == '\0')));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Attempt to determine whether or not the display is synched to vblank.
|
||||
*/
|
||||
void
|
||||
query_vsync(Display *dpy)
|
||||
{
|
||||
int interval = 0;
|
||||
|
||||
|
||||
#ifdef GLX_MESA_swap_control
|
||||
if ((interval <= 0)
|
||||
&& is_glx_extension_supported(dpy, "GLX_MESA_swap_control")) {
|
||||
PFNGLXGETSWAPINTERVALMESAPROC pglXGetSwapIntervalMESA =
|
||||
(PFNGLXGETSWAPINTERVALMESAPROC)
|
||||
glXGetProcAddressARB((const GLubyte *) "glXGetSwapIntervalMESA");
|
||||
|
||||
interval = (*pglXGetSwapIntervalMESA)();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef GLX_SGI_video_sync
|
||||
if ((interval <= 0)
|
||||
&& is_glx_extension_supported(dpy, "GLX_SGI_video_sync")) {
|
||||
PFNGLXGETVIDEOSYNCSGIPROC pglXGetVideoSyncSGI =
|
||||
(PFNGLXGETVIDEOSYNCSGIPROC)
|
||||
glXGetProcAddressARB((const GLubyte *) "glXGetVideoSyncSGI");
|
||||
unsigned count;
|
||||
|
||||
if ((*pglXGetVideoSyncSGI)(& count) == 0) {
|
||||
interval = (int) count;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if (interval > 0) {
|
||||
printf("Running synchronized to the vertical refresh. The framerate should be\n");
|
||||
if (interval == 1) {
|
||||
printf("approximately the same as the monitor refresh rate.\n");
|
||||
} else if (interval > 1) {
|
||||
printf("approximately 1/%d the monitor refresh rate.\n",
|
||||
interval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle one X event.
|
||||
* \return NOP, EXIT or DRAW
|
||||
@@ -567,6 +637,9 @@ make_window( Display *dpy, const char *name,
|
||||
static int
|
||||
handle_event(Display *dpy, Window win, XEvent *event)
|
||||
{
|
||||
(void) dpy;
|
||||
(void) win;
|
||||
|
||||
switch (event->type) {
|
||||
case Expose:
|
||||
return DRAW;
|
||||
@@ -686,6 +759,7 @@ main(int argc, char *argv[])
|
||||
make_window(dpy, "glxgears", x, y, winWidth, winHeight, &win, &ctx);
|
||||
XMapWindow(dpy, win);
|
||||
glXMakeCurrent(dpy, win, ctx);
|
||||
query_vsync(dpy);
|
||||
|
||||
if (printInfo) {
|
||||
printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
|
||||
|
||||
@@ -178,6 +178,7 @@ int main( int argc, char *argv[] )
|
||||
glColor3f( 0.0, 1.0, 1.0 );
|
||||
glRectf( -0.75, -0.75, 0.75, 0.75 );
|
||||
glFlush();
|
||||
glXWaitGL();
|
||||
|
||||
XMapWindow( dpy, win );
|
||||
|
||||
|
||||
@@ -286,7 +286,7 @@ EventLoop(void)
|
||||
XLookupString(&event.xkey, buf, sizeof(buf), &keySym, &stat);
|
||||
switch (keySym) {
|
||||
case XK_Escape:
|
||||
exit(0);
|
||||
return;
|
||||
break;
|
||||
case XK_d:
|
||||
case XK_D:
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
# src/egl/Makefile
|
||||
|
||||
TOP = ../..
|
||||
|
||||
SUBDIRS = main drivers/demo drivers/dri
|
||||
|
||||
|
||||
default: subdirs
|
||||
|
||||
|
||||
subdirs:
|
||||
@for dir in $(SUBDIRS) ; do \
|
||||
if [ -d $$dir ] ; then \
|
||||
(cd $$dir && $(MAKE)) || exit 1 ; \
|
||||
fi \
|
||||
done
|
||||
|
||||
|
||||
clean:
|
||||
-@for dir in $(SUBDIRS) ; do \
|
||||
if [ -d $$dir ] ; then \
|
||||
(cd $$dir && $(MAKE) clean) ; \
|
||||
fi \
|
||||
done
|
||||
@@ -1,564 +0,0 @@
|
||||
Name
|
||||
|
||||
MESA_screen_surface
|
||||
|
||||
Name Strings
|
||||
|
||||
EGL_MESA_screen_surface
|
||||
|
||||
Contact
|
||||
|
||||
Brian Paul
|
||||
|
||||
To discuss, join the dri-egl@lists.freedesktop.org list.
|
||||
|
||||
Status
|
||||
|
||||
Preliminary - totally subject to change.
|
||||
|
||||
Version
|
||||
|
||||
11 (27 January 2006)
|
||||
|
||||
Number
|
||||
|
||||
TBD
|
||||
|
||||
Dependencies
|
||||
|
||||
EGL 1.0 or later.
|
||||
|
||||
Overview
|
||||
|
||||
EGL 1.1 supports three types of drawing surfaces:
|
||||
* Window surfaces
|
||||
* Pixmap surfaces
|
||||
* Pbuffer surfaces
|
||||
This extension defines a fourth type of drawing surface:
|
||||
* Screen surface
|
||||
|
||||
A screen surface is a surface for which the (front) color buffer can
|
||||
be directly displayed (i.e. scanned out) on a monitor (such as a flat
|
||||
panel or CRT). In particular the color buffer memory will be allocated
|
||||
at a location in VRAM (and in a suitable format) which can be displayed
|
||||
by the graphics hardware.
|
||||
|
||||
Note that the width and height of the screen surface need not exactly
|
||||
match the monitor's current resolution. For example, while the monitor
|
||||
may be configured to to show 1024x768 pixels, the associated screen
|
||||
surface may be larger, such as 1200x1000. The "screen origin" attribute
|
||||
will specify which region of the screen surface which is visible on the
|
||||
monitor. The screen surface can be scrolled by changing this origin.
|
||||
|
||||
This extension also defines functions for controlling the monitor's
|
||||
display mode (width, height, refresh rate, etc), and specifing which
|
||||
screen surface is to be displayed on a monitor.
|
||||
|
||||
The new EGLModeMESA type and related functions are very similar to the
|
||||
EGLConfig type and related functions. The user may get a list of
|
||||
supported modes for a screen and specify the mode to be used when
|
||||
displaying a screen surface.
|
||||
|
||||
|
||||
Issues
|
||||
|
||||
1. Should EGL_INTERLACE be a supported mode attribute?
|
||||
|
||||
Arguments against:
|
||||
|
||||
No, this should be provided by another extension which would
|
||||
also provide the mechanisms needed to play back interlaced video
|
||||
material correctly on hardware that supports it.
|
||||
This extension should prefer non-interlaced modes. [M. Danzer]
|
||||
|
||||
Arguments for:
|
||||
|
||||
An interlaced display can be of use without considering video
|
||||
material. Being able to query whether a screen is operating in
|
||||
interlaced mode can be used by applications to control their
|
||||
drawing. For example: avoid drawing 1-pixel-wide horizontal lines
|
||||
if screen is interlaced. [B. Paul]
|
||||
|
||||
Resolution: Defer for future extension?
|
||||
|
||||
|
||||
2. Should EGL_REFRESH_RATE be a supported mode attribute?
|
||||
|
||||
Arguments for:
|
||||
|
||||
Yes, it's been shown that applications and/or users need to select
|
||||
modes by this. [M. Danzer]
|
||||
|
||||
Many examples have been given in which it's desirable to let the
|
||||
user choose from a variety of refresh rates without having to
|
||||
restart/reconfigure. [B. Paul]
|
||||
|
||||
Arguments against:
|
||||
|
||||
TBD.
|
||||
|
||||
Resolution: Yes.
|
||||
|
||||
|
||||
3. Exactly how should the list of modes returned by eglChooseConfigMESA
|
||||
be sorted?
|
||||
|
||||
Current method is described in the text below. Subject to change.
|
||||
|
||||
Alternately, leave the sorting order undefined so that each
|
||||
implementation can return the modes in order of "most desirable"
|
||||
to "least desirable" which may depend on the display technology
|
||||
(CRT vs LCD, etc) or other factors.
|
||||
|
||||
|
||||
4. How should screen blanking be supported? Note that a screen can be
|
||||
disabled or turned off by calling eglShowSurface(dpy, scrn,
|
||||
EGL_NO_SURFACE, EGL_NO_MODE_MESA). But what about power-save mode?
|
||||
|
||||
I would defer this to other extensions that depend on this one.
|
||||
I can imagine people wanting different semantics not just in
|
||||
relation to the power management API being exposed (DPMS or whatever)
|
||||
but also relating to what events can trigger EGL_CONTEXT_LOST. Also
|
||||
I'm not sure whether power management commands are properly operations
|
||||
on the Display or on a screen surface. [A. Jackson]
|
||||
|
||||
|
||||
5. Should the EGL_PHYSICAL_SIZE_EGL query be kept? The size information
|
||||
isn't always reliable (consider video projectors) but can still be
|
||||
used to determine the pixel aspect ratio.
|
||||
|
||||
Resolution: Omit. The EGL 1.2 specification includes queries for
|
||||
the display resolution and pixel aspect ratio.
|
||||
|
||||
|
||||
6. Should detailed mode timing information be exposed by this API?
|
||||
|
||||
Probably not. Instead, offer that information in a layered extension.
|
||||
|
||||
|
||||
7. How should the notion of a screen's "native" mode be expressed?
|
||||
For example, LCD panels have a native resolution and refresh rate
|
||||
that looks best but other sub-optimal resolutions may be supported.
|
||||
|
||||
The mode attribute EGL_OPTIMAL_MESA will be set for modes which
|
||||
best match the screen. [M. Danzer]
|
||||
|
||||
|
||||
8. Should eglQueryModeStringMESA() be included? This function returns
|
||||
a human-readable string which corresponds to an EGLMode.
|
||||
|
||||
Arguments for:
|
||||
|
||||
A mode name such as "HDTV-720P" might mean more to users than
|
||||
"1280x720@60Hz" if the later were generated via code.
|
||||
|
||||
Arguments against:
|
||||
|
||||
There's no standard syntax for the strings. May cause more
|
||||
trouble than it's worth.
|
||||
|
||||
Postpone for future extension. [A. Jackson]
|
||||
|
||||
Latest discussion leaning toward omitting this function.
|
||||
|
||||
|
||||
9. Should we use "Get" or "Query" for functions which return state?
|
||||
The EGL 1.x specification doesn't seem to be totally consistent
|
||||
in this regard, but "Query" is used more often.
|
||||
|
||||
Use "Get" for mode-related queries (as for EGLConfigs) but "Query"
|
||||
for everything else.
|
||||
|
||||
|
||||
10. What should be the default size for screen surfaces?
|
||||
|
||||
For Pbuffer surfaces the default width and height are zero.
|
||||
We'll do the same for screen surfaces. Since there's no function
|
||||
to resize surfaces it's useless to have a 0x0 screen, but this isn't
|
||||
a situation that'll normally be encountered.
|
||||
|
||||
|
||||
11. Should there be a function for resizing a screen surface?
|
||||
|
||||
Suppose one wants to change the screen's size in the EGL application.
|
||||
Also suppose there's a hardware restriction such that only one screen
|
||||
surface can exist at a time (either for lack of memory or because of
|
||||
memory layout restrictions).
|
||||
|
||||
The basic idea is that the currently displayed screen surface must
|
||||
be deallocated before a new one can be created. Perhaps a resize
|
||||
function would work better?
|
||||
|
||||
|
||||
12. How should sub-pixel LCD color information be made available?
|
||||
What about the display's gamma value?
|
||||
|
||||
Perhaps expose as additional read-only mode attributes.
|
||||
|
||||
Perhaps postpone for a layered extension.
|
||||
|
||||
|
||||
13. What happens if the user attempts to delete a screen surface that
|
||||
is currently being shown?
|
||||
|
||||
Spec currently says that's illegal and that an error (TBD) will be
|
||||
generated.
|
||||
|
||||
|
||||
14. What if the physical screen size can't be determined? Should
|
||||
a query of EGL_PHYSICAL_SIZE_MESA return [0,0]?
|
||||
|
||||
Obsolete: EGL_PHYSICAL_SIZE_MESA not used.
|
||||
|
||||
|
||||
15. Suppose the device's number of RAMDACs is different from the
|
||||
number of output ports. For example, a graphics card with
|
||||
two RAMDACs but three ports (VGA, DVI, TV).
|
||||
|
||||
Address this in a follow-on extension. [Matthias Hopf]
|
||||
|
||||
|
||||
16. How should we deal with on-the-fly device changes? For example,
|
||||
the monitor being unplugged and replaced by another with different
|
||||
characteristics?
|
||||
|
||||
A HAL event could be received via DBUS in the application [J. Smirl,
|
||||
A. Jackson].
|
||||
|
||||
Should there be an EGL mechanism for detecting this? Maybe an
|
||||
EGL_SCREEN_LOST error (similar to EGL_CONTEXT_LOST) can be recorded
|
||||
when there's a screen change. At least then the application can
|
||||
poll to detect this situation.
|
||||
|
||||
Maybe leave that to a future extension.
|
||||
|
||||
See also the EGL_SCREEN_COUNT_MESA query.
|
||||
|
||||
|
||||
17. What if pixel-accurate panning is not supported (see
|
||||
eglScreenPositionMESA)? [M. Danzer]
|
||||
|
||||
Is this a common problem? Can we ignore it for now?
|
||||
|
||||
|
||||
18. Should eglShowSurfaceMESA be renamed to eglShowScreenSurfaceMESA?
|
||||
|
||||
Probably.
|
||||
|
||||
|
||||
|
||||
New Procedures and Functions
|
||||
|
||||
EGLBoolean eglChooseModeMESA(EGLDisplay dpy, EGLScreenMESA screen,
|
||||
const EGLint *attrib_list,
|
||||
EGLModeMESA *modes, EGLint modes_size,
|
||||
EGLint *num_modes)
|
||||
|
||||
EGLBoolean eglGetModesMESA(EGLDisplay dpy, EGLScreenMESA screen,
|
||||
EGLModeMESA *modes, EGLint modes_size,
|
||||
EGLint *num_modes)
|
||||
|
||||
EGLBoolean eglGetModeAttribMESA(EGLDisplay dpy, EGLModeMESA mode,
|
||||
EGLint attrib, EGLint *value)
|
||||
|
||||
|
||||
EGLBoolean eglGetScreensMESA(EGLDisplay dpy, EGLScreenMESA *screens,
|
||||
EGLint screens_size, EGLint *num_screens)
|
||||
|
||||
EGLSurface eglCreateScreenSurfaceMESA(EGLDisplay dpy, EGLConfig config,
|
||||
const EGLint *attrib_list)
|
||||
|
||||
EGLBoolean eglShowSurfaceMESA(EGLDisplay dpy, EGLScreenMESA screen,
|
||||
EGLSurface surface, EGLModeMESA mode)
|
||||
|
||||
EGLBoolean eglScreenPositionMESA(EGLDisplay dpy, EGLScreenMESA screen,
|
||||
EGLint x, EGLint y)
|
||||
|
||||
|
||||
EGLBoolean eglQueryScreenMESA(EGLDisplay dpy, EGLScreenMESA screen,
|
||||
EGLint attrib, EGLint *value);
|
||||
|
||||
EGLBoolean eglQueryScreenSurfaceMESA(EGLDisplay dpy, EGLScreenMESA screen,
|
||||
EGLSurface *surface)
|
||||
|
||||
EGLBoolean eglQueryScreenModeMESA(EGLDisplay dpy, EGLScreenMESA screen,
|
||||
EGLModeMESA *mode)
|
||||
|
||||
const char *eglQueryModeStringMESA(EGLDisplay dpy, EGLMode mode);
|
||||
|
||||
|
||||
New Types
|
||||
|
||||
EGLModeMESA
|
||||
EGLScreenMESA
|
||||
|
||||
New Tokens
|
||||
|
||||
New error codes:
|
||||
|
||||
EGL_BAD_SCREEN_MESA
|
||||
EGL_BAD_MODE_MESA
|
||||
|
||||
Screen-related tokens:
|
||||
|
||||
EGL_SCREEN_COUNT_MESA
|
||||
EGL_SCREEN_POSITION_MESA
|
||||
EGL_SCREEN_BIT_MESA
|
||||
EGL_SCREEN_POSITION_GRANULARITY_MESA
|
||||
|
||||
Mode-related tokens:
|
||||
|
||||
EGL_MODE_ID_MESA
|
||||
EGL_REFRESH_RATE_MESA
|
||||
EGL_INTERLACED_MESA
|
||||
EGL_OPTIMAL_MESA
|
||||
EGL_NO_MODE_MESA
|
||||
|
||||
|
||||
Additions to Chapter X of the EGL 1.1 Specification
|
||||
|
||||
[XXX this all has to be rewritten to fit into the EGL specification
|
||||
and match the conventions of an EGL extension. For now, just list
|
||||
all the functions with brief descriptions.]
|
||||
|
||||
|
||||
EGLBoolean eglChooseModeMESA(EGLDisplay dpy, const EGLScreenMESA screen,
|
||||
EGLint *attrib_list, EGLModeMESA *modes,
|
||||
EGLint modes_size, EGLint *num_modes)
|
||||
|
||||
Like eglChooseConfig, returns a list of EGLModes which match the given
|
||||
attribute list. This does not set the screen's current display mode.
|
||||
The attribute list is a list of token/value pairs terminated with
|
||||
EGL_NONE. Supported attributes include:
|
||||
|
||||
Name Description
|
||||
--------------------- ---------------------------------------------
|
||||
EGL_WIDTH Mode width (resolution)
|
||||
EGL_HEIGHT Mode height (resolution)
|
||||
EGL_REFRESH_RATE_MESA The mode's refresh rate, multiplied by 1000
|
||||
EGL_INTERLACED_MESA 1 indicates an interlaced mode, 0 otherwise
|
||||
EGL_OPTIMAL_MESA Set if the most is especially optimal for the
|
||||
screen (ex. for particular LCD resolutions)
|
||||
|
||||
Any other token will generate the error EGL_BAD_ATTRIBUTE.
|
||||
|
||||
The list of modes returned by eglChooseModeMESA will be sorted
|
||||
according to the following criteria. See the discussion of table 3.3
|
||||
in the EGL specification for more information.
|
||||
|
||||
Selection Sort Sort
|
||||
Attribute Default Criteria Order Priority
|
||||
-------------------- -------------- ----------- ------ --------
|
||||
EGL_OPTIMAL_MESA EGL_DONT_CARE Exact 1,0 1
|
||||
EGL_INTERLACED_MESA EGL_DONT_CARE Exact 0,1 2
|
||||
EGL_REFRESH_RATE EGL_DONT_CARE AtLeast Larger 3
|
||||
EGL_WIDTH EGL_DONT_CARE AtLeast Larger 4
|
||||
EGL_HEIGHT EGL_DONT_CARE AtLeast Larger 5
|
||||
EGL_MODE_ID_MESA EGL_DONT_CARE Exact Smaller 6
|
||||
|
||||
|
||||
EGLBoolean eglGetModesMESA(EGLDisplay dpy, EGLScreenMESA screen,
|
||||
EGLModeMESA *modes, EGLint modes_size,
|
||||
EGLint *num_modes)
|
||||
|
||||
Like eglGetConfigs, returns a list of all modes supported by the
|
||||
given screen. The returned modes will be sorted in the same manner
|
||||
as for eglChooseModeMESA().
|
||||
|
||||
|
||||
|
||||
EGLBoolean eglGetModeAttribMESA(EGLDisplay dpy, EGLModeMESA mode,
|
||||
EGLint attrib, EGLint *value)
|
||||
|
||||
Used to query mode attributes. The following attributes are supported:
|
||||
|
||||
Name Return value description
|
||||
--------------------- ----------------------------------------------
|
||||
EGL_OPTIMAL_MESA 1 indicates an optimal mode, 0 otherwise
|
||||
EGL_INTERLACED_MESA 1 indicates an interlaced mode, 0 otherwise
|
||||
EGL_REFRESH_RATE_MESA The mode's refresh rate, multiplied by 1000
|
||||
EGL_WIDTH Mode width (resolution)
|
||||
EGL_HEIGHT Mode height (resolution)
|
||||
EGL_MODE_ID_MESA A unique small integer identifier for the mode
|
||||
|
||||
Any other token will generate the error EGL_BAD_ATTRIBUTE.
|
||||
|
||||
|
||||
|
||||
EGLBoolean eglGetScreensMESA(EGLDisplay dpy, EGLScreenMESA *screens,
|
||||
EGLint screens_size, EGLint *num_screens)
|
||||
|
||||
This function returns an array of all available screen handles.
|
||||
<screens_size> is the maximum number of screens to return in the
|
||||
<screens> array. <num_screens> will return the number of screen handles
|
||||
placed in the array, even if <screens> is NULL.
|
||||
|
||||
The number of screens and the availability of each may change over
|
||||
time (hot-plugging). Screen handles will not be reused. When a
|
||||
screen handle becomes invalid, function calls which reference an
|
||||
invalid handle will generate EGL_BAD_SCREEN_MESA.
|
||||
|
||||
The first screen handle returned will be considered to be the primary
|
||||
one.
|
||||
|
||||
|
||||
|
||||
EGLSurface eglCreateScreenSurfaceMESA(EGLDisplay dpy, EGLConfig config,
|
||||
const EGLint *attrib_list)
|
||||
|
||||
Create a surface that can be displayed on a screen. <attrib_list> is
|
||||
an array of token/value pairs terminated with EGL_NONE. Valid tokens
|
||||
include:
|
||||
|
||||
Name Description
|
||||
---------------- --------------------------------
|
||||
EGL_WIDTH desired surface width in pixels
|
||||
EGL_HEIGHT desired surface height in pixels
|
||||
|
||||
Any other token will generate the error EGL_BAD_ATTRIBUTE.
|
||||
The default width and height are zero.
|
||||
|
||||
|
||||
|
||||
EGLBoolean eglShowSurfaceMESA(EGLDisplay dpy, EGLScreenMESA screen,
|
||||
EGLSurface surface, EGLModeMESA mode)
|
||||
|
||||
This function causes a screen to show the given surface (or more
|
||||
precisely, the surface's front color buffer) with the given mode.
|
||||
|
||||
If the surface is in any way incompatible with the mode, the error
|
||||
EGL_BAD_MATCH will be generated, EGL_FALSE will be returned, and the
|
||||
previous screen state will remain in effect. This might occur when
|
||||
the bandwidth of the video-out subsystem is exceeded, or if the mode
|
||||
specifies a width or height that's greater than the width or height
|
||||
of the surface.
|
||||
|
||||
To disable a screen, the values EGL_NO_SURFACE and EGL_NO_MODE_MESA
|
||||
be passed as the <surface> and <mode> parameters.
|
||||
|
||||
The values of EGL_SCREEN_POSITION_MESA are clamped to the new valid
|
||||
range computed from the screen size and surface size. If the new
|
||||
surface is EGL_NO_SURFACE, EGL_SCREEN_POSITION_MESA is set to [0, 0].
|
||||
|
||||
|
||||
Attempting to delete a screen surface which is currently being
|
||||
displayed will result in the error EGL_BAD_ACCESS being generated.
|
||||
|
||||
|
||||
|
||||
EGLBoolean eglScreenPositionMESA(EGLDisplay dpy, EGLScreenMESA screen,
|
||||
EGLint x, EGLint y)
|
||||
|
||||
Specifies the origin of the screen's view into the surface, if the
|
||||
surface is larger than the screen. Valid values for x and y are
|
||||
[0, surfaceWidth - screenWidth] and [0, surfaceHeight - screenHeight],
|
||||
respectively.
|
||||
|
||||
The x and y values are also constrained to be integer multiples of the
|
||||
EGL_SCREEN_POSITION_GRANULARITY_MESA values.
|
||||
|
||||
|
||||
|
||||
|
||||
EGLBoolean eglQueryScreenMESA(EGLDisplay dpy, EGLScreenMESA screen,
|
||||
EGLint attrib, EGLint *value);
|
||||
|
||||
Used to query screen attributes. <attrib> may be one of the following:
|
||||
|
||||
Name Return value description
|
||||
------------------------ ---------------------------------------------
|
||||
EGL_SCREEN_POSITION_MESA x, y position of the screen's origin with
|
||||
respect to the surface. If no surface is
|
||||
attached to the screen, [0, 0] is returned.
|
||||
EGL_SCREEN_POSITION_GRANULARITY_MESA
|
||||
Returns the granularity, in pixels, for
|
||||
which the screen position is constrained.
|
||||
|
||||
Any other token will generate the error EGL_BAD_ATTRIBUTE.
|
||||
|
||||
|
||||
|
||||
|
||||
EGLBoolean eglQueryScreenSurfaceMESA(EGLDisplay dpy, EGLScreenMESA screen,
|
||||
EGLSurface *surface)
|
||||
|
||||
Returns the surface currently displayed on the given screen. <surface>
|
||||
may be EGL_NO_SURFACE if the screen isn't currently showing any surface.
|
||||
|
||||
|
||||
|
||||
|
||||
EGLBoolean eglQueryScreenModeMESA(EGLDisplay dpy, EGLScreenMESA screen,
|
||||
EGLModeMESA *mode)
|
||||
|
||||
Returns the given screen's current display mode. The mode may be
|
||||
EGL_NO_MODE_MESA if the screen is currently disabled.
|
||||
|
||||
|
||||
|
||||
const char *eglQueryModeStringMESA(EGLDisplay dpy, EGLModeMESA mode);
|
||||
|
||||
Returns a human-readable string for the given mode. The string is a
|
||||
zero-terminated C string which the user should not attempt to free.
|
||||
There is no standard syntax for mode strings. Applications should
|
||||
not directly rely on mode strings.
|
||||
|
||||
|
||||
|
||||
Version History
|
||||
|
||||
1. 15 March 2005 - BrianP
|
||||
Initial version
|
||||
|
||||
2. 16 March 2005 - BrianP
|
||||
Removed EGL_DEPTH_MESA
|
||||
Added EGL_PHYSICAL_WIDTH_MESA, EGL_PHYSICAL_HEIGHT_MESA queries
|
||||
Added EGL_OPTIMAL_MESA for width/height/refresh rate selection
|
||||
Added possible eglQueryModeStringMESA() function
|
||||
More details of the new functions explained.
|
||||
|
||||
3. 18 March 2005 - BrianP
|
||||
Added screen_number to eglChooseModeMESA().
|
||||
Fix off by one mistake in value range for ORIGIN attributes
|
||||
Added Issues section
|
||||
|
||||
4. 21 March 2005 - BrianP
|
||||
Removed eglScreenAttribsMESA().
|
||||
Added eglScreenPositionMESA() to set screen origin.
|
||||
Replaced EGL_SCREEN_X/Y_OFFSET_MESA with EGL_SCREEN_POSITION_MESA.
|
||||
Replaced EGL_PHYSICAL_WIDTH/HEIGHT_MESA with EGL_PHYSICAL_SIZE_MESA.
|
||||
Use EGL_OPTIMAL_MESA as a new mode attribute. (Michel Danzer)
|
||||
Added a few more issues.
|
||||
|
||||
5. 6 April 2005 - BrianP
|
||||
More language for eglGetModeStringMESA().
|
||||
Added issues 10, 11, 12, 13, 14.
|
||||
Updated issue 3 discussion about mode sorting.
|
||||
|
||||
6. 22 April 2005 - BrianP
|
||||
Fixed "LDC" typo.
|
||||
Added issues 15, 16.
|
||||
Changed dependency on EGL 1.1 to EGL 1.0
|
||||
s/EGL_NUM_SCREENS_MESA/EGL_SCREEN_COUNT_MESA/
|
||||
Added eglQueryDisplayMESA() to New Functions section.
|
||||
Clarified language for the EGL_SCREEN_COUNT_MESA query.
|
||||
|
||||
7. 29 April 2005 - BrianP
|
||||
Added EGLScreenMESA type and eglGetScreensMESA() function. [J. Smirl].
|
||||
Replaced EGLint screen_number parameters with EGLScreenMESA screen.
|
||||
Added issue 17 (pixel-accurate panning)
|
||||
|
||||
8. 2 May 2005 - BrianP
|
||||
Removed eglQueryDisplayMESA.
|
||||
Fixed a few more EGLint -> EGLScreenMESA changes.
|
||||
|
||||
9. 20 May 2005 - BrianP
|
||||
Fixed a few typos.
|
||||
Updated some open issues text.
|
||||
|
||||
10. 10 August 2005 - BrianP
|
||||
Added EGL_SCREEN_POSITION_GRANULARITY_MESA.
|
||||
|
||||
11. 27 January 2006 - BrianP
|
||||
EGL_PHYSICAL_SIZE_MESA removed since EGL 1.2 has a similar feature.
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
# src/egl/drivers/demo/Makefile
|
||||
|
||||
TOP = ../../../..
|
||||
include $(TOP)/configs/current
|
||||
|
||||
|
||||
INCLUDE_DIRS = -I$(TOP)/include -I$(TOP)/src/egl/main
|
||||
|
||||
|
||||
SOURCES = demo.c
|
||||
|
||||
OBJECTS = $(SOURCES:.c=.o)
|
||||
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@
|
||||
|
||||
|
||||
|
||||
default: $(TOP)/$(LIB_DIR)/demodriver.so
|
||||
|
||||
|
||||
$(TOP)/$(LIB_DIR)/demodriver.so: $(OBJECTS)
|
||||
$(MKLIB) -o demodriver.so -noprefix -linker '$(CC)' \
|
||||
-ldflags '$(LDFLAGS)' -install $(TOP)/$(LIB_DIR) \
|
||||
$(OBJECTS)
|
||||
|
||||
|
||||
|
||||
clean:
|
||||
-rm -f *.o
|
||||
-rm -f *.so
|
||||
@@ -1,316 +0,0 @@
|
||||
/*
|
||||
* Sample driver: Demo
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "eglconfig.h"
|
||||
#include "eglcontext.h"
|
||||
#include "egldisplay.h"
|
||||
#include "egldriver.h"
|
||||
#include "eglglobals.h"
|
||||
#include "eglmode.h"
|
||||
#include "eglscreen.h"
|
||||
#include "eglsurface.h"
|
||||
|
||||
|
||||
/**
|
||||
* Demo driver-specific driver class derived from _EGLDriver
|
||||
*/
|
||||
typedef struct demo_driver
|
||||
{
|
||||
_EGLDriver Base; /* base class/object */
|
||||
GLuint DemoStuff;
|
||||
} DemoDriver;
|
||||
|
||||
#define DEMO_DRIVER(D) ((DemoDriver *) (D))
|
||||
|
||||
|
||||
/**
|
||||
* Demo driver-specific surface class derived from _EGLSurface
|
||||
*/
|
||||
typedef struct demo_surface
|
||||
{
|
||||
_EGLSurface Base; /* base class/object */
|
||||
GLuint DemoStuff;
|
||||
} DemoSurface;
|
||||
|
||||
|
||||
/**
|
||||
* Demo driver-specific context class derived from _EGLContext
|
||||
*/
|
||||
typedef struct demo_context
|
||||
{
|
||||
_EGLContext Base; /* base class/object */
|
||||
GLuint DemoStuff;
|
||||
} DemoContext;
|
||||
|
||||
|
||||
|
||||
static EGLBoolean
|
||||
demoInitialize(_EGLDriver *drv, EGLDisplay dpy, EGLint *major, EGLint *minor)
|
||||
{
|
||||
_EGLDisplay *disp = _eglLookupDisplay(dpy);
|
||||
_EGLScreen *scrn;
|
||||
EGLint i;
|
||||
|
||||
/* Create a screen */
|
||||
scrn = calloc(1, sizeof(*scrn));
|
||||
_eglAddScreen(disp, scrn);
|
||||
|
||||
/* Create the screen's modes - silly example */
|
||||
_eglAddNewMode(scrn, 1600, 1200, 72 * 1000, "1600x1200-72");
|
||||
_eglAddNewMode(scrn, 1280, 1024, 72 * 1000, "1280x1024-70");
|
||||
_eglAddNewMode(scrn, 1280, 1024, 70 * 1000, "1280x1024-70");
|
||||
_eglAddNewMode(scrn, 1024, 768, 72 * 1000, "1024x768-72");
|
||||
|
||||
/* Create the display's visual configs - silly example */
|
||||
for (i = 0; i < 4; i++) {
|
||||
_EGLConfig config;
|
||||
_eglInitConfig(&config, i + 1);
|
||||
_eglSetConfigAttrib(&config, EGL_RED_SIZE, 8);
|
||||
_eglSetConfigAttrib(&config, EGL_GREEN_SIZE, 8);
|
||||
_eglSetConfigAttrib(&config, EGL_BLUE_SIZE, 8);
|
||||
_eglSetConfigAttrib(&config, EGL_ALPHA_SIZE, 8);
|
||||
_eglSetConfigAttrib(&config, EGL_BUFFER_SIZE, 32);
|
||||
if (i & 1) {
|
||||
_eglSetConfigAttrib(&config, EGL_DEPTH_SIZE, 32);
|
||||
}
|
||||
if (i & 2) {
|
||||
_eglSetConfigAttrib(&config, EGL_STENCIL_SIZE, 8);
|
||||
}
|
||||
_eglSetConfigAttrib(&config, EGL_SURFACE_TYPE,
|
||||
(EGL_WINDOW_BIT | EGL_PIXMAP_BIT | EGL_PBUFFER_BIT));
|
||||
_eglAddConfig(disp, &config);
|
||||
}
|
||||
|
||||
drv->Initialized = EGL_TRUE;
|
||||
|
||||
*major = 1;
|
||||
*minor = 0;
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
static EGLBoolean
|
||||
demoTerminate(_EGLDriver *drv, EGLDisplay dpy)
|
||||
{
|
||||
/*DemoDriver *demo = DEMO_DRIVER(dpy);*/
|
||||
free(drv);
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
static DemoContext *
|
||||
LookupDemoContext(EGLContext ctx)
|
||||
{
|
||||
_EGLContext *c = _eglLookupContext(ctx);
|
||||
return (DemoContext *) c;
|
||||
}
|
||||
|
||||
|
||||
static DemoSurface *
|
||||
LookupDemoSurface(EGLSurface surf)
|
||||
{
|
||||
_EGLSurface *s = _eglLookupSurface(surf);
|
||||
return (DemoSurface *) s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static EGLContext
|
||||
demoCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list)
|
||||
{
|
||||
_EGLConfig *conf;
|
||||
DemoContext *c;
|
||||
int i;
|
||||
|
||||
conf = _eglLookupConfig(drv, dpy, config);
|
||||
if (!conf) {
|
||||
_eglError(EGL_BAD_CONFIG, "eglCreateContext");
|
||||
return EGL_NO_CONTEXT;
|
||||
}
|
||||
|
||||
for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
|
||||
switch (attrib_list[i]) {
|
||||
/* no attribs defined for now */
|
||||
default:
|
||||
_eglError(EGL_BAD_ATTRIBUTE, "eglCreateContext");
|
||||
return EGL_NO_CONTEXT;
|
||||
}
|
||||
}
|
||||
|
||||
c = (DemoContext *) calloc(1, sizeof(DemoContext));
|
||||
if (!c)
|
||||
return EGL_NO_CONTEXT;
|
||||
|
||||
_eglInitContext(drv, dpy, &c->Base, config, attrib_list);
|
||||
c->DemoStuff = 1;
|
||||
printf("demoCreateContext\n");
|
||||
|
||||
/* generate handle and insert into hash table */
|
||||
_eglSaveContext(&c->Base);
|
||||
assert(c->Base.Handle);
|
||||
|
||||
return c->Base.Handle;
|
||||
}
|
||||
|
||||
|
||||
static EGLSurface
|
||||
demoCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint *attrib_list)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
|
||||
switch (attrib_list[i]) {
|
||||
/* no attribs at this time */
|
||||
default:
|
||||
_eglError(EGL_BAD_ATTRIBUTE, "eglCreateWindowSurface");
|
||||
return EGL_NO_SURFACE;
|
||||
}
|
||||
}
|
||||
printf("eglCreateWindowSurface()\n");
|
||||
/* XXX unfinished */
|
||||
|
||||
return EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
|
||||
static EGLSurface
|
||||
demoCreatePixmapSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativePixmapType pixmap, const EGLint *attrib_list)
|
||||
{
|
||||
_EGLConfig *conf;
|
||||
EGLint i;
|
||||
|
||||
conf = _eglLookupConfig(drv, dpy, config);
|
||||
if (!conf) {
|
||||
_eglError(EGL_BAD_CONFIG, "eglCreatePixmapSurface");
|
||||
return EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
|
||||
switch (attrib_list[i]) {
|
||||
/* no attribs at this time */
|
||||
default:
|
||||
_eglError(EGL_BAD_ATTRIBUTE, "eglCreatePixmapSurface");
|
||||
return EGL_NO_SURFACE;
|
||||
}
|
||||
}
|
||||
|
||||
if (conf->Attrib[EGL_SURFACE_TYPE - FIRST_ATTRIB] == 0) {
|
||||
_eglError(EGL_BAD_MATCH, "eglCreatePixmapSurface");
|
||||
return EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
printf("eglCreatePixmapSurface()\n");
|
||||
return EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
|
||||
static EGLSurface
|
||||
demoCreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
|
||||
const EGLint *attrib_list)
|
||||
{
|
||||
DemoSurface *surf = (DemoSurface *) calloc(1, sizeof(DemoSurface));
|
||||
if (!surf)
|
||||
return EGL_NO_SURFACE;
|
||||
|
||||
if (!_eglInitSurface(drv, dpy, &surf->Base, EGL_PBUFFER_BIT,
|
||||
config, attrib_list)) {
|
||||
free(surf);
|
||||
return EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
/* a real driver would allocate the pbuffer memory here */
|
||||
|
||||
return surf->Base.Handle;
|
||||
}
|
||||
|
||||
|
||||
static EGLBoolean
|
||||
demoDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
|
||||
{
|
||||
DemoSurface *fs = LookupDemoSurface(surface);
|
||||
_eglRemoveSurface(&fs->Base);
|
||||
if (fs->Base.IsBound) {
|
||||
fs->Base.DeletePending = EGL_TRUE;
|
||||
}
|
||||
else {
|
||||
free(fs);
|
||||
}
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
static EGLBoolean
|
||||
demoDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext context)
|
||||
{
|
||||
DemoContext *fc = LookupDemoContext(context);
|
||||
_eglRemoveContext(&fc->Base);
|
||||
if (fc->Base.IsBound) {
|
||||
fc->Base.DeletePending = EGL_TRUE;
|
||||
}
|
||||
else {
|
||||
free(fc);
|
||||
}
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
static EGLBoolean
|
||||
demoMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext context)
|
||||
{
|
||||
/*DemoDriver *demo = DEMO_DRIVER(dpy);*/
|
||||
DemoSurface *readSurf = LookupDemoSurface(read);
|
||||
DemoSurface *drawSurf = LookupDemoSurface(draw);
|
||||
DemoContext *ctx = LookupDemoContext(context);
|
||||
EGLBoolean b;
|
||||
|
||||
b = _eglMakeCurrent(drv, dpy, draw, read, context);
|
||||
if (!b)
|
||||
return EGL_FALSE;
|
||||
|
||||
/* XXX this is where we'd do the hardware context switch */
|
||||
(void) drawSurf;
|
||||
(void) readSurf;
|
||||
(void) ctx;
|
||||
|
||||
printf("eglMakeCurrent()\n");
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The bootstrap function. Return a new DemoDriver object and
|
||||
* plug in API functions.
|
||||
*/
|
||||
_EGLDriver *
|
||||
_eglMain(_EGLDisplay *dpy)
|
||||
{
|
||||
DemoDriver *demo;
|
||||
|
||||
demo = (DemoDriver *) calloc(1, sizeof(DemoDriver));
|
||||
if (!demo) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* First fill in the dispatch table with defaults */
|
||||
_eglInitDriverFallbacks(&demo->Base);
|
||||
/* then plug in our Demo-specific functions */
|
||||
demo->Base.API.Initialize = demoInitialize;
|
||||
demo->Base.API.Terminate = demoTerminate;
|
||||
demo->Base.API.CreateContext = demoCreateContext;
|
||||
demo->Base.API.MakeCurrent = demoMakeCurrent;
|
||||
demo->Base.API.CreateWindowSurface = demoCreateWindowSurface;
|
||||
demo->Base.API.CreatePixmapSurface = demoCreatePixmapSurface;
|
||||
demo->Base.API.CreatePbufferSurface = demoCreatePbufferSurface;
|
||||
demo->Base.API.DestroySurface = demoDestroySurface;
|
||||
demo->Base.API.DestroyContext = demoDestroyContext;
|
||||
|
||||
/* enable supported extensions */
|
||||
demo->Base.Extensions.MESA_screen_surface = EGL_TRUE;
|
||||
demo->Base.Extensions.MESA_copy_context = EGL_TRUE;
|
||||
|
||||
return &demo->Base;
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
# src/egl/drivers/dri/Makefile
|
||||
|
||||
TOP = ../../../..
|
||||
include $(TOP)/configs/current
|
||||
|
||||
|
||||
### Include directories
|
||||
INCLUDE_DIRS = \
|
||||
-I. \
|
||||
-I/usr/include \
|
||||
-I/usr/include/drm \
|
||||
-I$(TOP)/include \
|
||||
-I$(TOP)/include/GL/internal \
|
||||
-I$(TOP)/src/mesa \
|
||||
-I$(TOP)/src/mesa/main \
|
||||
-I$(TOP)/src/mesa/glapi \
|
||||
-I$(TOP)/src/mesa/math \
|
||||
-I$(TOP)/src/mesa/transform \
|
||||
-I$(TOP)/src/mesa/shader \
|
||||
-I$(TOP)/src/mesa/swrast \
|
||||
-I$(TOP)/src/mesa/swrast_setup \
|
||||
-I$(TOP)/src/egl/main \
|
||||
-I$(TOP)/src/mesa/drivers/dri/common
|
||||
|
||||
|
||||
HEADERS = egldri.h
|
||||
|
||||
SOURCES = egldri.c
|
||||
|
||||
OBJECTS = $(SOURCES:.c=.o)
|
||||
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@
|
||||
|
||||
|
||||
|
||||
default: depend library Makefile
|
||||
|
||||
|
||||
# EGLdri Library
|
||||
library: $(TOP)/$(LIB_DIR)/libEGLdri.so
|
||||
|
||||
$(TOP)/$(LIB_DIR)/libEGLdri.so: $(OBJECTS)
|
||||
$(MKLIB) -o EGLdri -linker '$(CC)' -ldflags '$(LDFLAGS)' \
|
||||
-major 1 -minor 0 \
|
||||
-install $(TOP)/$(LIB_DIR) -ldl $(OBJECTS)
|
||||
|
||||
|
||||
clean:
|
||||
-rm -f *.o
|
||||
-rm -f *.so
|
||||
|
||||
depend: $(SOURCES) $(HEADERS)
|
||||
@ echo "running $(MKDEP)"
|
||||
@ touch depend
|
||||
$(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDE_DIRS) \
|
||||
$(SOURCES) $(HEADERS) > /dev/null
|
||||
|
||||
include depend
|
||||
# DO NOT DELETE
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,113 +0,0 @@
|
||||
#ifndef EGLDRI_INCLUDED
|
||||
#define EGLDRI_INCLUDED
|
||||
|
||||
#include "egldisplay.h"
|
||||
#include "eglscreen.h"
|
||||
#include "eglsurface.h"
|
||||
#include "eglcontext.h"
|
||||
#include "mtypes.h"
|
||||
#include "dri_util.h"
|
||||
#include "drm_sarea.h"
|
||||
|
||||
/**
|
||||
* dri display-specific driver class derived from _EGLDisplay
|
||||
*/
|
||||
typedef struct dri_display
|
||||
{
|
||||
_EGLDisplay Base; /* base class/object */
|
||||
void *pFB;
|
||||
int drmFD; /**< \brief DRM device file descriptor */
|
||||
int minor;
|
||||
unsigned long hFrameBuffer;
|
||||
|
||||
int virtualWidth;
|
||||
int virtualHeight;
|
||||
int fbSize;
|
||||
int bpp;
|
||||
int cpp;
|
||||
int card_type;
|
||||
int SAREASize;
|
||||
drm_sarea_t *pSAREA;
|
||||
unsigned int serverContext; /**< \brief DRM context only active on server */
|
||||
unsigned long FBStart; /**< \brief physical address of the framebuffer */
|
||||
void *driverClientMsg;
|
||||
int driverClientMsgSize;
|
||||
int chipset;
|
||||
void *driverPrivate;
|
||||
drm_magic_t magic;
|
||||
|
||||
__DRIscreen driScreen;
|
||||
|
||||
} driDisplay;
|
||||
|
||||
|
||||
/**
|
||||
* dri driver-specific screen class derived from _EGLScreen
|
||||
*/
|
||||
typedef struct dri_screen
|
||||
{
|
||||
_EGLScreen Base;
|
||||
char fb[NAME_MAX]; /** the screen name, like "fb0" */
|
||||
} driScreen;
|
||||
|
||||
|
||||
/**
|
||||
* dri driver-specific surface class derived from _EGLSurface
|
||||
*/
|
||||
typedef struct dri_surface
|
||||
{
|
||||
_EGLSurface Base; /* base class/object */
|
||||
__DRIdrawable drawable;
|
||||
} driSurface;
|
||||
|
||||
|
||||
/**
|
||||
* dri driver-specific context class derived from _EGLContext
|
||||
*/
|
||||
typedef struct dri_context
|
||||
{
|
||||
_EGLContext Base; /* base class/object */
|
||||
__DRIcontext driContext; /**< \brief context dependent methods */
|
||||
} driContext;
|
||||
|
||||
|
||||
|
||||
static inline driDisplay *
|
||||
Lookup_driDisplay(EGLDisplay dpy)
|
||||
{
|
||||
_EGLDisplay *d = _eglLookupDisplay(dpy);
|
||||
return (driDisplay *) d;
|
||||
}
|
||||
|
||||
|
||||
static inline driScreen *
|
||||
Lookup_driScreen(EGLDisplay dpy, EGLScreenMESA screen)
|
||||
{
|
||||
_EGLScreen *s = _eglLookupScreen(dpy, screen);
|
||||
return (driScreen *) s;
|
||||
}
|
||||
|
||||
|
||||
static inline driContext *
|
||||
Lookup_driContext(EGLContext ctx)
|
||||
{
|
||||
_EGLContext *c = _eglLookupContext(ctx);
|
||||
return (driContext *) c;
|
||||
}
|
||||
|
||||
|
||||
static inline driSurface *
|
||||
Lookup_driSurface(EGLSurface surf)
|
||||
{
|
||||
_EGLSurface *s = _eglLookupSurface(surf);
|
||||
return (driSurface *) s;
|
||||
}
|
||||
|
||||
extern void _eglDRIInitDriverFallbacks(_EGLDriver *drv);
|
||||
extern EGLBoolean _eglDRIShowScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLSurface surface, EGLModeMESA m);
|
||||
extern EGLBoolean _eglDRIInitialize(_EGLDriver *drv, EGLDisplay dpy, EGLint *major, EGLint *minor);
|
||||
extern EGLBoolean _eglDRIGetDisplayInfo(driDisplay *dpy);
|
||||
extern EGLBoolean _eglDRICreateDisplay(driDisplay *dpy, __DRIframebuffer *framebuffer);
|
||||
extern EGLBoolean _eglDRICreateScreens(driDisplay *dpy);
|
||||
|
||||
#endif /* EGLDRI_INCLUDED */
|
||||
@@ -1,67 +0,0 @@
|
||||
# src/egl/main/Makefile
|
||||
|
||||
TOP = ../../..
|
||||
include $(TOP)/configs/current
|
||||
|
||||
|
||||
INCLUDE_DIRS = -I$(TOP)/include -I$(TOP)/src/mesa/glapi
|
||||
|
||||
HEADERS = \
|
||||
eglconfig.h \
|
||||
eglcontext.h \
|
||||
egldisplay.h \
|
||||
egldriver.h \
|
||||
eglglobals.h \
|
||||
egllog.h \
|
||||
eglhash.h \
|
||||
eglmode.h \
|
||||
eglscreen.h \
|
||||
eglsurface.h
|
||||
|
||||
SOURCES = \
|
||||
eglapi.c \
|
||||
eglconfig.c \
|
||||
eglcontext.c \
|
||||
egldisplay.c \
|
||||
egldriver.c \
|
||||
eglglobals.c \
|
||||
egllog.c \
|
||||
eglhash.c \
|
||||
eglmode.c \
|
||||
eglscreen.c \
|
||||
eglsurface.c
|
||||
|
||||
OBJECTS = $(SOURCES:.c=.o)
|
||||
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@
|
||||
|
||||
|
||||
|
||||
default: depend library
|
||||
|
||||
|
||||
# EGL Library
|
||||
library: $(TOP)/$(LIB_DIR)/libEGL.so
|
||||
|
||||
$(TOP)/$(LIB_DIR)/libEGL.so: $(OBJECTS)
|
||||
$(MKLIB) -o EGL -linker '$(CC)' -ldflags '$(LDFLAGS)' \
|
||||
-major 1 -minor 0 \
|
||||
-install $(TOP)/$(LIB_DIR) -ldl $(OBJECTS)
|
||||
|
||||
|
||||
|
||||
clean:
|
||||
-rm -f *.o *.so*
|
||||
-rm -f core.*
|
||||
|
||||
|
||||
depend: $(SOURCES) $(HEADERS)
|
||||
@ echo "running $(MKDEP)"
|
||||
@ touch depend
|
||||
$(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDE_DIRS) \
|
||||
$(SOURCES) $(HEADERS) > /dev/null
|
||||
|
||||
include depend
|
||||
# DO NOT DELETE
|
||||
@@ -1,586 +0,0 @@
|
||||
/**
|
||||
* Public EGL API entrypoints
|
||||
*
|
||||
* Generally, we use the EGLDisplay parameter as a key to lookup the
|
||||
* appropriate device driver handle, then jump though the driver's
|
||||
* dispatch table to handle the function.
|
||||
*
|
||||
* That allows us the option of supporting multiple, simultaneous,
|
||||
* heterogeneous hardware devices in the future.
|
||||
*
|
||||
* The EGLDisplay, EGLConfig, EGLContext and EGLSurface types are
|
||||
* opaque handles implemented with 32-bit unsigned integers.
|
||||
* It's up to the driver function or fallback function to look up the
|
||||
* handle and get an object.
|
||||
* By using opaque handles, we leave open the possibility of having
|
||||
* indirect rendering in the future, like GLX.
|
||||
*
|
||||
*
|
||||
* Notes on naming conventions:
|
||||
*
|
||||
* eglFooBar - public EGL function
|
||||
* EGL_FOO_BAR - public EGL token
|
||||
* EGLDatatype - public EGL datatype
|
||||
*
|
||||
* _eglFooBar - private EGL function
|
||||
* _EGLDatatype - private EGL datatype, typedef'd struct
|
||||
* _egl_struct - private EGL struct, non-typedef'd
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "eglcontext.h"
|
||||
#include "egldisplay.h"
|
||||
#include "egltypedefs.h"
|
||||
#include "eglglobals.h"
|
||||
#include "egldriver.h"
|
||||
#include "eglsurface.h"
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* NOTE: displayName is treated as a string in _eglChooseDriver()!!!
|
||||
* This will probably change!
|
||||
* See _eglChooseDriver() for details!
|
||||
*/
|
||||
EGLDisplay APIENTRY
|
||||
eglGetDisplay(NativeDisplayType displayName)
|
||||
{
|
||||
_EGLDisplay *dpy;
|
||||
_eglInitGlobals();
|
||||
dpy = _eglNewDisplay(displayName);
|
||||
if (dpy)
|
||||
return dpy->Handle;
|
||||
else
|
||||
return EGL_NO_DISPLAY;
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean APIENTRY
|
||||
eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
|
||||
{
|
||||
if (dpy) {
|
||||
_EGLDriver *drv = _eglChooseDriver(dpy);
|
||||
if (drv)
|
||||
return drv->API.Initialize(drv, dpy, major, minor);
|
||||
}
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean APIENTRY
|
||||
eglTerminate(EGLDisplay dpy)
|
||||
{
|
||||
_EGLDriver *drv = _eglLookupDriver(dpy);
|
||||
if (drv)
|
||||
return _eglCloseDriver(drv, dpy);
|
||||
else
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
const char * APIENTRY
|
||||
eglQueryString(EGLDisplay dpy, EGLint name)
|
||||
{
|
||||
_EGLDriver *drv = _eglLookupDriver(dpy);
|
||||
if (drv)
|
||||
return drv->API.QueryString(drv, dpy, name);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean APIENTRY
|
||||
eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
|
||||
{
|
||||
_EGLDriver *drv = _eglLookupDriver(dpy);
|
||||
/* XXX check drv for null in remaining functions */
|
||||
return drv->API.GetConfigs(drv, dpy, configs, config_size, num_config);
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean APIENTRY
|
||||
eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
|
||||
{
|
||||
_EGLDriver *drv = _eglLookupDriver(dpy);
|
||||
return drv->API.ChooseConfig(drv, dpy, attrib_list, configs, config_size, num_config);
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean APIENTRY
|
||||
eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
|
||||
{
|
||||
_EGLDriver *drv = _eglLookupDriver(dpy);
|
||||
return drv->API.GetConfigAttrib(drv, dpy, config, attribute, value);
|
||||
}
|
||||
|
||||
|
||||
EGLContext APIENTRY
|
||||
eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list)
|
||||
{
|
||||
_EGLDriver *drv = _eglLookupDriver(dpy);
|
||||
return drv->API.CreateContext(drv, dpy, config, share_list, attrib_list);
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean APIENTRY
|
||||
eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
|
||||
{
|
||||
_EGLDriver *drv = _eglLookupDriver(dpy);
|
||||
return drv->API.DestroyContext(drv, dpy, ctx);
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean APIENTRY
|
||||
eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
|
||||
{
|
||||
_EGLDriver *drv = _eglLookupDriver(dpy);
|
||||
return drv->API.MakeCurrent(drv, dpy, draw, read, ctx);
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean APIENTRY
|
||||
eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
|
||||
{
|
||||
_EGLDriver *drv = _eglLookupDriver(dpy);
|
||||
return drv->API.QueryContext(drv, dpy, ctx, attribute, value);
|
||||
}
|
||||
|
||||
|
||||
EGLSurface APIENTRY
|
||||
eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint *attrib_list)
|
||||
{
|
||||
_EGLDriver *drv = _eglLookupDriver(dpy);
|
||||
return drv->API.CreateWindowSurface(drv, dpy, config, window, attrib_list);
|
||||
}
|
||||
|
||||
|
||||
EGLSurface APIENTRY
|
||||
eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, NativePixmapType pixmap, const EGLint *attrib_list)
|
||||
{
|
||||
_EGLDriver *drv = _eglLookupDriver(dpy);
|
||||
return drv->API.CreatePixmapSurface(drv, dpy, config, pixmap, attrib_list);
|
||||
}
|
||||
|
||||
|
||||
EGLSurface APIENTRY
|
||||
eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
|
||||
{
|
||||
_EGLDriver *drv = _eglLookupDriver(dpy);
|
||||
return drv->API.CreatePbufferSurface(drv, dpy, config, attrib_list);
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean APIENTRY
|
||||
eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
|
||||
{
|
||||
_EGLDriver *drv = _eglLookupDriver(dpy);
|
||||
return drv->API.DestroySurface(drv, dpy, surface);
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean APIENTRY
|
||||
eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value)
|
||||
{
|
||||
_EGLDriver *drv = _eglLookupDriver(dpy);
|
||||
return drv->API.QuerySurface(drv, dpy, surface, attribute, value);
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean APIENTRY
|
||||
eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
|
||||
{
|
||||
_EGLDriver *drv = _eglLookupDriver(dpy);
|
||||
return drv->API.SurfaceAttrib(drv, dpy, surface, attribute, value);
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean APIENTRY
|
||||
eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
|
||||
{
|
||||
_EGLDriver *drv = _eglLookupDriver(dpy);
|
||||
return drv->API.BindTexImage(drv, dpy, surface, buffer);
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean APIENTRY
|
||||
eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
|
||||
{
|
||||
_EGLDriver *drv = _eglLookupDriver(dpy);
|
||||
return drv->API.ReleaseTexImage(drv, dpy, surface, buffer);
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean APIENTRY
|
||||
eglSwapInterval(EGLDisplay dpy, EGLint interval)
|
||||
{
|
||||
_EGLDriver *drv = _eglLookupDriver(dpy);
|
||||
return drv->API.SwapInterval(drv, dpy, interval);
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean APIENTRY
|
||||
eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
|
||||
{
|
||||
_EGLDriver *drv = _eglLookupDriver(dpy);
|
||||
return drv->API.SwapBuffers(drv, dpy, draw);
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean APIENTRY
|
||||
eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, NativePixmapType target)
|
||||
{
|
||||
_EGLDriver *drv = _eglLookupDriver(dpy);
|
||||
return drv->API.CopyBuffers(drv, dpy, surface, target);
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean APIENTRY
|
||||
eglWaitGL(void)
|
||||
{
|
||||
EGLDisplay dpy = eglGetCurrentDisplay();
|
||||
if (dpy != EGL_NO_DISPLAY) {
|
||||
_EGLDriver *drv = _eglLookupDriver(dpy);
|
||||
return drv->API.WaitGL(drv, dpy);
|
||||
}
|
||||
else
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean APIENTRY
|
||||
eglWaitNative(EGLint engine)
|
||||
{
|
||||
EGLDisplay dpy = eglGetCurrentDisplay();
|
||||
if (dpy != EGL_NO_DISPLAY) {
|
||||
_EGLDriver *drv = _eglLookupDriver(dpy);
|
||||
return drv->API.WaitNative(drv, dpy, engine);
|
||||
}
|
||||
else
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
EGLDisplay APIENTRY
|
||||
eglGetCurrentDisplay(void)
|
||||
{
|
||||
_EGLDisplay *dpy = _eglGetCurrentDisplay();
|
||||
if (dpy)
|
||||
return dpy->Handle;
|
||||
else
|
||||
return EGL_NO_DISPLAY;
|
||||
}
|
||||
|
||||
|
||||
EGLContext APIENTRY
|
||||
eglGetCurrentContext(void)
|
||||
{
|
||||
_EGLContext *ctx = _eglGetCurrentContext();
|
||||
if (ctx)
|
||||
return ctx->Handle;
|
||||
else
|
||||
return EGL_NO_CONTEXT;
|
||||
}
|
||||
|
||||
|
||||
EGLSurface APIENTRY
|
||||
eglGetCurrentSurface(EGLint readdraw)
|
||||
{
|
||||
_EGLSurface *s = _eglGetCurrentSurface(readdraw);
|
||||
if (s)
|
||||
return s->Handle;
|
||||
else
|
||||
return EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
|
||||
EGLint APIENTRY
|
||||
eglGetError(void)
|
||||
{
|
||||
_EGLThreadInfo *t = _eglGetCurrentThread();
|
||||
EGLint e = t->LastError;
|
||||
t->LastError = EGL_SUCCESS;
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
void (* APIENTRY eglGetProcAddress(const char *procname))()
|
||||
{
|
||||
typedef void (*genericFunc)();
|
||||
struct name_function {
|
||||
const char *name;
|
||||
_EGLProc function;
|
||||
};
|
||||
static struct name_function egl_functions[] = {
|
||||
/* alphabetical order */
|
||||
{ "eglBindTexImage", (_EGLProc) eglBindTexImage },
|
||||
{ "eglChooseConfig", (_EGLProc) eglChooseConfig },
|
||||
{ "eglCopyBuffers", (_EGLProc) eglCopyBuffers },
|
||||
{ "eglCreateContext", (_EGLProc) eglCreateContext },
|
||||
{ "eglCreatePbufferSurface", (_EGLProc) eglCreatePbufferSurface },
|
||||
{ "eglCreatePixmapSurface", (_EGLProc) eglCreatePixmapSurface },
|
||||
{ "eglCreateWindowSurface", (_EGLProc) eglCreateWindowSurface },
|
||||
{ "eglDestroyContext", (_EGLProc) eglDestroyContext },
|
||||
{ "eglDestroySurface", (_EGLProc) eglDestroySurface },
|
||||
{ "eglGetConfigAttrib", (_EGLProc) eglGetConfigAttrib },
|
||||
{ "eglGetConfigs", (_EGLProc) eglGetConfigs },
|
||||
{ "eglGetCurrentContext", (_EGLProc) eglGetCurrentContext },
|
||||
{ "eglGetCurrentDisplay", (_EGLProc) eglGetCurrentDisplay },
|
||||
{ "eglGetCurrentSurface", (_EGLProc) eglGetCurrentSurface },
|
||||
{ "eglGetDisplay", (_EGLProc) eglGetDisplay },
|
||||
{ "eglGetError", (_EGLProc) eglGetError },
|
||||
{ "eglGetProcAddress", (_EGLProc) eglGetProcAddress },
|
||||
{ "eglInitialize", (_EGLProc) eglInitialize },
|
||||
{ "eglMakeCurrent", (_EGLProc) eglMakeCurrent },
|
||||
{ "eglQueryContext", (_EGLProc) eglQueryContext },
|
||||
{ "eglQueryString", (_EGLProc) eglQueryString },
|
||||
{ "eglQuerySurface", (_EGLProc) eglQuerySurface },
|
||||
{ "eglReleaseTexImage", (_EGLProc) eglReleaseTexImage },
|
||||
{ "eglSurfaceAttrib", (_EGLProc) eglSurfaceAttrib },
|
||||
{ "eglSwapBuffers", (_EGLProc) eglSwapBuffers },
|
||||
{ "eglSwapInterval", (_EGLProc) eglSwapInterval },
|
||||
{ "eglTerminate", (_EGLProc) eglTerminate },
|
||||
{ "eglWaitGL", (_EGLProc) eglWaitGL },
|
||||
{ "eglWaitNative", (_EGLProc) eglWaitNative },
|
||||
/* Extensions */
|
||||
#ifdef EGL_MESA_screen_surface
|
||||
{ "eglChooseModeMESA", (_EGLProc) eglChooseModeMESA },
|
||||
{ "eglGetModesMESA", (_EGLProc) eglGetModesMESA },
|
||||
{ "eglGetModeAttribMESA", (_EGLProc) eglGetModeAttribMESA },
|
||||
{ "eglCopyContextMESA", (_EGLProc) eglCopyContextMESA },
|
||||
{ "eglGetScreensMESA", (_EGLProc) eglGetScreensMESA },
|
||||
{ "eglCreateScreenSurfaceMESA", (_EGLProc) eglCreateScreenSurfaceMESA },
|
||||
{ "eglShowScreenSurfaceMESA", (_EGLProc) eglShowScreenSurfaceMESA },
|
||||
{ "eglScreenPositionMESA", (_EGLProc) eglScreenPositionMESA },
|
||||
{ "eglQueryScreenMESA", (_EGLProc) eglQueryScreenMESA },
|
||||
{ "eglQueryScreenSurfaceMESA", (_EGLProc) eglQueryScreenSurfaceMESA },
|
||||
{ "eglQueryScreenModeMESA", (_EGLProc) eglQueryScreenModeMESA },
|
||||
{ "eglQueryModeStringMESA", (_EGLProc) eglQueryModeStringMESA },
|
||||
#endif /* EGL_MESA_screen_surface */
|
||||
#ifdef EGL_VERSION_1_2
|
||||
{ "eglBindAPI", (_EGLProc) eglBindAPI },
|
||||
{ "eglCreatePbufferFromClientBuffer", (_EGLProc) eglCreatePbufferFromClientBuffer },
|
||||
{ "eglQueryAPI", (_EGLProc) eglQueryAPI },
|
||||
{ "eglReleaseThread", (_EGLProc) eglReleaseThread },
|
||||
{ "eglWaitClient", (_EGLProc) eglWaitClient },
|
||||
#endif /* EGL_VERSION_1_2 */
|
||||
{ NULL, NULL }
|
||||
};
|
||||
EGLint i;
|
||||
for (i = 0; egl_functions[i].name; i++) {
|
||||
if (strcmp(egl_functions[i].name, procname) == 0) {
|
||||
return (genericFunc) egl_functions[i].function;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
/* XXX enable this code someday */
|
||||
return (genericFunc) _glapi_get_proc_address(procname);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* EGL_MESA_screen extension
|
||||
*/
|
||||
|
||||
EGLBoolean APIENTRY
|
||||
eglChooseModeMESA(EGLDisplay dpy, EGLScreenMESA screen,
|
||||
const EGLint *attrib_list, EGLModeMESA *modes,
|
||||
EGLint modes_size, EGLint *num_modes)
|
||||
{
|
||||
_EGLDriver *drv = _eglLookupDriver(dpy);
|
||||
if (drv)
|
||||
return drv->API.ChooseModeMESA(drv, dpy, screen, attrib_list, modes, modes_size, num_modes);
|
||||
else
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean APIENTRY
|
||||
eglGetModesMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *modes, EGLint mode_size, EGLint *num_mode)
|
||||
{
|
||||
_EGLDriver *drv = _eglLookupDriver(dpy);
|
||||
if (drv)
|
||||
return drv->API.GetModesMESA(drv, dpy, screen, modes, mode_size, num_mode);
|
||||
else
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean APIENTRY
|
||||
eglGetModeAttribMESA(EGLDisplay dpy, EGLModeMESA mode, EGLint attribute, EGLint *value)
|
||||
{
|
||||
_EGLDriver *drv = _eglLookupDriver(dpy);
|
||||
if (drv)
|
||||
return drv->API.GetModeAttribMESA(drv, dpy, mode, attribute, value);
|
||||
else
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean APIENTRY
|
||||
eglCopyContextMESA(EGLDisplay dpy, EGLContext source, EGLContext dest, EGLint mask)
|
||||
{
|
||||
_EGLDriver *drv = _eglLookupDriver(dpy);
|
||||
if (drv)
|
||||
return drv->API.CopyContextMESA(drv, dpy, source, dest, mask);
|
||||
else
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean
|
||||
eglGetScreensMESA(EGLDisplay dpy, EGLScreenMESA *screens, EGLint max_screens, EGLint *num_screens)
|
||||
{
|
||||
_EGLDriver *drv = _eglLookupDriver(dpy);
|
||||
if (drv)
|
||||
return drv->API.GetScreensMESA(drv, dpy, screens, max_screens, num_screens);
|
||||
else
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
EGLSurface
|
||||
eglCreateScreenSurfaceMESA(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
|
||||
{
|
||||
_EGLDriver *drv = _eglLookupDriver(dpy);
|
||||
return drv->API.CreateScreenSurfaceMESA(drv, dpy, config, attrib_list);
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean
|
||||
eglShowScreenSurfaceMESA(EGLDisplay dpy, EGLint screen, EGLSurface surface, EGLModeMESA mode)
|
||||
{
|
||||
_EGLDriver *drv = _eglLookupDriver(dpy);
|
||||
return drv->API.ShowScreenSurfaceMESA(drv, dpy, screen, surface, mode);
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean
|
||||
eglScreenPositionMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLint x, EGLint y)
|
||||
{
|
||||
_EGLDriver *drv = _eglLookupDriver(dpy);
|
||||
return drv->API.ScreenPositionMESA(drv, dpy, screen, x, y);
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean
|
||||
eglQueryScreenMESA( EGLDisplay dpy, EGLScreenMESA screen, EGLint attribute, EGLint *value)
|
||||
{
|
||||
_EGLDriver *drv = _eglLookupDriver(dpy);
|
||||
return drv->API.QueryScreenMESA(drv, dpy, screen, attribute, value);
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean
|
||||
eglQueryScreenSurfaceMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLSurface *surface)
|
||||
{
|
||||
_EGLDriver *drv = _eglLookupDriver(dpy);
|
||||
return drv->API.QueryScreenSurfaceMESA(drv, dpy, screen, surface);
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean
|
||||
eglQueryScreenModeMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *mode)
|
||||
{
|
||||
_EGLDriver *drv = _eglLookupDriver(dpy);
|
||||
return drv->API.QueryScreenModeMESA(drv, dpy, screen, mode);
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
eglQueryModeStringMESA(EGLDisplay dpy, EGLModeMESA mode)
|
||||
{
|
||||
_EGLDriver *drv = _eglLookupDriver(dpy);
|
||||
return drv->API.QueryModeStringMESA(drv, dpy, mode);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
** EGL 1.2
|
||||
**/
|
||||
|
||||
#ifdef EGL_VERSION_1_2
|
||||
|
||||
EGLBoolean
|
||||
eglBindAPI(EGLenum api)
|
||||
{
|
||||
_EGLThreadInfo *t = _eglGetCurrentThread();
|
||||
|
||||
switch (api) {
|
||||
case EGL_OPENGL_ES_API:
|
||||
if (_eglGlobal.OpenGLESAPISupported) {
|
||||
t->CurrentAPI = api;
|
||||
return EGL_TRUE;
|
||||
}
|
||||
_eglError(EGL_BAD_PARAMETER, "eglBindAPI");
|
||||
return EGL_FALSE;
|
||||
case EGL_OPENVG_API:
|
||||
if (_eglGlobal.OpenVGAPISupported) {
|
||||
t->CurrentAPI = api;
|
||||
return EGL_TRUE;
|
||||
}
|
||||
_eglError(EGL_BAD_PARAMETER, "eglBindAPI");
|
||||
return EGL_FALSE;
|
||||
default:
|
||||
return EGL_FALSE;
|
||||
}
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
EGLSurface
|
||||
eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype,
|
||||
EGLClientBuffer buffer, EGLConfig config,
|
||||
const EGLint *attrib_list)
|
||||
{
|
||||
_EGLDriver *drv = _eglLookupDriver(dpy);
|
||||
return drv->API.CreatePbufferFromClientBuffer(drv, dpy, buftype, buffer,
|
||||
config, attrib_list);
|
||||
}
|
||||
|
||||
|
||||
EGLenum
|
||||
eglQueryAPI(void)
|
||||
{
|
||||
/* returns one of EGL_OPENGL_ES_API or EGL_OPENVG_API */
|
||||
_EGLThreadInfo *t = _eglGetCurrentThread();
|
||||
return t->CurrentAPI;
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean
|
||||
eglReleaseThread(void)
|
||||
{
|
||||
_EGLThreadInfo *t = _eglGetCurrentThread();
|
||||
EGLDisplay dpy = eglGetCurrentDisplay();
|
||||
if (dpy) {
|
||||
_EGLDriver *drv = _eglLookupDriver(dpy);
|
||||
/* unbind context */
|
||||
(void) drv->API.MakeCurrent(drv, dpy, EGL_NO_SURFACE,
|
||||
EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
}
|
||||
_eglDeleteThreadData(t);
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean
|
||||
eglWaitClient(void)
|
||||
{
|
||||
EGLDisplay dpy = eglGetCurrentDisplay();
|
||||
if (dpy != EGL_NO_DISPLAY) {
|
||||
_EGLDriver *drv = _eglLookupDriver(dpy);
|
||||
return drv->API.WaitClient(drv, dpy);
|
||||
}
|
||||
else
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
#endif /* EGL_VERSION_1_2 */
|
||||
@@ -1,119 +0,0 @@
|
||||
#ifndef EGLAPI_INCLUDED
|
||||
#define EGLAPI_INCLUDED
|
||||
|
||||
/**
|
||||
* Typedefs for all EGL API entrypoint functions.
|
||||
*/
|
||||
|
||||
|
||||
/* driver funcs */
|
||||
typedef EGLBoolean (*Initialize_t)(_EGLDriver *, EGLDisplay dpy, EGLint *major, EGLint *minor);
|
||||
typedef EGLBoolean (*Terminate_t)(_EGLDriver *, EGLDisplay dpy);
|
||||
|
||||
/* config funcs */
|
||||
typedef EGLBoolean (*GetConfigs_t)(_EGLDriver *drv, EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config);
|
||||
typedef EGLBoolean (*ChooseConfig_t)(_EGLDriver *drv, EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
|
||||
typedef EGLBoolean (*GetConfigAttrib_t)(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value);
|
||||
|
||||
/* context funcs */
|
||||
typedef EGLContext (*CreateContext_t)(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list);
|
||||
typedef EGLBoolean (*DestroyContext_t)(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx);
|
||||
typedef EGLBoolean (*MakeCurrent_t)(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
|
||||
typedef EGLBoolean (*QueryContext_t)(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value);
|
||||
|
||||
/* surface funcs */
|
||||
typedef EGLSurface (*CreateWindowSurface_t)(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint *attrib_list);
|
||||
typedef EGLSurface (*CreatePixmapSurface_t)(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativePixmapType pixmap, const EGLint *attrib_list);
|
||||
typedef EGLSurface (*CreatePbufferSurface_t)(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
|
||||
typedef EGLBoolean (*DestroySurface_t)(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface);
|
||||
typedef EGLBoolean (*QuerySurface_t)(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value);
|
||||
typedef EGLBoolean (*SurfaceAttrib_t)(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value);
|
||||
typedef EGLBoolean (*BindTexImage_t)(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint buffer);
|
||||
typedef EGLBoolean (*ReleaseTexImage_t)(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint buffer);
|
||||
typedef EGLBoolean (*SwapInterval_t)(_EGLDriver *drv, EGLDisplay dpy, EGLint interval);
|
||||
typedef EGLBoolean (*SwapBuffers_t)(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw);
|
||||
typedef EGLBoolean (*CopyBuffers_t)(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, NativePixmapType target);
|
||||
|
||||
/* misc funcs */
|
||||
typedef const char *(*QueryString_t)(_EGLDriver *drv, EGLDisplay dpy, EGLint name);
|
||||
typedef EGLBoolean (*WaitGL_t)(_EGLDriver *drv, EGLDisplay dpy);
|
||||
typedef EGLBoolean (*WaitNative_t)(_EGLDriver *drv, EGLDisplay dpy, EGLint engine);
|
||||
|
||||
|
||||
#ifdef EGL_MESA_screen_surface
|
||||
typedef EGLBoolean (*ChooseModeMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, const EGLint *attrib_list, EGLModeMESA *modes, EGLint modes_size, EGLint *num_modes);
|
||||
typedef EGLBoolean (*GetModesMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *modes, EGLint mode_size, EGLint *num_mode);
|
||||
typedef EGLBoolean (*GetModeAttribMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLModeMESA mode, EGLint attribute, EGLint *value);
|
||||
typedef EGLBoolean (*CopyContextMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLContext source, EGLContext dest, EGLint mask);
|
||||
typedef EGLBoolean (*GetScreensMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA *screens, EGLint max_screens, EGLint *num_screens);
|
||||
typedef EGLSurface (*CreateScreenSurfaceMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
|
||||
typedef EGLBoolean (*ShowScreenSurfaceMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLSurface surface, EGLModeMESA mode);
|
||||
typedef EGLBoolean (*ScreenPositionMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLint x, EGLint y);
|
||||
typedef EGLBoolean (*QueryScreenMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLint attribute, EGLint *value);
|
||||
typedef EGLBoolean (*QueryScreenSurfaceMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLSurface *surface);
|
||||
typedef EGLBoolean (*QueryScreenModeMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *mode);
|
||||
typedef const char * (*QueryModeStringMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLModeMESA mode);
|
||||
#endif /* EGL_MESA_screen_surface */
|
||||
|
||||
|
||||
#ifdef EGL_VERSION_1_2
|
||||
typedef EGLBoolean (*WaitClient_t)(_EGLDriver *drv, EGLDisplay dpy);
|
||||
typedef EGLSurface (*CreatePbufferFromClientBuffer_t)(_EGLDriver *drv, EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list);
|
||||
#endif /* EGL_VERSION_1_2 */
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The API dispatcher jumps through these functions
|
||||
*/
|
||||
struct _egl_api
|
||||
{
|
||||
Initialize_t Initialize;
|
||||
Terminate_t Terminate;
|
||||
|
||||
GetConfigs_t GetConfigs;
|
||||
ChooseConfig_t ChooseConfig;
|
||||
GetConfigAttrib_t GetConfigAttrib;
|
||||
|
||||
CreateContext_t CreateContext;
|
||||
DestroyContext_t DestroyContext;
|
||||
MakeCurrent_t MakeCurrent;
|
||||
QueryContext_t QueryContext;
|
||||
|
||||
CreateWindowSurface_t CreateWindowSurface;
|
||||
CreatePixmapSurface_t CreatePixmapSurface;
|
||||
CreatePbufferSurface_t CreatePbufferSurface;
|
||||
DestroySurface_t DestroySurface;
|
||||
QuerySurface_t QuerySurface;
|
||||
SurfaceAttrib_t SurfaceAttrib;
|
||||
BindTexImage_t BindTexImage;
|
||||
ReleaseTexImage_t ReleaseTexImage;
|
||||
SwapInterval_t SwapInterval;
|
||||
SwapBuffers_t SwapBuffers;
|
||||
CopyBuffers_t CopyBuffers;
|
||||
|
||||
QueryString_t QueryString;
|
||||
WaitGL_t WaitGL;
|
||||
WaitNative_t WaitNative;
|
||||
|
||||
/* EGL_MESA_screen extension */
|
||||
ChooseModeMESA_t ChooseModeMESA;
|
||||
GetModesMESA_t GetModesMESA;
|
||||
GetModeAttribMESA_t GetModeAttribMESA;
|
||||
CopyContextMESA_t CopyContextMESA;
|
||||
GetScreensMESA_t GetScreensMESA;
|
||||
CreateScreenSurfaceMESA_t CreateScreenSurfaceMESA;
|
||||
ShowScreenSurfaceMESA_t ShowScreenSurfaceMESA;
|
||||
ScreenPositionMESA_t ScreenPositionMESA;
|
||||
QueryScreenMESA_t QueryScreenMESA;
|
||||
QueryScreenSurfaceMESA_t QueryScreenSurfaceMESA;
|
||||
QueryScreenModeMESA_t QueryScreenModeMESA;
|
||||
QueryModeStringMESA_t QueryModeStringMESA;
|
||||
|
||||
#ifdef EGL_VERSION_1_2
|
||||
WaitClient_t WaitClient;
|
||||
CreatePbufferFromClientBuffer_t CreatePbufferFromClientBuffer;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* EGLAPI_INCLUDED */
|
||||
@@ -1,638 +0,0 @@
|
||||
/**
|
||||
* EGL Configuration (pixel format) functions.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "eglconfig.h"
|
||||
#include "egldisplay.h"
|
||||
#include "egldriver.h"
|
||||
#include "eglglobals.h"
|
||||
#include "egllog.h"
|
||||
|
||||
|
||||
#define MIN2(A, B) (((A) < (B)) ? (A) : (B))
|
||||
|
||||
|
||||
/**
|
||||
* Convert an _EGLConfig to a __GLcontextModes object.
|
||||
* NOTE: This routine may be incomplete - we're only making sure that
|
||||
* the fields needed by Mesa (for _mesa_create_context/framebuffer) are
|
||||
* set correctly.
|
||||
*/
|
||||
void
|
||||
_eglConfigToContextModesRec(const _EGLConfig *config, __GLcontextModes *mode)
|
||||
{
|
||||
memset(mode, 0, sizeof(*mode));
|
||||
|
||||
mode->rgbMode = GL_TRUE; /* no color index */
|
||||
mode->colorIndexMode = GL_FALSE;
|
||||
mode->doubleBufferMode = GL_TRUE; /* always DB for now */
|
||||
mode->stereoMode = GL_FALSE;
|
||||
|
||||
mode->redBits = GET_CONFIG_ATTRIB(config, EGL_RED_SIZE);
|
||||
mode->greenBits = GET_CONFIG_ATTRIB(config, EGL_GREEN_SIZE);
|
||||
mode->blueBits = GET_CONFIG_ATTRIB(config, EGL_BLUE_SIZE);
|
||||
mode->alphaBits = GET_CONFIG_ATTRIB(config, EGL_ALPHA_SIZE);
|
||||
mode->rgbBits = GET_CONFIG_ATTRIB(config, EGL_BUFFER_SIZE);
|
||||
|
||||
/* no rgba masks - fix? */
|
||||
|
||||
mode->depthBits = GET_CONFIG_ATTRIB(config, EGL_DEPTH_SIZE);
|
||||
mode->haveDepthBuffer = mode->depthBits > 0;
|
||||
|
||||
mode->stencilBits = GET_CONFIG_ATTRIB(config, EGL_STENCIL_SIZE);
|
||||
mode->haveStencilBuffer = mode->stencilBits > 0;
|
||||
|
||||
/* no accum */
|
||||
|
||||
mode->level = GET_CONFIG_ATTRIB(config, EGL_LEVEL);
|
||||
mode->samples = GET_CONFIG_ATTRIB(config, EGL_SAMPLES);
|
||||
mode->sampleBuffers = GET_CONFIG_ATTRIB(config, EGL_SAMPLE_BUFFERS);
|
||||
|
||||
/* surface type - not really needed */
|
||||
mode->visualType = GLX_TRUE_COLOR;
|
||||
mode->renderType = GLX_RGBA_BIT;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_eglSetConfigAttrib(_EGLConfig *config, EGLint attr, EGLint val)
|
||||
{
|
||||
assert(attr >= FIRST_ATTRIB);
|
||||
assert(attr < FIRST_ATTRIB + MAX_ATTRIBS);
|
||||
config->Attrib[attr - FIRST_ATTRIB] = val;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Init the given _EGLconfig to default values.
|
||||
* \param id the configuration's ID.
|
||||
*/
|
||||
void
|
||||
_eglInitConfig(_EGLConfig *config, EGLint id)
|
||||
{
|
||||
memset(config, 0, sizeof(*config));
|
||||
config->Handle = id;
|
||||
_eglSetConfigAttrib(config, EGL_CONFIG_ID, id);
|
||||
_eglSetConfigAttrib(config, EGL_BIND_TO_TEXTURE_RGB, EGL_DONT_CARE);
|
||||
_eglSetConfigAttrib(config, EGL_BIND_TO_TEXTURE_RGBA, EGL_DONT_CARE);
|
||||
_eglSetConfigAttrib(config, EGL_CONFIG_CAVEAT, EGL_DONT_CARE);
|
||||
_eglSetConfigAttrib(config, EGL_NATIVE_RENDERABLE, EGL_DONT_CARE);
|
||||
_eglSetConfigAttrib(config, EGL_NATIVE_VISUAL_TYPE, EGL_DONT_CARE);
|
||||
_eglSetConfigAttrib(config, EGL_MIN_SWAP_INTERVAL, EGL_DONT_CARE);
|
||||
_eglSetConfigAttrib(config, EGL_MAX_SWAP_INTERVAL, EGL_DONT_CARE);
|
||||
_eglSetConfigAttrib(config, EGL_SURFACE_TYPE,
|
||||
EGL_SCREEN_BIT_MESA | EGL_PBUFFER_BIT |
|
||||
EGL_PIXMAP_BIT | EGL_WINDOW_BIT);
|
||||
_eglSetConfigAttrib(config, EGL_TRANSPARENT_TYPE, EGL_NONE);
|
||||
_eglSetConfigAttrib(config, EGL_TRANSPARENT_RED_VALUE, EGL_DONT_CARE);
|
||||
_eglSetConfigAttrib(config, EGL_TRANSPARENT_GREEN_VALUE, EGL_DONT_CARE);
|
||||
_eglSetConfigAttrib(config, EGL_TRANSPARENT_BLUE_VALUE, EGL_DONT_CARE);
|
||||
#ifdef EGL_VERSION_1_2
|
||||
_eglSetConfigAttrib(config, EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER);
|
||||
_eglSetConfigAttrib(config, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT);
|
||||
#endif /* EGL_VERSION_1_2 */
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Given an EGLConfig handle, return the corresponding _EGLConfig object.
|
||||
*/
|
||||
_EGLConfig *
|
||||
_eglLookupConfig(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config)
|
||||
{
|
||||
EGLint i;
|
||||
_EGLDisplay *disp = _eglLookupDisplay(dpy);
|
||||
for (i = 0; i < disp->NumConfigs; i++) {
|
||||
if (disp->Configs[i].Handle == config) {
|
||||
return disp->Configs + i;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add the given _EGLConfig to the given display.
|
||||
*/
|
||||
_EGLConfig *
|
||||
_eglAddConfig(_EGLDisplay *display, const _EGLConfig *config)
|
||||
{
|
||||
_EGLConfig *newConfigs;
|
||||
EGLint n;
|
||||
|
||||
n = display->NumConfigs;
|
||||
|
||||
newConfigs = (_EGLConfig *) realloc(display->Configs,
|
||||
(n + 1) * sizeof(_EGLConfig));
|
||||
if (newConfigs) {
|
||||
display->Configs = newConfigs;
|
||||
display->Configs[n] = *config; /* copy struct */
|
||||
display->Configs[n].Handle = n;
|
||||
display->NumConfigs++;
|
||||
return display->Configs + n;
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse the attrib_list to fill in the fields of the given _eglConfig
|
||||
* Return EGL_FALSE if any errors, EGL_TRUE otherwise.
|
||||
*/
|
||||
EGLBoolean
|
||||
_eglParseConfigAttribs(_EGLConfig *config, const EGLint *attrib_list)
|
||||
{
|
||||
EGLint i;
|
||||
|
||||
/* set all config attribs to EGL_DONT_CARE */
|
||||
for (i = 0; i < MAX_ATTRIBS; i++) {
|
||||
config->Attrib[i] = EGL_DONT_CARE;
|
||||
}
|
||||
|
||||
for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
|
||||
const EGLint attr = attrib_list[i];
|
||||
if (attr >= EGL_BUFFER_SIZE &&
|
||||
attr <= EGL_MAX_SWAP_INTERVAL) {
|
||||
EGLint k = attr - FIRST_ATTRIB;
|
||||
assert(k >= 0);
|
||||
assert(k < MAX_ATTRIBS);
|
||||
config->Attrib[k] = attrib_list[++i];
|
||||
}
|
||||
#ifdef EGL_VERSION_1_2
|
||||
else if (attr == EGL_COLOR_BUFFER_TYPE) {
|
||||
EGLint bufType = attrib_list[++i];
|
||||
if (bufType != EGL_RGB_BUFFER && bufType != EGL_LUMINANCE_BUFFER) {
|
||||
_eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
_eglSetConfigAttrib(config, EGL_COLOR_BUFFER_TYPE, bufType);
|
||||
}
|
||||
else if (attr == EGL_RENDERABLE_TYPE) {
|
||||
EGLint renType = attrib_list[++i];
|
||||
if (renType & ~(EGL_OPENGL_ES_BIT | EGL_OPENVG_BIT)) {
|
||||
_eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
_eglSetConfigAttrib(config, EGL_RENDERABLE_TYPE, renType);
|
||||
}
|
||||
else if (attr == EGL_ALPHA_MASK_SIZE ||
|
||||
attr == EGL_LUMINANCE_SIZE) {
|
||||
EGLint value = attrib_list[++i];
|
||||
_eglSetConfigAttrib(config, attr, value);
|
||||
}
|
||||
#endif /* EGL_VERSION_1_2 */
|
||||
else {
|
||||
_eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
}
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
#define EXACT 1
|
||||
#define ATLEAST 2
|
||||
#define MASK 3
|
||||
#define SMALLER 4
|
||||
#define SPECIAL 5
|
||||
#define NONE 6
|
||||
|
||||
struct sort_info {
|
||||
EGLint Attribute;
|
||||
EGLint MatchCriteria;
|
||||
EGLint SortOrder;
|
||||
};
|
||||
|
||||
/* This encodes the info from Table 3.5 of the EGL spec, ordered by
|
||||
* Sort Priority.
|
||||
*
|
||||
* XXX To do: EGL 1.2 attribs
|
||||
*/
|
||||
static struct sort_info SortInfo[] = {
|
||||
{ EGL_CONFIG_CAVEAT, EXACT, SPECIAL },
|
||||
{ EGL_RED_SIZE, ATLEAST, SPECIAL },
|
||||
{ EGL_GREEN_SIZE, ATLEAST, SPECIAL },
|
||||
{ EGL_BLUE_SIZE, ATLEAST, SPECIAL },
|
||||
{ EGL_ALPHA_SIZE, ATLEAST, SPECIAL },
|
||||
{ EGL_BUFFER_SIZE, ATLEAST, SMALLER },
|
||||
{ EGL_SAMPLE_BUFFERS, ATLEAST, SMALLER },
|
||||
{ EGL_SAMPLES, ATLEAST, SMALLER },
|
||||
{ EGL_DEPTH_SIZE, ATLEAST, SMALLER },
|
||||
{ EGL_STENCIL_SIZE, ATLEAST, SMALLER },
|
||||
{ EGL_NATIVE_VISUAL_TYPE, EXACT, SPECIAL },
|
||||
{ EGL_CONFIG_ID, EXACT, SMALLER },
|
||||
{ EGL_BIND_TO_TEXTURE_RGB, EXACT, NONE },
|
||||
{ EGL_BIND_TO_TEXTURE_RGBA, EXACT, NONE },
|
||||
{ EGL_LEVEL, EXACT, NONE },
|
||||
{ EGL_NATIVE_RENDERABLE, EXACT, NONE },
|
||||
{ EGL_MAX_SWAP_INTERVAL, EXACT, NONE },
|
||||
{ EGL_MIN_SWAP_INTERVAL, EXACT, NONE },
|
||||
{ EGL_SURFACE_TYPE, MASK, NONE },
|
||||
{ EGL_TRANSPARENT_TYPE, EXACT, NONE },
|
||||
{ EGL_TRANSPARENT_RED_VALUE, EXACT, NONE },
|
||||
{ EGL_TRANSPARENT_GREEN_VALUE, EXACT, NONE },
|
||||
{ EGL_TRANSPARENT_BLUE_VALUE, EXACT, NONE },
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return EGL_TRUE if the attributes of c meet or exceed the minimums
|
||||
* specified by min.
|
||||
*/
|
||||
static EGLBoolean
|
||||
_eglConfigQualifies(const _EGLConfig *c, const _EGLConfig *min)
|
||||
{
|
||||
EGLint i;
|
||||
for (i = 0; SortInfo[i].Attribute != 0; i++) {
|
||||
const EGLint mv = GET_CONFIG_ATTRIB(min, SortInfo[i].Attribute);
|
||||
if (mv != EGL_DONT_CARE) {
|
||||
const EGLint cv = GET_CONFIG_ATTRIB(c, SortInfo[i].Attribute);
|
||||
if (SortInfo[i].MatchCriteria == EXACT) {
|
||||
if (cv != mv) {
|
||||
return EGL_FALSE;
|
||||
}
|
||||
}
|
||||
else if (SortInfo[i].MatchCriteria == ATLEAST) {
|
||||
if (cv < mv) {
|
||||
return EGL_FALSE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert(SortInfo[i].MatchCriteria == MASK);
|
||||
if ((mv & cv) != mv) {
|
||||
return EGL_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compare configs 'a' and 'b' and return -1 if a belongs before b,
|
||||
* 1 if a belongs after b, or 0 if they're equal.
|
||||
* Used by qsort().
|
||||
*/
|
||||
static int
|
||||
_eglCompareConfigs(const void *a, const void *b)
|
||||
{
|
||||
const _EGLConfig *aConfig = (const _EGLConfig *) a;
|
||||
const _EGLConfig *bConfig = (const _EGLConfig *) b;
|
||||
EGLint i;
|
||||
|
||||
for (i = 0; SortInfo[i].Attribute != 0; i++) {
|
||||
const EGLint aVal = GET_CONFIG_ATTRIB(aConfig, SortInfo[i].Attribute);
|
||||
const EGLint bVal = GET_CONFIG_ATTRIB(bConfig, SortInfo[i].Attribute);
|
||||
if (SortInfo[i].SortOrder == SMALLER) {
|
||||
if (aVal < bVal)
|
||||
return -1;
|
||||
else if (aVal > bVal)
|
||||
return 1;
|
||||
/* else, continue examining attribute values */
|
||||
}
|
||||
else if (SortInfo[i].SortOrder == SPECIAL) {
|
||||
if (SortInfo[i].Attribute == EGL_CONFIG_CAVEAT) {
|
||||
/* values are EGL_NONE, SLOW_CONFIG, or NON_CONFORMANT_CONFIG */
|
||||
if (aVal < bVal)
|
||||
return -1;
|
||||
else if (aVal > bVal)
|
||||
return 1;
|
||||
}
|
||||
else if (SortInfo[i].Attribute == EGL_RED_SIZE ||
|
||||
SortInfo[i].Attribute == EGL_GREEN_SIZE ||
|
||||
SortInfo[i].Attribute == EGL_BLUE_SIZE ||
|
||||
SortInfo[i].Attribute == EGL_ALPHA_SIZE) {
|
||||
if (aVal > bVal)
|
||||
return -1;
|
||||
else if (aVal < bVal)
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
assert(SortInfo[i].Attribute == EGL_NATIVE_VISUAL_TYPE);
|
||||
if (aVal < bVal)
|
||||
return -1;
|
||||
else if (aVal > bVal)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert(SortInfo[i].SortOrder == NONE);
|
||||
/* continue examining attribute values */
|
||||
}
|
||||
}
|
||||
|
||||
/* all attributes identical */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Typical fallback routine for eglChooseConfig
|
||||
*/
|
||||
EGLBoolean
|
||||
_eglChooseConfig(_EGLDriver *drv, EGLDisplay dpy, const EGLint *attrib_list,
|
||||
EGLConfig *configs, EGLint config_size, EGLint *num_configs)
|
||||
{
|
||||
_EGLDisplay *disp = _eglLookupDisplay(dpy);
|
||||
_EGLConfig **configList, criteria;
|
||||
EGLint i, count;
|
||||
|
||||
/* parse the attrib_list to initialize criteria */
|
||||
if (!_eglParseConfigAttribs(&criteria, attrib_list)) {
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
/* allocate array of config pointers */
|
||||
configList = (_EGLConfig **) malloc(config_size * sizeof(_EGLConfig *));
|
||||
if (!configList) {
|
||||
_eglError(EGL_BAD_CONFIG, "eglChooseConfig(out of memory)");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
/* make array of pointers to qualifying configs */
|
||||
for (i = count = 0; i < disp->NumConfigs && count < config_size; i++) {
|
||||
if (_eglConfigQualifies(disp->Configs + i, &criteria)) {
|
||||
configList[count++] = disp->Configs + i;
|
||||
}
|
||||
}
|
||||
|
||||
/* sort array of pointers */
|
||||
qsort(configList, count, sizeof(_EGLConfig *), _eglCompareConfigs);
|
||||
|
||||
/* copy config handles to output array */
|
||||
for (i = 0; i < count; i++) {
|
||||
configs[i] = configList[i]->Handle;
|
||||
}
|
||||
|
||||
free(configList);
|
||||
|
||||
*num_configs = count;
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fallback for eglGetConfigAttrib.
|
||||
*/
|
||||
EGLBoolean
|
||||
_eglGetConfigAttrib(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
|
||||
EGLint attribute, EGLint *value)
|
||||
{
|
||||
const _EGLConfig *conf = _eglLookupConfig(drv, dpy, config);
|
||||
const EGLint k = attribute - FIRST_ATTRIB;
|
||||
if (k >= 0 && k < MAX_ATTRIBS) {
|
||||
*value = conf->Attrib[k];
|
||||
return EGL_TRUE;
|
||||
}
|
||||
else {
|
||||
_eglError(EGL_BAD_ATTRIBUTE, "eglGetConfigAttrib");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fallback for eglGetConfigs.
|
||||
*/
|
||||
EGLBoolean
|
||||
_eglGetConfigs(_EGLDriver *drv, EGLDisplay dpy, EGLConfig *configs,
|
||||
EGLint config_size, EGLint *num_config)
|
||||
{
|
||||
_EGLDisplay *disp = _eglLookupDisplay(dpy);
|
||||
|
||||
if (!drv->Initialized) {
|
||||
_eglError(EGL_NOT_INITIALIZED, "eglGetConfigs");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
if (configs) {
|
||||
EGLint i;
|
||||
*num_config = MIN2(disp->NumConfigs, config_size);
|
||||
for (i = 0; i < *num_config; i++) {
|
||||
configs[i] = disp->Configs[i].Handle;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* just return total number of supported configs */
|
||||
*num_config = disp->NumConfigs;
|
||||
}
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a set of \c __GLcontextModes that a driver will expose.
|
||||
*
|
||||
* A set of \c __GLcontextModes will be created based on the supplied
|
||||
* parameters. The number of modes processed will be 2 *
|
||||
* \c num_depth_stencil_bits * \c num_db_modes.
|
||||
*
|
||||
* For the most part, data is just copied from \c depth_bits, \c stencil_bits,
|
||||
* \c db_modes, and \c visType into each \c __GLcontextModes element.
|
||||
* However, the meanings of \c fb_format and \c fb_type require further
|
||||
* explanation. The \c fb_format specifies which color components are in
|
||||
* each pixel and what the default order is. For example, \c GL_RGB specifies
|
||||
* that red, green, blue are available and red is in the "most significant"
|
||||
* position and blue is in the "least significant". The \c fb_type specifies
|
||||
* the bit sizes of each component and the actual ordering. For example, if
|
||||
* \c GL_UNSIGNED_SHORT_5_6_5_REV is specified with \c GL_RGB, bits [15:11]
|
||||
* are the blue value, bits [10:5] are the green value, and bits [4:0] are
|
||||
* the red value.
|
||||
*
|
||||
* One sublte issue is the combination of \c GL_RGB or \c GL_BGR and either
|
||||
* of the \c GL_UNSIGNED_INT_8_8_8_8 modes. The resulting mask values in the
|
||||
* \c __GLcontextModes structure is \b identical to the \c GL_RGBA or
|
||||
* \c GL_BGRA case, except the \c alphaMask is zero. This means that, as
|
||||
* far as this routine is concerned, \c GL_RGB with \c GL_UNSIGNED_INT_8_8_8_8
|
||||
* still uses 32-bits.
|
||||
*
|
||||
* If in doubt, look at the tables used in the function.
|
||||
*
|
||||
* \param ptr_to_modes Pointer to a pointer to a linked list of
|
||||
* \c __GLcontextModes. Upon completion, a pointer to
|
||||
* the next element to be process will be stored here.
|
||||
* If the function fails and returns \c GL_FALSE, this
|
||||
* value will be unmodified, but some elements in the
|
||||
* linked list may be modified.
|
||||
* \param fb_format Format of the framebuffer. Currently only \c GL_RGB,
|
||||
* \c GL_RGBA, \c GL_BGR, and \c GL_BGRA are supported.
|
||||
* \param fb_type Type of the pixels in the framebuffer. Currently only
|
||||
* \c GL_UNSIGNED_SHORT_5_6_5,
|
||||
* \c GL_UNSIGNED_SHORT_5_6_5_REV,
|
||||
* \c GL_UNSIGNED_INT_8_8_8_8, and
|
||||
* \c GL_UNSIGNED_INT_8_8_8_8_REV are supported.
|
||||
* \param depth_bits Array of depth buffer sizes to be exposed.
|
||||
* \param stencil_bits Array of stencil buffer sizes to be exposed.
|
||||
* \param num_depth_stencil_bits Number of entries in both \c depth_bits and
|
||||
* \c stencil_bits.
|
||||
* \param db_modes Array of buffer swap modes. If an element has a
|
||||
* value of \c GLX_NONE, then it represents a
|
||||
* single-buffered mode. Other valid values are
|
||||
* \c GLX_SWAP_EXCHANGE_OML, \c GLX_SWAP_COPY_OML, and
|
||||
* \c GLX_SWAP_UNDEFINED_OML. See the
|
||||
* GLX_OML_swap_method extension spec for more details.
|
||||
* \param num_db_modes Number of entries in \c db_modes.
|
||||
* \param visType GLX visual type. Usually either \c GLX_TRUE_COLOR or
|
||||
* \c GLX_DIRECT_COLOR.
|
||||
*
|
||||
* \returns
|
||||
* \c GL_TRUE on success or \c GL_FALSE on failure. Currently the only
|
||||
* cause of failure is a bad parameter (i.e., unsupported \c fb_format or
|
||||
* \c fb_type).
|
||||
*
|
||||
* \todo
|
||||
* There is currently no way to support packed RGB modes (i.e., modes with
|
||||
* exactly 3 bytes per pixel) or floating-point modes. This could probably
|
||||
* be done by creating some new, private enums with clever names likes
|
||||
* \c GL_UNSIGNED_3BYTE_8_8_8, \c GL_4FLOAT_32_32_32_32,
|
||||
* \c GL_4HALF_16_16_16_16, etc. We can cross that bridge when we come to it.
|
||||
*/
|
||||
GLboolean
|
||||
_eglFillInConfigs(_EGLConfig * configs,
|
||||
GLenum fb_format, GLenum fb_type,
|
||||
const uint8_t * depth_bits, const uint8_t * stencil_bits,
|
||||
unsigned num_depth_stencil_bits,
|
||||
const GLenum * db_modes, unsigned num_db_modes,
|
||||
int visType)
|
||||
{
|
||||
static const uint8_t bits_table[3][4] = {
|
||||
/* R G B A */
|
||||
{ 5, 6, 5, 0 }, /* Any GL_UNSIGNED_SHORT_5_6_5 */
|
||||
{ 8, 8, 8, 0 }, /* Any RGB with any GL_UNSIGNED_INT_8_8_8_8 */
|
||||
{ 8, 8, 8, 8 } /* Any RGBA with any GL_UNSIGNED_INT_8_8_8_8 */
|
||||
};
|
||||
|
||||
/* The following arrays are all indexed by the fb_type masked with 0x07.
|
||||
* Given the four supported fb_type values, this results in valid array
|
||||
* indices of 3, 4, 5, and 7.
|
||||
*/
|
||||
static const uint32_t masks_table_rgb[8][4] = {
|
||||
{0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000F800, 0x000007E0, 0x0000001F, 0x00000000}, /* 5_6_5 */
|
||||
{0x0000001F, 0x000007E0, 0x0000F800, 0x00000000}, /* 5_6_5_REV */
|
||||
{0xFF000000, 0x00FF0000, 0x0000FF00, 0x00000000}, /* 8_8_8_8 */
|
||||
{0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000} /* 8_8_8_8_REV */
|
||||
};
|
||||
|
||||
static const uint32_t masks_table_rgba[8][4] = {
|
||||
{0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000F800, 0x000007E0, 0x0000001F, 0x00000000}, /* 5_6_5 */
|
||||
{0x0000001F, 0x000007E0, 0x0000F800, 0x00000000}, /* 5_6_5_REV */
|
||||
{0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF}, /* 8_8_8_8 */
|
||||
{0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000}, /* 8_8_8_8_REV */
|
||||
};
|
||||
|
||||
static const uint32_t masks_table_bgr[8][4] = {
|
||||
{0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000001F, 0x000007E0, 0x0000F800, 0x00000000}, /* 5_6_5 */
|
||||
{0x0000F800, 0x000007E0, 0x0000001F, 0x00000000}, /* 5_6_5_REV */
|
||||
{0x0000FF00, 0x00FF0000, 0xFF000000, 0x00000000}, /* 8_8_8_8 */
|
||||
{0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000}, /* 8_8_8_8_REV */
|
||||
};
|
||||
|
||||
static const uint32_t masks_table_bgra[8][4] = {
|
||||
{0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000001F, 0x000007E0, 0x0000F800, 0x00000000}, /* 5_6_5 */
|
||||
{0x0000F800, 0x000007E0, 0x0000001F, 0x00000000}, /* 5_6_5_REV */
|
||||
{0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF}, /* 8_8_8_8 */
|
||||
{0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000}, /* 8_8_8_8_REV */
|
||||
};
|
||||
|
||||
static const uint8_t bytes_per_pixel[8] = {
|
||||
0, 0, 0, 2, 2, 4, 0, 4
|
||||
};
|
||||
|
||||
const uint8_t * bits;
|
||||
const uint32_t * masks;
|
||||
const int index = fb_type & 0x07;
|
||||
_EGLConfig *config;
|
||||
unsigned i;
|
||||
unsigned j;
|
||||
unsigned k;
|
||||
|
||||
if ( bytes_per_pixel[index] == 0 ) {
|
||||
_eglLog(_EGL_INFO,
|
||||
"[%s:%u] Framebuffer type 0x%04x has 0 bytes per pixel.",
|
||||
__FUNCTION__, __LINE__, fb_type);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
/* Valid types are GL_UNSIGNED_SHORT_5_6_5 and GL_UNSIGNED_INT_8_8_8_8 and
|
||||
* the _REV versions.
|
||||
*
|
||||
* Valid formats are GL_RGBA, GL_RGB, and GL_BGRA.
|
||||
*/
|
||||
switch ( fb_format ) {
|
||||
case GL_RGB:
|
||||
bits = (bytes_per_pixel[index] == 2) ? bits_table[0] : bits_table[1];
|
||||
masks = masks_table_rgb[index];
|
||||
break;
|
||||
|
||||
case GL_RGBA:
|
||||
bits = (bytes_per_pixel[index] == 2) ? bits_table[0] : bits_table[2];
|
||||
masks = masks_table_rgba[index];
|
||||
break;
|
||||
|
||||
case GL_BGR:
|
||||
bits = (bytes_per_pixel[index] == 2) ? bits_table[0] : bits_table[1];
|
||||
masks = masks_table_bgr[index];
|
||||
break;
|
||||
|
||||
case GL_BGRA:
|
||||
bits = (bytes_per_pixel[index] == 2) ? bits_table[0] : bits_table[2];
|
||||
masks = masks_table_bgra[index];
|
||||
break;
|
||||
|
||||
default:
|
||||
_eglLog(_EGL_WARNING,
|
||||
"[%s:%u] Framebuffer format 0x%04x is not GL_RGB, GL_RGBA, GL_BGR, or GL_BGRA.",
|
||||
__FUNCTION__, __LINE__, fb_format);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
config = configs;
|
||||
for (k = 0; k < num_depth_stencil_bits; k++) {
|
||||
for (i = 0; i < num_db_modes; i++) {
|
||||
for (j = 0; j < 2; j++) {
|
||||
_eglSetConfigAttrib(config, EGL_RED_SIZE, bits[0]);
|
||||
_eglSetConfigAttrib(config, EGL_GREEN_SIZE, bits[1]);
|
||||
_eglSetConfigAttrib(config, EGL_BLUE_SIZE, bits[2]);
|
||||
_eglSetConfigAttrib(config, EGL_ALPHA_SIZE, bits[3]);
|
||||
_eglSetConfigAttrib(config, EGL_BUFFER_SIZE,
|
||||
bits[0] + bits[1] + bits[2] + bits[3]);
|
||||
|
||||
_eglSetConfigAttrib(config, EGL_STENCIL_SIZE, stencil_bits[k]);
|
||||
_eglSetConfigAttrib(config, EGL_DEPTH_SIZE, depth_bits[i]);
|
||||
|
||||
_eglSetConfigAttrib(config, EGL_SURFACE_TYPE, EGL_SCREEN_BIT_MESA |
|
||||
EGL_PBUFFER_BIT | EGL_PIXMAP_BIT | EGL_WINDOW_BIT);
|
||||
|
||||
config++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return GL_TRUE;
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
#ifndef EGLCONFIG_INCLUDED
|
||||
#define EGLCONFIG_INCLUDED
|
||||
|
||||
|
||||
#include "egltypedefs.h"
|
||||
#include "GL/internal/glcore.h"
|
||||
|
||||
|
||||
#define MAX_ATTRIBS 100
|
||||
#define FIRST_ATTRIB EGL_BUFFER_SIZE
|
||||
|
||||
|
||||
struct _egl_config
|
||||
{
|
||||
EGLConfig Handle; /* the public/opaque handle which names this config */
|
||||
EGLint Attrib[MAX_ATTRIBS];
|
||||
};
|
||||
|
||||
|
||||
#define SET_CONFIG_ATTRIB(CONF, ATTR, VAL) ((CONF)->Attrib[(ATTR) - FIRST_ATTRIB] = VAL)
|
||||
#define GET_CONFIG_ATTRIB(CONF, ATTR) ((CONF)->Attrib[(ATTR) - FIRST_ATTRIB])
|
||||
|
||||
|
||||
extern void
|
||||
_eglInitConfig(_EGLConfig *config, EGLint id);
|
||||
|
||||
|
||||
extern _EGLConfig *
|
||||
_eglLookupConfig(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config);
|
||||
|
||||
|
||||
extern _EGLConfig *
|
||||
_eglAddConfig(_EGLDisplay *display, const _EGLConfig *config);
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
_eglParseConfigAttribs(_EGLConfig *config, const EGLint *attrib_list);
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
_eglChooseConfig(_EGLDriver *drv, EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
_eglGetConfigAttrib(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value);
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
_eglGetConfigs(_EGLDriver *drv, EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config);
|
||||
|
||||
|
||||
extern void
|
||||
_eglSetConfigAttrib(_EGLConfig *config, EGLint attr, EGLint val);
|
||||
|
||||
extern GLboolean
|
||||
_eglFillInConfigs( _EGLConfig *configs,
|
||||
GLenum fb_format, GLenum fb_type,
|
||||
const uint8_t * depth_bits, const uint8_t * stencil_bits,
|
||||
unsigned num_depth_stencil_bits,
|
||||
const GLenum * db_modes, unsigned num_db_modes,
|
||||
int visType );
|
||||
|
||||
extern void
|
||||
_eglConfigToContextModesRec(const _EGLConfig *config, __GLcontextModes *mode);
|
||||
|
||||
|
||||
#endif /* EGLCONFIG_INCLUDED */
|
||||
@@ -1,276 +0,0 @@
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "eglconfig.h"
|
||||
#include "eglcontext.h"
|
||||
#include "egldisplay.h"
|
||||
#include "egldriver.h"
|
||||
#include "eglglobals.h"
|
||||
#include "eglhash.h"
|
||||
#include "eglsurface.h"
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the given _EGLContext object to defaults.
|
||||
*/
|
||||
EGLBoolean
|
||||
_eglInitContext(_EGLDriver *drv, EGLDisplay dpy, _EGLContext *ctx,
|
||||
EGLConfig config, const EGLint *attrib_list)
|
||||
{
|
||||
_EGLConfig *conf;
|
||||
_EGLDisplay *display = _eglLookupDisplay(dpy);
|
||||
EGLint i;
|
||||
|
||||
conf = _eglLookupConfig(drv, dpy, config);
|
||||
if (!conf) {
|
||||
_eglError(EGL_BAD_CONFIG, "eglCreateContext");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
|
||||
switch (attrib_list[i]) {
|
||||
/* no attribs defined for now */
|
||||
default:
|
||||
_eglError(EGL_BAD_ATTRIBUTE, "eglCreateContext");
|
||||
return EGL_NO_CONTEXT;
|
||||
}
|
||||
}
|
||||
|
||||
memset(ctx, 0, sizeof(_EGLContext));
|
||||
ctx->Display = display;
|
||||
ctx->Config = conf;
|
||||
ctx->DrawSurface = EGL_NO_SURFACE;
|
||||
ctx->ReadSurface = EGL_NO_SURFACE;
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Assign an EGLContext handle to the _EGLContext object then put it into
|
||||
* the hash table.
|
||||
*/
|
||||
void
|
||||
_eglSaveContext(_EGLContext *ctx)
|
||||
{
|
||||
assert(ctx);
|
||||
ctx->Handle = _eglHashGenKey(_eglGlobal.Contexts);
|
||||
_eglHashInsert(_eglGlobal.Contexts, ctx->Handle, ctx);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove the given _EGLContext object from the hash table.
|
||||
*/
|
||||
void
|
||||
_eglRemoveContext(_EGLContext *ctx)
|
||||
{
|
||||
_eglHashRemove(_eglGlobal.Contexts, ctx->Handle);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the _EGLContext object that corresponds to the given
|
||||
* EGLContext handle.
|
||||
*/
|
||||
_EGLContext *
|
||||
_eglLookupContext(EGLContext ctx)
|
||||
{
|
||||
_EGLContext *c = (_EGLContext *) _eglHashLookup(_eglGlobal.Contexts, ctx);
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the currently bound _EGLContext object, or NULL.
|
||||
*/
|
||||
_EGLContext *
|
||||
_eglGetCurrentContext(void)
|
||||
{
|
||||
_EGLThreadInfo *t = _eglGetCurrentThread();
|
||||
return t->CurrentContext;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Just a placeholder/demo function. Real driver will never use this!
|
||||
*/
|
||||
EGLContext
|
||||
_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
|
||||
EGLContext share_list, const EGLint *attrib_list)
|
||||
{
|
||||
#if 0 /* example code */
|
||||
_EGLContext *context;
|
||||
|
||||
context = (_EGLContext *) calloc(1, sizeof(_EGLContext));
|
||||
if (!context)
|
||||
return EGL_NO_CONTEXT;
|
||||
|
||||
if (!_eglInitContext(drv, dpy, context, config, attrib_list)) {
|
||||
free(context);
|
||||
return EGL_NO_CONTEXT;
|
||||
}
|
||||
|
||||
_eglSaveContext(context);
|
||||
return context->Handle;
|
||||
#endif
|
||||
return EGL_NO_CONTEXT;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Default fallback routine - drivers should usually override this.
|
||||
*/
|
||||
EGLBoolean
|
||||
_eglDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx)
|
||||
{
|
||||
_EGLContext *context = _eglLookupContext(ctx);
|
||||
if (context) {
|
||||
_eglHashRemove(_eglGlobal.Contexts, ctx);
|
||||
if (context->IsBound) {
|
||||
context->DeletePending = EGL_TRUE;
|
||||
}
|
||||
else {
|
||||
free(context);
|
||||
}
|
||||
return EGL_TRUE;
|
||||
}
|
||||
else {
|
||||
_eglError(EGL_BAD_CONTEXT, "eglDestroyContext");
|
||||
return EGL_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean
|
||||
_eglQueryContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx,
|
||||
EGLint attribute, EGLint *value)
|
||||
{
|
||||
_EGLContext *c = _eglLookupContext(ctx);
|
||||
|
||||
(void) drv;
|
||||
(void) dpy;
|
||||
|
||||
if (!c) {
|
||||
_eglError(EGL_BAD_CONTEXT, "eglQueryContext");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
switch (attribute) {
|
||||
case EGL_CONFIG_ID:
|
||||
*value = GET_CONFIG_ATTRIB(c->Config, EGL_CONFIG_ID);
|
||||
return EGL_TRUE;
|
||||
#ifdef EGL_VERSION_1_2
|
||||
case EGL_CONTEXT_CLIENT_TYPE:
|
||||
*value = c->ClientAPI;
|
||||
return EGL_FALSE;
|
||||
#endif /* EGL_VERSION_1_2 */
|
||||
default:
|
||||
_eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Drivers will typically call this to do the error checking and
|
||||
* update the various IsBound and DeletePending flags.
|
||||
* Then, the driver will do its device-dependent Make-Current stuff.
|
||||
*/
|
||||
EGLBoolean
|
||||
_eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d,
|
||||
EGLSurface r, EGLContext context)
|
||||
{
|
||||
_EGLThreadInfo *t = _eglGetCurrentThread();
|
||||
_EGLContext *ctx = _eglLookupContext(context);
|
||||
_EGLSurface *draw = _eglLookupSurface(d);
|
||||
_EGLSurface *read = _eglLookupSurface(r);
|
||||
|
||||
_EGLContext *oldContext = _eglGetCurrentContext();
|
||||
_EGLSurface *oldDrawSurface = _eglGetCurrentSurface(EGL_DRAW);
|
||||
_EGLSurface *oldReadSurface = _eglGetCurrentSurface(EGL_READ);
|
||||
|
||||
/* error checking */
|
||||
if (ctx) {
|
||||
if (draw == NULL || read == NULL) {
|
||||
_eglError(EGL_BAD_MATCH, "eglMakeCurrent");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
if (draw->Config != ctx->Config) {
|
||||
_eglError(EGL_BAD_MATCH, "eglMakeCurrent");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
if (read->Config != ctx->Config) {
|
||||
_eglError(EGL_BAD_MATCH, "eglMakeCurrent");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* check if the old context or surfaces need to be deleted
|
||||
*/
|
||||
if (oldDrawSurface != NULL) {
|
||||
oldDrawSurface->IsBound = EGL_FALSE;
|
||||
if (oldDrawSurface->DeletePending) {
|
||||
/* make sure we don't try to rebind a deleted surface */
|
||||
if (draw == oldDrawSurface || draw == oldReadSurface) {
|
||||
draw = NULL;
|
||||
}
|
||||
/* really delete surface now */
|
||||
drv->API.DestroySurface(drv, dpy, oldDrawSurface->Handle);
|
||||
}
|
||||
}
|
||||
if (oldReadSurface != NULL && oldReadSurface != oldDrawSurface) {
|
||||
oldReadSurface->IsBound = EGL_FALSE;
|
||||
if (oldReadSurface->DeletePending) {
|
||||
/* make sure we don't try to rebind a deleted surface */
|
||||
if (read == oldDrawSurface || read == oldReadSurface) {
|
||||
read = NULL;
|
||||
}
|
||||
/* really delete surface now */
|
||||
drv->API.DestroySurface(drv, dpy, oldReadSurface->Handle);
|
||||
}
|
||||
}
|
||||
if (oldContext != NULL) {
|
||||
oldContext->IsBound = EGL_FALSE;
|
||||
if (oldContext->DeletePending) {
|
||||
/* make sure we don't try to rebind a deleted context */
|
||||
if (ctx == oldContext) {
|
||||
ctx = NULL;
|
||||
}
|
||||
/* really delete context now */
|
||||
drv->API.DestroyContext(drv, dpy, oldContext->Handle);
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx) {
|
||||
/* check read/draw again, in case we deleted them above */
|
||||
if (draw == NULL || read == NULL) {
|
||||
_eglError(EGL_BAD_MATCH, "eglMakeCurrent");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
ctx->DrawSurface = draw;
|
||||
ctx->ReadSurface = read;
|
||||
ctx->IsBound = EGL_TRUE;
|
||||
draw->IsBound = EGL_TRUE;
|
||||
read->IsBound = EGL_TRUE;
|
||||
}
|
||||
|
||||
t->CurrentContext = ctx;
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This is defined by the EGL_MESA_copy_context extension.
|
||||
*/
|
||||
EGLBoolean
|
||||
_eglCopyContextMESA(_EGLDriver *drv, EGLDisplay dpy, EGLContext source,
|
||||
EGLContext dest, EGLint mask)
|
||||
{
|
||||
/* This function will always have to be overridden/implemented in the
|
||||
* device driver. If the driver is based on Mesa, use _mesa_copy_context().
|
||||
*/
|
||||
return EGL_FALSE;
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
|
||||
#ifndef EGLCONTEXT_INCLUDED
|
||||
#define EGLCONTEXT_INCLUDED
|
||||
|
||||
|
||||
#include "egltypedefs.h"
|
||||
|
||||
|
||||
/**
|
||||
* "Base" class for device driver contexts.
|
||||
*/
|
||||
struct _egl_context
|
||||
{
|
||||
EGLContext Handle; /* The public/opaque handle which names this object */
|
||||
|
||||
_EGLDisplay *Display; /* who do I belong to? */
|
||||
|
||||
_EGLConfig *Config;
|
||||
|
||||
_EGLSurface *DrawSurface;
|
||||
_EGLSurface *ReadSurface;
|
||||
|
||||
EGLBoolean IsBound;
|
||||
EGLBoolean DeletePending;
|
||||
#ifdef EGL_VERSION_1_2
|
||||
EGLint ClientAPI; /* Either EGL_OPENGL_ES_API or EGL_OPENVG_API */
|
||||
#endif /* EGL_VERSION_1_2 */
|
||||
};
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
_eglInitContext(_EGLDriver *drv, EGLDisplay dpy, _EGLContext *ctx,
|
||||
EGLConfig config, const EGLint *attrib_list);
|
||||
|
||||
|
||||
extern void
|
||||
_eglSaveContext(_EGLContext *ctx);
|
||||
|
||||
|
||||
extern void
|
||||
_eglRemoveContext(_EGLContext *ctx);
|
||||
|
||||
|
||||
extern _EGLContext *
|
||||
_eglLookupContext(EGLContext ctx);
|
||||
|
||||
|
||||
extern _EGLContext *
|
||||
_eglGetCurrentContext(void);
|
||||
|
||||
|
||||
extern EGLContext
|
||||
_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list);
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
_eglDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx);
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
_eglQueryContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value);
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
_eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
_eglCopyContextMESA(_EGLDriver *drv, EGLDisplay dpy, EGLContext source, EGLContext dest, EGLint mask);
|
||||
|
||||
#endif /* EGLCONTEXT_INCLUDED */
|
||||
@@ -1,71 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "eglcontext.h"
|
||||
#include "egldisplay.h"
|
||||
#include "eglglobals.h"
|
||||
#include "eglhash.h"
|
||||
|
||||
|
||||
static char *
|
||||
my_strdup(const char *s)
|
||||
{
|
||||
int l = strlen(s);
|
||||
char *s2 = malloc(l + 1);
|
||||
strcpy(s2, s);
|
||||
return s2;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* We're assuming that the NativeDisplayType parameter is actually
|
||||
* a string.
|
||||
* Return a new _EGLDisplay object for the given displayName
|
||||
*/
|
||||
_EGLDisplay *
|
||||
_eglNewDisplay(NativeDisplayType displayName)
|
||||
{
|
||||
_EGLDisplay *dpy = (_EGLDisplay *) calloc(1, sizeof(_EGLDisplay));
|
||||
if (dpy) {
|
||||
dpy->Handle = _eglHashGenKey(_eglGlobal.Displays);
|
||||
_eglHashInsert(_eglGlobal.Displays, dpy->Handle, dpy);
|
||||
if (displayName)
|
||||
dpy->Name = my_strdup(displayName);
|
||||
else
|
||||
dpy->Name = NULL;
|
||||
dpy->Driver = NULL; /* this gets set later */
|
||||
}
|
||||
return dpy;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the _EGLDisplay object that corresponds to the given public/
|
||||
* opaque display handle.
|
||||
*/
|
||||
_EGLDisplay *
|
||||
_eglLookupDisplay(EGLDisplay dpy)
|
||||
{
|
||||
_EGLDisplay *d = (_EGLDisplay *) _eglHashLookup(_eglGlobal.Displays, dpy);
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
_EGLDisplay *
|
||||
_eglGetCurrentDisplay(void)
|
||||
{
|
||||
_EGLContext *ctx = _eglGetCurrentContext();
|
||||
if (ctx)
|
||||
return ctx->Display;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_eglCleanupDisplay(_EGLDisplay *disp)
|
||||
{
|
||||
/* XXX incomplete */
|
||||
free(disp->Configs);
|
||||
free(disp->Name);
|
||||
/* driver deletes _EGLDisplay */
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
#ifndef EGLDISPLAY_INCLUDED
|
||||
#define EGLDISPLAY_INCLUDED
|
||||
|
||||
|
||||
#include "egltypedefs.h"
|
||||
|
||||
|
||||
struct _egl_display
|
||||
{
|
||||
EGLDisplay Handle;
|
||||
|
||||
char *Name;
|
||||
_EGLDriver *Driver;
|
||||
|
||||
EGLint NumScreens;
|
||||
_EGLScreen **Screens; /* array [NumScreens] */
|
||||
|
||||
EGLint NumConfigs;
|
||||
_EGLConfig *Configs; /* array [NumConfigs] */
|
||||
};
|
||||
|
||||
|
||||
extern _EGLDisplay *
|
||||
_eglNewDisplay(NativeDisplayType displayName);
|
||||
|
||||
|
||||
extern _EGLDisplay *
|
||||
_eglLookupDisplay(EGLDisplay dpy);
|
||||
|
||||
|
||||
extern _EGLDisplay *
|
||||
_eglGetCurrentDisplay(void);
|
||||
|
||||
|
||||
extern void
|
||||
_eglCleanupDisplay(_EGLDisplay *disp);
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
_eglQueryDisplayMESA(_EGLDriver *drv, EGLDisplay dpy, EGLint attrib, EGLint *value);
|
||||
|
||||
|
||||
|
||||
#endif /* EGLDISPLAY_INCLUDED */
|
||||
@@ -1,272 +0,0 @@
|
||||
#include <assert.h>
|
||||
#include <dlfcn.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "eglconfig.h"
|
||||
#include "eglcontext.h"
|
||||
#include "egldisplay.h"
|
||||
#include "egldriver.h"
|
||||
#include "eglglobals.h"
|
||||
#include "egllog.h"
|
||||
#include "eglmode.h"
|
||||
#include "eglscreen.h"
|
||||
#include "eglsurface.h"
|
||||
|
||||
|
||||
const char *DefaultDriverName = "demodriver";
|
||||
|
||||
|
||||
/**
|
||||
* Choose and open/init the hardware driver for the given EGLDisplay.
|
||||
* Previously, the EGLDisplay was created with _eglNewDisplay() where
|
||||
* we recorded the user's NativeDisplayType parameter.
|
||||
*
|
||||
* Now we'll use the NativeDisplayType value.
|
||||
*
|
||||
* Currently, the native display value is treated as a string.
|
||||
* If the first character is ':' we interpret it as a screen or card index
|
||||
* number (i.e. ":0" or ":1", etc)
|
||||
* Else if the first character is '!' we interpret it as specific driver name
|
||||
* (i.e. "!r200" or "!i830".
|
||||
*/
|
||||
_EGLDriver *
|
||||
_eglChooseDriver(EGLDisplay display)
|
||||
{
|
||||
_EGLDisplay *dpy = _eglLookupDisplay(display);
|
||||
_EGLDriver *drv;
|
||||
const char *driverName = DefaultDriverName;
|
||||
const char *name;
|
||||
|
||||
assert(dpy);
|
||||
|
||||
name = dpy->Name;
|
||||
if (!name) {
|
||||
/* use default */
|
||||
}
|
||||
else if (name[0] == ':' && (name[1] >= '0' && name[1] <= '9') && !name[2]) {
|
||||
/* XXX probe hardware here to determine which driver to open */
|
||||
driverName = "libEGLdri";
|
||||
}
|
||||
else if (name[0] == '!') {
|
||||
/* use specified driver name */
|
||||
driverName = name + 1;
|
||||
}
|
||||
else {
|
||||
/* Maybe display was returned by XOpenDisplay? */
|
||||
_eglLog(_EGL_FATAL, "eglChooseDriver() bad name");
|
||||
}
|
||||
|
||||
_eglLog(_EGL_INFO, "eglChooseDriver() choosing %s", driverName);
|
||||
|
||||
drv = _eglOpenDriver(dpy, driverName);
|
||||
dpy->Driver = drv;
|
||||
|
||||
return drv;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Open/load the named driver and call its bootstrap function: _eglMain().
|
||||
* \return new _EGLDriver object.
|
||||
*/
|
||||
_EGLDriver *
|
||||
_eglOpenDriver(_EGLDisplay *dpy, const char *driverName)
|
||||
{
|
||||
_EGLDriver *drv;
|
||||
_EGLMain_t mainFunc;
|
||||
void *lib;
|
||||
char driverFilename[1000];
|
||||
|
||||
/* XXX also prepend a directory path??? */
|
||||
sprintf(driverFilename, "%s.so", driverName);
|
||||
|
||||
_eglLog(_EGL_DEBUG, "dlopen(%s)", driverFilename);
|
||||
lib = dlopen(driverFilename, RTLD_NOW);
|
||||
if (!lib) {
|
||||
_eglLog(_EGL_WARNING, "Could not open %s (%s)",
|
||||
driverFilename, dlerror());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mainFunc = (_EGLMain_t) dlsym(lib, "_eglMain");
|
||||
if (!mainFunc) {
|
||||
_eglLog(_EGL_WARNING, "_eglMain not found in %s", driverFilename);
|
||||
dlclose(lib);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
drv = mainFunc(dpy);
|
||||
if (!drv) {
|
||||
dlclose(lib);
|
||||
return NULL;
|
||||
}
|
||||
/* with a recurvise open you want the inner most handle */
|
||||
if (!drv->LibHandle)
|
||||
drv->LibHandle = lib;
|
||||
else
|
||||
dlclose(lib);
|
||||
|
||||
drv->Display = dpy;
|
||||
return drv;
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean
|
||||
_eglCloseDriver(_EGLDriver *drv, EGLDisplay dpy)
|
||||
{
|
||||
void *handle = drv->LibHandle;
|
||||
EGLBoolean b;
|
||||
|
||||
_eglLog(_EGL_INFO, "Closing driver");
|
||||
|
||||
/*
|
||||
* XXX check for currently bound context/surfaces and delete them?
|
||||
*/
|
||||
|
||||
b = drv->API.Terminate(drv, dpy);
|
||||
dlclose(handle);
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Given a display handle, return the _EGLDriver for that display.
|
||||
*/
|
||||
_EGLDriver *
|
||||
_eglLookupDriver(EGLDisplay dpy)
|
||||
{
|
||||
_EGLDisplay *d = _eglLookupDisplay(dpy);
|
||||
if (d)
|
||||
return d->Driver;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Plug all the available fallback routines into the given driver's
|
||||
* dispatch table.
|
||||
*/
|
||||
void
|
||||
_eglInitDriverFallbacks(_EGLDriver *drv)
|
||||
{
|
||||
/* If a pointer is set to NULL, then the device driver _really_ has
|
||||
* to implement it.
|
||||
*/
|
||||
drv->API.Initialize = NULL;
|
||||
drv->API.Terminate = NULL;
|
||||
|
||||
drv->API.GetConfigs = _eglGetConfigs;
|
||||
drv->API.ChooseConfig = _eglChooseConfig;
|
||||
drv->API.GetConfigAttrib = _eglGetConfigAttrib;
|
||||
|
||||
drv->API.CreateContext = _eglCreateContext;
|
||||
drv->API.DestroyContext = _eglDestroyContext;
|
||||
drv->API.MakeCurrent = _eglMakeCurrent;
|
||||
drv->API.QueryContext = _eglQueryContext;
|
||||
|
||||
drv->API.CreateWindowSurface = _eglCreateWindowSurface;
|
||||
drv->API.CreatePixmapSurface = _eglCreatePixmapSurface;
|
||||
drv->API.CreatePbufferSurface = _eglCreatePbufferSurface;
|
||||
drv->API.DestroySurface = _eglDestroySurface;
|
||||
drv->API.QuerySurface = _eglQuerySurface;
|
||||
drv->API.SurfaceAttrib = _eglSurfaceAttrib;
|
||||
drv->API.BindTexImage = _eglBindTexImage;
|
||||
drv->API.ReleaseTexImage = _eglReleaseTexImage;
|
||||
drv->API.SwapInterval = _eglSwapInterval;
|
||||
drv->API.SwapBuffers = _eglSwapBuffers;
|
||||
drv->API.CopyBuffers = _eglCopyBuffers;
|
||||
|
||||
drv->API.QueryString = _eglQueryString;
|
||||
drv->API.WaitGL = _eglWaitGL;
|
||||
drv->API.WaitNative = _eglWaitNative;
|
||||
|
||||
#ifdef EGL_MESA_screen_surface
|
||||
drv->API.ChooseModeMESA = _eglChooseModeMESA;
|
||||
drv->API.GetModesMESA = _eglGetModesMESA;
|
||||
drv->API.GetModeAttribMESA = _eglGetModeAttribMESA;
|
||||
drv->API.GetScreensMESA = _eglGetScreensMESA;
|
||||
drv->API.CreateScreenSurfaceMESA = _eglCreateScreenSurfaceMESA;
|
||||
drv->API.ShowScreenSurfaceMESA = _eglShowScreenSurfaceMESA;
|
||||
drv->API.ScreenPositionMESA = _eglScreenPositionMESA;
|
||||
drv->API.QueryScreenMESA = _eglQueryScreenMESA;
|
||||
drv->API.QueryScreenSurfaceMESA = _eglQueryScreenSurfaceMESA;
|
||||
drv->API.QueryScreenModeMESA = _eglQueryScreenModeMESA;
|
||||
drv->API.QueryModeStringMESA = _eglQueryModeStringMESA;
|
||||
#endif /* EGL_MESA_screen_surface */
|
||||
|
||||
#ifdef EGL_VERSION_1_2
|
||||
drv->API.CreatePbufferFromClientBuffer = _eglCreatePbufferFromClientBuffer;
|
||||
#endif /* EGL_VERSION_1_2 */
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Examine the individual extension enable/disable flags and recompute
|
||||
* the driver's Extensions string.
|
||||
*/
|
||||
static void
|
||||
_eglUpdateExtensionsString(_EGLDriver *drv)
|
||||
{
|
||||
drv->Extensions.String[0] = 0;
|
||||
|
||||
if (drv->Extensions.MESA_screen_surface)
|
||||
strcat(drv->Extensions.String, "EGL_MESA_screen_surface ");
|
||||
if (drv->Extensions.MESA_copy_context)
|
||||
strcat(drv->Extensions.String, "EGL_MESA_copy_context ");
|
||||
assert(strlen(drv->Extensions.String) < MAX_EXTENSIONS_LEN);
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *
|
||||
_eglQueryString(_EGLDriver *drv, EGLDisplay dpy, EGLint name)
|
||||
{
|
||||
(void) drv;
|
||||
(void) dpy;
|
||||
switch (name) {
|
||||
case EGL_VENDOR:
|
||||
return "Mesa Project";
|
||||
case EGL_VERSION:
|
||||
return "1.0";
|
||||
case EGL_EXTENSIONS:
|
||||
_eglUpdateExtensionsString(drv);
|
||||
return drv->Extensions.String;
|
||||
#ifdef EGL_VERSION_1_2
|
||||
case EGL_CLIENT_APIS:
|
||||
/* XXX need to initialize somewhere */
|
||||
return drv->ClientAPIs;
|
||||
#endif
|
||||
default:
|
||||
_eglError(EGL_BAD_PARAMETER, "eglQueryString");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean
|
||||
_eglWaitGL(_EGLDriver *drv, EGLDisplay dpy)
|
||||
{
|
||||
/* just a placeholder */
|
||||
(void) drv;
|
||||
(void) dpy;
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean
|
||||
_eglWaitNative(_EGLDriver *drv, EGLDisplay dpy, EGLint engine)
|
||||
{
|
||||
/* just a placeholder */
|
||||
(void) drv;
|
||||
(void) dpy;
|
||||
switch (engine) {
|
||||
case EGL_CORE_NATIVE_ENGINE:
|
||||
break;
|
||||
default:
|
||||
_eglError(EGL_BAD_PARAMETER, "eglWaitNative(engine)");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
#ifndef EGLDRIVER_INCLUDED
|
||||
#define EGLDRIVER_INCLUDED
|
||||
|
||||
|
||||
#include "egltypedefs.h"
|
||||
#include "eglapi.h"
|
||||
|
||||
/* should probably use a dynamic-length string, but this will do */
|
||||
#define MAX_EXTENSIONS_LEN 1000
|
||||
|
||||
|
||||
/**
|
||||
* Optional EGL extensions info.
|
||||
*/
|
||||
struct _egl_extensions
|
||||
{
|
||||
EGLBoolean MESA_screen_surface;
|
||||
EGLBoolean MESA_copy_context;
|
||||
|
||||
char String[MAX_EXTENSIONS_LEN];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Base class for device drivers.
|
||||
*/
|
||||
struct _egl_driver
|
||||
{
|
||||
EGLBoolean Initialized; /* set by driver after initialized */
|
||||
|
||||
void *LibHandle; /* dlopen handle */
|
||||
|
||||
_EGLDisplay *Display;
|
||||
|
||||
int ABIversion;
|
||||
int APImajor, APIminor; /* returned through eglInitialize */
|
||||
const char *ClientAPIs;
|
||||
|
||||
_EGLAPI API;
|
||||
|
||||
_EGLExtensions Extensions;
|
||||
};
|
||||
|
||||
|
||||
extern _EGLDriver *_eglMain(_EGLDisplay *dpy);
|
||||
|
||||
|
||||
extern _EGLDriver *
|
||||
_eglChooseDriver(EGLDisplay dpy);
|
||||
|
||||
|
||||
extern _EGLDriver *
|
||||
_eglOpenDriver(_EGLDisplay *dpy, const char *driverName);
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
_eglCloseDriver(_EGLDriver *drv, EGLDisplay dpy);
|
||||
|
||||
|
||||
extern _EGLDriver *
|
||||
_eglLookupDriver(EGLDisplay d);
|
||||
|
||||
|
||||
extern void
|
||||
_eglInitDriverFallbacks(_EGLDriver *drv);
|
||||
|
||||
|
||||
extern const char *
|
||||
_eglQueryString(_EGLDriver *drv, EGLDisplay dpy, EGLint name);
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
_eglWaitGL(_EGLDriver *drv, EGLDisplay dpy);
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
_eglWaitNative(_EGLDriver *drv, EGLDisplay dpy, EGLint engine);
|
||||
|
||||
|
||||
|
||||
#endif /* EGLDRIVER_INCLUDED */
|
||||
@@ -1,148 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "eglglobals.h"
|
||||
|
||||
|
||||
struct _egl_global _eglGlobal = { .Initialized = EGL_FALSE };
|
||||
|
||||
|
||||
/**
|
||||
* Init the fields in the _eglGlobal struct
|
||||
* May be safely called more than once.
|
||||
*/
|
||||
void
|
||||
_eglInitGlobals(void)
|
||||
{
|
||||
if (!_eglGlobal.Initialized) {
|
||||
_eglGlobal.Displays = _eglNewHashTable();
|
||||
_eglGlobal.Contexts = _eglNewHashTable();
|
||||
_eglGlobal.Surfaces = _eglNewHashTable();
|
||||
_eglGlobal.FreeScreenHandle = 1;
|
||||
_eglGlobal.Initialized = EGL_TRUE;
|
||||
|
||||
_eglGlobal.OpenGLESAPISupported = EGL_TRUE;
|
||||
_eglGlobal.OpenVGAPISupported = EGL_FALSE;
|
||||
|
||||
/* XXX temporary */
|
||||
_eglGlobal.ThreadInfo = _eglNewThreadInfo();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Should call this via an atexit handler.
|
||||
*/
|
||||
void
|
||||
_eglDestroyGlobals(void)
|
||||
{
|
||||
/* XXX TODO walk over table entries, deleting each */
|
||||
_eglDeleteHashTable(_eglGlobal.Displays);
|
||||
_eglDeleteHashTable(_eglGlobal.Contexts);
|
||||
_eglDeleteHashTable(_eglGlobal.Surfaces);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Allocate and init a new _EGLThreadInfo object.
|
||||
*/
|
||||
_EGLThreadInfo *
|
||||
_eglNewThreadInfo(void)
|
||||
{
|
||||
_EGLThreadInfo *t = (_EGLThreadInfo *) calloc(1, sizeof(_EGLThreadInfo));
|
||||
if (t) {
|
||||
t->CurrentContext = EGL_NO_CONTEXT;
|
||||
t->LastError = EGL_SUCCESS;
|
||||
t->CurrentAPI = EGL_NONE;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delete/free a _EGLThreadInfo object.
|
||||
*/
|
||||
void
|
||||
_eglDeleteThreadData(_EGLThreadInfo *t)
|
||||
{
|
||||
free(t);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return pointer to calling thread's _EGLThreadInfo object.
|
||||
* Create a new one if needed.
|
||||
* Should never return NULL.
|
||||
*/
|
||||
_EGLThreadInfo *
|
||||
_eglGetCurrentThread(void)
|
||||
{
|
||||
_eglInitGlobals();
|
||||
|
||||
/* XXX temporary */
|
||||
return _eglGlobal.ThreadInfo;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Record EGL error code.
|
||||
*/
|
||||
void
|
||||
_eglError(EGLint errCode, const char *msg)
|
||||
{
|
||||
_EGLThreadInfo *t = _eglGetCurrentThread();
|
||||
const char *s;
|
||||
|
||||
if (t->LastError == EGL_SUCCESS) {
|
||||
t->LastError = errCode;
|
||||
|
||||
switch (errCode) {
|
||||
case EGL_BAD_ACCESS:
|
||||
s = "EGL_BAD_ACCESS";
|
||||
break;
|
||||
case EGL_BAD_ALLOC:
|
||||
s = "EGL_BAD_ALLOC";
|
||||
break;
|
||||
case EGL_BAD_ATTRIBUTE:
|
||||
s = "EGL_BAD_ATTRIBUTE";
|
||||
break;
|
||||
case EGL_BAD_CONFIG:
|
||||
s = "EGL_BAD_CONFIG";
|
||||
break;
|
||||
case EGL_BAD_CONTEXT:
|
||||
s = "EGL_BAD_CONTEXT";
|
||||
break;
|
||||
case EGL_BAD_CURRENT_SURFACE:
|
||||
s = "EGL_BAD_CURRENT_SURFACE";
|
||||
break;
|
||||
case EGL_BAD_DISPLAY:
|
||||
s = "EGL_BAD_DISPLAY";
|
||||
break;
|
||||
case EGL_BAD_MATCH:
|
||||
s = "EGL_BAD_MATCH";
|
||||
break;
|
||||
case EGL_BAD_NATIVE_PIXMAP:
|
||||
s = "EGL_BAD_NATIVE_PIXMAP";
|
||||
break;
|
||||
case EGL_BAD_NATIVE_WINDOW:
|
||||
s = "EGL_BAD_NATIVE_WINDOW";
|
||||
break;
|
||||
case EGL_BAD_PARAMETER:
|
||||
s = "EGL_BAD_PARAMETER";
|
||||
break;
|
||||
case EGL_BAD_SURFACE:
|
||||
s = "EGL_BAD_SURFACE";
|
||||
break;
|
||||
case EGL_BAD_SCREEN_MESA:
|
||||
s = "EGL_BAD_SCREEN_MESA";
|
||||
break;
|
||||
case EGL_BAD_MODE_MESA:
|
||||
s = "EGL_BAD_MODE_MESA";
|
||||
break;
|
||||
default:
|
||||
s = "other";
|
||||
}
|
||||
/* XXX temporary */
|
||||
fprintf(stderr, "EGL user error 0x%x (%s) in %s\n", errCode, s, msg);
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
#ifndef EGLGLOBALS_INCLUDED
|
||||
#define EGLGLOBALS_INCLUDED
|
||||
|
||||
#include "egltypedefs.h"
|
||||
#include "eglhash.h"
|
||||
|
||||
|
||||
/**
|
||||
* Per-thread info
|
||||
*/
|
||||
struct _egl_thread_info
|
||||
{
|
||||
EGLint LastError;
|
||||
_EGLContext *CurrentContext;
|
||||
EGLenum CurrentAPI;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Global library data
|
||||
*/
|
||||
struct _egl_global
|
||||
{
|
||||
EGLBoolean Initialized;
|
||||
|
||||
_EGLHashtable *Displays;
|
||||
_EGLHashtable *Contexts;
|
||||
_EGLHashtable *Surfaces;
|
||||
|
||||
EGLScreenMESA FreeScreenHandle;
|
||||
|
||||
/* XXX these may be temporary */
|
||||
EGLBoolean OpenGLESAPISupported;
|
||||
EGLBoolean OpenVGAPISupported;
|
||||
|
||||
/* XXX temporary - should be thread-specific data (TSD) */
|
||||
_EGLThreadInfo *ThreadInfo;
|
||||
};
|
||||
|
||||
|
||||
extern struct _egl_global _eglGlobal;
|
||||
|
||||
|
||||
extern void
|
||||
_eglInitGlobals(void);
|
||||
|
||||
|
||||
extern void
|
||||
_eglDestroyGlobals(void);
|
||||
|
||||
|
||||
extern _EGLThreadInfo *
|
||||
_eglNewThreadInfo(void);
|
||||
|
||||
|
||||
extern void
|
||||
_eglDeleteThreadData(_EGLThreadInfo *t);
|
||||
|
||||
|
||||
extern _EGLThreadInfo *
|
||||
_eglGetCurrentThread(void);
|
||||
|
||||
|
||||
extern void
|
||||
_eglError(EGLint errCode, const char *msg);
|
||||
|
||||
|
||||
#endif /* EGLGLOBALS_INCLUDED */
|
||||
@@ -1,347 +0,0 @@
|
||||
/**
|
||||
* \file hash.c
|
||||
* Generic hash table.
|
||||
*
|
||||
* This code taken from Mesa and adapted.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "eglhash.h"
|
||||
|
||||
|
||||
#define TABLE_SIZE 1023 /**< Size of lookup table/array */
|
||||
|
||||
#define HASH_FUNC(K) ((K) % TABLE_SIZE)
|
||||
|
||||
|
||||
/*
|
||||
* Unfinished mutex stuff
|
||||
*/
|
||||
|
||||
typedef int _EGLMutex;
|
||||
|
||||
static void
|
||||
_eglInitMutex(_EGLMutex m)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
_eglDestroyMutex(_EGLMutex m)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
_eglLockMutex(_EGLMutex m)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
_eglUnlockMutex(_EGLMutex m)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
typedef struct _egl_hashentry _EGLHashentry;
|
||||
|
||||
struct _egl_hashentry
|
||||
{
|
||||
EGLuint Key; /**< the entry's key */
|
||||
void *Data; /**< the entry's data */
|
||||
_EGLHashentry *Next; /**< pointer to next entry */
|
||||
};
|
||||
|
||||
|
||||
struct _egl_hashtable
|
||||
{
|
||||
_EGLHashentry *Table[TABLE_SIZE]; /**< the lookup table */
|
||||
EGLuint MaxKey; /**< highest key inserted so far */
|
||||
_EGLMutex Mutex; /**< mutual exclusion lock */
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create a new hash table.
|
||||
*
|
||||
* \return pointer to a new, empty hash table.
|
||||
*/
|
||||
_EGLHashtable *
|
||||
_eglNewHashTable(void)
|
||||
{
|
||||
_EGLHashtable *table = (_EGLHashtable *) calloc(1, sizeof(_EGLHashtable));
|
||||
if (table) {
|
||||
_eglInitMutex(table->Mutex);
|
||||
table->MaxKey = 1;
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Delete a hash table.
|
||||
* Frees each entry on the hash table and then the hash table structure itself.
|
||||
* Note that the caller should have already traversed the table and deleted
|
||||
* the objects in the table (i.e. We don't free the entries' data pointer).
|
||||
*
|
||||
* \param table the hash table to delete.
|
||||
*/
|
||||
void
|
||||
_eglDeleteHashTable(_EGLHashtable *table)
|
||||
{
|
||||
EGLuint i;
|
||||
assert(table);
|
||||
for (i = 0; i < TABLE_SIZE; i++) {
|
||||
_EGLHashentry *entry = table->Table[i];
|
||||
while (entry) {
|
||||
_EGLHashentry *next = entry->Next;
|
||||
free(entry);
|
||||
entry = next;
|
||||
}
|
||||
}
|
||||
_eglDestroyMutex(table->Mutex);
|
||||
free(table);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Lookup an entry in the hash table.
|
||||
*
|
||||
* \param table the hash table.
|
||||
* \param key the key.
|
||||
*
|
||||
* \return pointer to user's data or NULL if key not in table
|
||||
*/
|
||||
void *
|
||||
_eglHashLookup(const _EGLHashtable *table, EGLuint key)
|
||||
{
|
||||
EGLuint pos;
|
||||
const _EGLHashentry *entry;
|
||||
|
||||
assert(table);
|
||||
|
||||
if (!key)
|
||||
return NULL;
|
||||
|
||||
pos = HASH_FUNC(key);
|
||||
entry = table->Table[pos];
|
||||
while (entry) {
|
||||
if (entry->Key == key) {
|
||||
return entry->Data;
|
||||
}
|
||||
entry = entry->Next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Insert a key/pointer pair into the hash table.
|
||||
* If an entry with this key already exists we'll replace the existing entry.
|
||||
*
|
||||
* \param table the hash table.
|
||||
* \param key the key (not zero).
|
||||
* \param data pointer to user data.
|
||||
*/
|
||||
void
|
||||
_eglHashInsert(_EGLHashtable *table, EGLuint key, void *data)
|
||||
{
|
||||
/* search for existing entry with this key */
|
||||
EGLuint pos;
|
||||
_EGLHashentry *entry;
|
||||
|
||||
assert(table);
|
||||
assert(key);
|
||||
|
||||
_eglLockMutex(table->Mutex);
|
||||
|
||||
if (key > table->MaxKey)
|
||||
table->MaxKey = key;
|
||||
|
||||
pos = HASH_FUNC(key);
|
||||
entry = table->Table[pos];
|
||||
while (entry) {
|
||||
if (entry->Key == key) {
|
||||
/* replace entry's data */
|
||||
entry->Data = data;
|
||||
_eglUnlockMutex(table->Mutex);
|
||||
return;
|
||||
}
|
||||
entry = entry->Next;
|
||||
}
|
||||
|
||||
/* alloc and insert new table entry */
|
||||
entry = (_EGLHashentry *) malloc(sizeof(_EGLHashentry));
|
||||
entry->Key = key;
|
||||
entry->Data = data;
|
||||
entry->Next = table->Table[pos];
|
||||
table->Table[pos] = entry;
|
||||
|
||||
_eglUnlockMutex(table->Mutex);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Remove an entry from the hash table.
|
||||
*
|
||||
* \param table the hash table.
|
||||
* \param key key of entry to remove.
|
||||
*
|
||||
* While holding the hash table's lock, searches the entry with the matching
|
||||
* key and unlinks it.
|
||||
*/
|
||||
void
|
||||
_eglHashRemove(_EGLHashtable *table, EGLuint key)
|
||||
{
|
||||
EGLuint pos;
|
||||
_EGLHashentry *entry, *prev;
|
||||
|
||||
assert(table);
|
||||
assert(key);
|
||||
|
||||
_eglLockMutex(table->Mutex);
|
||||
|
||||
pos = HASH_FUNC(key);
|
||||
prev = NULL;
|
||||
entry = table->Table[pos];
|
||||
while (entry) {
|
||||
if (entry->Key == key) {
|
||||
/* found it! */
|
||||
if (prev) {
|
||||
prev->Next = entry->Next;
|
||||
}
|
||||
else {
|
||||
table->Table[pos] = entry->Next;
|
||||
}
|
||||
free(entry);
|
||||
_eglUnlockMutex(table->Mutex);
|
||||
return;
|
||||
}
|
||||
prev = entry;
|
||||
entry = entry->Next;
|
||||
}
|
||||
|
||||
_eglUnlockMutex(table->Mutex);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the key of the "first" entry in the hash table.
|
||||
*
|
||||
* This is used in the course of deleting all display lists when
|
||||
* a context is destroyed.
|
||||
*
|
||||
* \param table the hash table
|
||||
*
|
||||
* \return key for the "first" entry in the hash table.
|
||||
*
|
||||
* While holding the lock, walks through all table positions until finding
|
||||
* the first entry of the first non-empty one.
|
||||
*/
|
||||
EGLuint
|
||||
_eglHashFirstEntry(_EGLHashtable *table)
|
||||
{
|
||||
EGLuint pos;
|
||||
assert(table);
|
||||
_eglLockMutex(table->Mutex);
|
||||
for (pos = 0; pos < TABLE_SIZE; pos++) {
|
||||
if (table->Table[pos]) {
|
||||
_eglUnlockMutex(table->Mutex);
|
||||
return table->Table[pos]->Key;
|
||||
}
|
||||
}
|
||||
_eglUnlockMutex(table->Mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Given a hash table key, return the next key. This is used to walk
|
||||
* over all entries in the table. Note that the keys returned during
|
||||
* walking won't be in any particular order.
|
||||
* \return next hash key or 0 if end of table.
|
||||
*/
|
||||
EGLuint
|
||||
_eglHashNextEntry(const _EGLHashtable *table, EGLuint key)
|
||||
{
|
||||
const _EGLHashentry *entry;
|
||||
EGLuint pos;
|
||||
|
||||
assert(table);
|
||||
assert(key);
|
||||
|
||||
/* Find the entry with given key */
|
||||
pos = HASH_FUNC(key);
|
||||
entry = table->Table[pos];
|
||||
while (entry) {
|
||||
if (entry->Key == key) {
|
||||
break;
|
||||
}
|
||||
entry = entry->Next;
|
||||
}
|
||||
|
||||
if (!entry) {
|
||||
/* the key was not found, we can't find next entry */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (entry->Next) {
|
||||
/* return next in linked list */
|
||||
return entry->Next->Key;
|
||||
}
|
||||
else {
|
||||
/* look for next non-empty table slot */
|
||||
pos++;
|
||||
while (pos < TABLE_SIZE) {
|
||||
if (table->Table[pos]) {
|
||||
return table->Table[pos]->Key;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dump contents of hash table for debugging.
|
||||
*
|
||||
* \param table the hash table.
|
||||
*/
|
||||
void
|
||||
_eglHashPrint(const _EGLHashtable *table)
|
||||
{
|
||||
EGLuint i;
|
||||
assert(table);
|
||||
for (i = 0; i < TABLE_SIZE; i++) {
|
||||
const _EGLHashentry *entry = table->Table[i];
|
||||
while (entry) {
|
||||
printf("%u %p\n", entry->Key, entry->Data);
|
||||
entry = entry->Next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return a new, unused hash key.
|
||||
*/
|
||||
EGLuint
|
||||
_eglHashGenKey(_EGLHashtable *table)
|
||||
{
|
||||
EGLuint k;
|
||||
|
||||
_eglLockMutex(table->Mutex);
|
||||
k = table->MaxKey;
|
||||
table->MaxKey++;
|
||||
_eglUnlockMutex(table->Mutex);
|
||||
return k;
|
||||
}
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
/**
|
||||
* \file eglhash.h
|
||||
* Generic hash table.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef EGLHASH_INCLUDED
|
||||
#define EGLHASH_INCLUDED
|
||||
|
||||
|
||||
/* XXX move this? */
|
||||
typedef unsigned int EGLuint;
|
||||
|
||||
|
||||
typedef struct _egl_hashtable _EGLHashtable;
|
||||
|
||||
|
||||
extern _EGLHashtable *_eglNewHashTable(void);
|
||||
|
||||
extern void _eglDeleteHashTable(_EGLHashtable *table);
|
||||
|
||||
extern void *_eglHashLookup(const _EGLHashtable *table, EGLuint key);
|
||||
|
||||
extern void _eglHashInsert(_EGLHashtable *table, EGLuint key, void *data);
|
||||
|
||||
extern void _eglHashRemove(_EGLHashtable *table, EGLuint key);
|
||||
|
||||
extern EGLuint _eglHashFirstEntry(_EGLHashtable *table);
|
||||
|
||||
extern EGLuint _eglHashNextEntry(const _EGLHashtable *table, EGLuint key);
|
||||
|
||||
extern void _eglHashPrint(const _EGLHashtable *table);
|
||||
|
||||
extern EGLuint _eglHashGenKey(_EGLHashtable *table);
|
||||
|
||||
extern void _egltest_hash_functions(void);
|
||||
|
||||
|
||||
#endif /* EGLHASH_INCLUDED */
|
||||
@@ -1,94 +0,0 @@
|
||||
/**
|
||||
* Logging facility for debug/info messages.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "egllog.h"
|
||||
|
||||
#define MAXSTRING 1000
|
||||
#define FALLBACK_LOG_LEVEL _EGL_DEBUG
|
||||
#define FALLBACK_LOG_LEVEL_STR "debug"
|
||||
|
||||
static EGLint ReportingLevel = -1;
|
||||
|
||||
|
||||
static void
|
||||
log_level_initialize (void)
|
||||
{
|
||||
char *log_env = getenv ("EGL_LOG_LEVEL");
|
||||
|
||||
if (log_env == NULL) {
|
||||
ReportingLevel = FALLBACK_LOG_LEVEL;
|
||||
}
|
||||
else if (strcasecmp (log_env, "fatal") == 0) {
|
||||
ReportingLevel = _EGL_FATAL;
|
||||
}
|
||||
else if (strcasecmp (log_env, "warning") == 0) {
|
||||
ReportingLevel = _EGL_WARNING;
|
||||
}
|
||||
else if (strcasecmp (log_env, "info") == 0) {
|
||||
ReportingLevel = _EGL_INFO;
|
||||
}
|
||||
else if (strcasecmp (log_env, "debug") == 0) {
|
||||
ReportingLevel = _EGL_DEBUG;
|
||||
}
|
||||
else {
|
||||
fprintf (stderr, "Unrecognized EGL_LOG_LEVEL environment variable value. "
|
||||
"Expected one of \"fatal\", \"warning\", \"info\", \"debug\". "
|
||||
"Got \"%s\". Falling back to \"%s\".\n",
|
||||
log_env, FALLBACK_LOG_LEVEL_STR);
|
||||
ReportingLevel = FALLBACK_LOG_LEVEL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Log a message to stderr.
|
||||
* \param level one of _EGL_FATAL, _EGL_WARNING, _EGL_INFO, _EGL_DEBUG.
|
||||
*/
|
||||
void
|
||||
_eglLog(EGLint level, const char *fmtStr, ...)
|
||||
{
|
||||
va_list args;
|
||||
char msg[MAXSTRING];
|
||||
const char *levelStr;
|
||||
static int log_level_initialized = 0;
|
||||
|
||||
if (!log_level_initialized) {
|
||||
log_level_initialize ();
|
||||
log_level_initialized = 1;
|
||||
}
|
||||
|
||||
if (level <= ReportingLevel) {
|
||||
switch (level) {
|
||||
case _EGL_FATAL:
|
||||
levelStr = "Fatal";
|
||||
break;
|
||||
case _EGL_WARNING:
|
||||
levelStr = "Warning";
|
||||
break;
|
||||
case _EGL_INFO:
|
||||
levelStr = "Info";
|
||||
break;
|
||||
case _EGL_DEBUG:
|
||||
levelStr = "Debug";
|
||||
break;
|
||||
default:
|
||||
levelStr = "";
|
||||
}
|
||||
|
||||
va_start(args, fmtStr);
|
||||
vsnprintf(msg, MAXSTRING, fmtStr, args);
|
||||
va_end(args);
|
||||
|
||||
fprintf(stderr, "EGL %s: %s\n", levelStr, msg);
|
||||
|
||||
if (level == _EGL_FATAL) {
|
||||
exit(1); /* or abort()? */
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
#ifndef EGLLOG_INCLUDED
|
||||
#define EGLLOG_INCLUDED
|
||||
|
||||
#include "egltypedefs.h"
|
||||
|
||||
#define _EGL_FATAL 0 /* unrecoverable error */
|
||||
#define _EGL_WARNING 1 /* recoverable error/problem */
|
||||
#define _EGL_INFO 2 /* just useful info */
|
||||
#define _EGL_DEBUG 3 /* useful info for debugging */
|
||||
|
||||
|
||||
extern void
|
||||
_eglLog(EGLint level, const char *fmtStr, ...);
|
||||
|
||||
|
||||
#endif /* EGLLOG_INCLUDED */
|
||||
@@ -1,431 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "egldisplay.h"
|
||||
#include "egldriver.h"
|
||||
#include "eglmode.h"
|
||||
#include "eglglobals.h"
|
||||
#include "eglscreen.h"
|
||||
|
||||
|
||||
#define MIN2(A, B) (((A) < (B)) ? (A) : (B))
|
||||
|
||||
|
||||
static char *
|
||||
my_strdup(const char *s)
|
||||
{
|
||||
if (s) {
|
||||
int l = strlen(s);
|
||||
char *s2 = malloc(l + 1);
|
||||
if (s2)
|
||||
strcpy(s2, s);
|
||||
return s2;
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Given an EGLModeMESA handle, return the corresponding _EGLMode object
|
||||
* or null if non-existant.
|
||||
*/
|
||||
_EGLMode *
|
||||
_eglLookupMode(EGLDisplay dpy, EGLModeMESA mode)
|
||||
{
|
||||
const _EGLDisplay *disp = _eglLookupDisplay(dpy);
|
||||
EGLint scrnum;
|
||||
|
||||
/* loop over all screens on the display */
|
||||
for (scrnum = 0; scrnum < disp->NumScreens; scrnum++) {
|
||||
const _EGLScreen *scrn = disp->Screens[scrnum];
|
||||
EGLint i;
|
||||
/* search list of modes for handle */
|
||||
for (i = 0; i < scrn->NumModes; i++) {
|
||||
if (scrn->Modes[i].Handle == mode) {
|
||||
return scrn->Modes + i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a new mode with the given attributes (width, height, depth, refreshRate)
|
||||
* to the given screen.
|
||||
* Assign a new mode ID/handle to the mode as well.
|
||||
* \return pointer to the new _EGLMode
|
||||
*/
|
||||
_EGLMode *
|
||||
_eglAddNewMode(_EGLScreen *screen, EGLint width, EGLint height,
|
||||
EGLint refreshRate, const char *name)
|
||||
{
|
||||
EGLint n;
|
||||
_EGLMode *newModes;
|
||||
|
||||
assert(screen);
|
||||
assert(width > 0);
|
||||
assert(height > 0);
|
||||
assert(refreshRate > 0);
|
||||
|
||||
n = screen->NumModes;
|
||||
newModes = (_EGLMode *) realloc(screen->Modes, (n+1) * sizeof(_EGLMode));
|
||||
if (newModes) {
|
||||
screen->Modes = newModes;
|
||||
screen->Modes[n].Handle = n + 1;
|
||||
screen->Modes[n].Width = width;
|
||||
screen->Modes[n].Height = height;
|
||||
screen->Modes[n].RefreshRate = refreshRate;
|
||||
screen->Modes[n].Optimal = EGL_FALSE;
|
||||
screen->Modes[n].Interlaced = EGL_FALSE;
|
||||
screen->Modes[n].Name = my_strdup(name);
|
||||
screen->NumModes++;
|
||||
return screen->Modes + n;
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Parse the attrib_list to fill in the fields of the given _eglMode
|
||||
* Return EGL_FALSE if any errors, EGL_TRUE otherwise.
|
||||
*/
|
||||
static EGLBoolean
|
||||
_eglParseModeAttribs(_EGLMode *mode, const EGLint *attrib_list)
|
||||
{
|
||||
EGLint i;
|
||||
|
||||
/* init all attribs to EGL_DONT_CARE */
|
||||
mode->Handle = EGL_DONT_CARE;
|
||||
mode->Width = EGL_DONT_CARE;
|
||||
mode->Height = EGL_DONT_CARE;
|
||||
mode->RefreshRate = EGL_DONT_CARE;
|
||||
mode->Optimal = EGL_DONT_CARE;
|
||||
mode->Interlaced = EGL_DONT_CARE;
|
||||
mode->Name = NULL;
|
||||
|
||||
for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
|
||||
switch (attrib_list[i]) {
|
||||
case EGL_MODE_ID_MESA:
|
||||
mode->Handle = attrib_list[++i];
|
||||
if (mode->Handle <= 0) {
|
||||
_eglError(EGL_BAD_PARAMETER, "eglChooseModeMESA(handle)");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
break;
|
||||
case EGL_WIDTH:
|
||||
mode->Width = attrib_list[++i];
|
||||
if (mode->Width <= 0) {
|
||||
_eglError(EGL_BAD_PARAMETER, "eglChooseModeMESA(width)");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
break;
|
||||
case EGL_HEIGHT:
|
||||
mode->Height = attrib_list[++i];
|
||||
if (mode->Height <= 0) {
|
||||
_eglError(EGL_BAD_PARAMETER, "eglChooseModeMESA(height)");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
break;
|
||||
case EGL_REFRESH_RATE_MESA:
|
||||
mode->RefreshRate = attrib_list[++i];
|
||||
if (mode->RefreshRate <= 0) {
|
||||
_eglError(EGL_BAD_PARAMETER, "eglChooseModeMESA(refresh rate)");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
break;
|
||||
case EGL_INTERLACED_MESA:
|
||||
mode->Interlaced = attrib_list[++i];
|
||||
if (mode->Interlaced != EGL_TRUE && mode->Interlaced != EGL_FALSE) {
|
||||
_eglError(EGL_BAD_PARAMETER, "eglChooseModeMESA(interlaced)");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
break;
|
||||
case EGL_OPTIMAL_MESA:
|
||||
mode->Optimal = attrib_list[++i];
|
||||
if (mode->Optimal != EGL_TRUE && mode->Optimal != EGL_FALSE) {
|
||||
_eglError(EGL_BAD_PARAMETER, "eglChooseModeMESA(optimal)");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
_eglError(EGL_BAD_ATTRIBUTE, "eglChooseModeMESA");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
}
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine if the candidate mode's attributes are at least as good
|
||||
* as the minimal mode's.
|
||||
* \return EGL_TRUE if qualifies, EGL_FALSE otherwise
|
||||
*/
|
||||
static EGLBoolean
|
||||
_eglModeQualifies(const _EGLMode *c, const _EGLMode *min)
|
||||
{
|
||||
if (min->Handle != EGL_DONT_CARE && c->Handle != min->Handle)
|
||||
return EGL_FALSE;
|
||||
if (min->Width != EGL_DONT_CARE && c->Width < min->Width)
|
||||
return EGL_FALSE;
|
||||
if (min->Height != EGL_DONT_CARE && c->Height < min->Height)
|
||||
return EGL_FALSE;
|
||||
if (min->RefreshRate != EGL_DONT_CARE && c->RefreshRate < min->RefreshRate)
|
||||
return EGL_FALSE;
|
||||
if (min->Optimal != EGL_DONT_CARE && c->Optimal != min->Optimal)
|
||||
return EGL_FALSE;
|
||||
if (min->Interlaced != EGL_DONT_CARE && c->Interlaced != min->Interlaced)
|
||||
return EGL_FALSE;
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return value of given mode attribute, or -1 if bad attrib.
|
||||
*/
|
||||
static EGLint
|
||||
getModeAttrib(const _EGLMode *m, EGLint attrib)
|
||||
{
|
||||
switch (attrib) {
|
||||
case EGL_MODE_ID_MESA:
|
||||
return m->Handle;
|
||||
case EGL_WIDTH:
|
||||
return m->Width;
|
||||
case EGL_HEIGHT:
|
||||
return m->Height;
|
||||
case EGL_REFRESH_RATE_MESA:
|
||||
return m->RefreshRate;
|
||||
case EGL_OPTIMAL_MESA:
|
||||
return m->Optimal;
|
||||
case EGL_INTERLACED_MESA:
|
||||
return m->Interlaced;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define SMALLER 1
|
||||
#define LARGER 2
|
||||
|
||||
struct sort_info {
|
||||
EGLint Attrib;
|
||||
EGLint Order; /* SMALLER or LARGER */
|
||||
};
|
||||
|
||||
/* the order of these entries is the priority */
|
||||
static struct sort_info SortInfo[] = {
|
||||
{ EGL_OPTIMAL_MESA, LARGER },
|
||||
{ EGL_INTERLACED_MESA, SMALLER },
|
||||
{ EGL_WIDTH, LARGER },
|
||||
{ EGL_HEIGHT, LARGER },
|
||||
{ EGL_REFRESH_RATE_MESA, LARGER },
|
||||
{ EGL_MODE_ID_MESA, SMALLER },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Compare modes 'a' and 'b' and return -1 if a belongs before b, or 1 if a
|
||||
* belongs after b, or 0 if they're equal.
|
||||
* Used by qsort().
|
||||
*/
|
||||
static int
|
||||
_eglCompareModes(const void *a, const void *b)
|
||||
{
|
||||
const _EGLMode *aMode = *((const _EGLMode **) a);
|
||||
const _EGLMode *bMode = *((const _EGLMode **) b);
|
||||
EGLint i;
|
||||
|
||||
for (i = 0; SortInfo[i].Attrib; i++) {
|
||||
const EGLint aVal = getModeAttrib(aMode, SortInfo[i].Attrib);
|
||||
const EGLint bVal = getModeAttrib(bMode, SortInfo[i].Attrib);
|
||||
if (aVal == bVal) {
|
||||
/* a tie */
|
||||
continue;
|
||||
}
|
||||
else if (SortInfo[i].Order == SMALLER) {
|
||||
return (aVal < bVal) ? -1 : 1;
|
||||
}
|
||||
else if (SortInfo[i].Order == LARGER) {
|
||||
return (aVal > bVal) ? -1 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* all attributes identical */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Search for EGLModes which match the given attribute list.
|
||||
* Called via eglChooseModeMESA API function.
|
||||
*/
|
||||
EGLBoolean
|
||||
_eglChooseModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen,
|
||||
const EGLint *attrib_list, EGLModeMESA *modes,
|
||||
EGLint modes_size, EGLint *num_modes)
|
||||
{
|
||||
const _EGLScreen *scrn = _eglLookupScreen(dpy, screen);
|
||||
_EGLMode **modeList, min;
|
||||
EGLint i, count;
|
||||
|
||||
if (!scrn) {
|
||||
_eglError(EGL_BAD_SCREEN_MESA, "eglChooseModeMESA");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
if (!_eglParseModeAttribs(&min, attrib_list)) {
|
||||
/* error code will have been recorded */
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
/* allocate array of mode pointers */
|
||||
modeList = (_EGLMode **) malloc(modes_size * sizeof(_EGLMode *));
|
||||
if (!modeList) {
|
||||
_eglError(EGL_BAD_MODE_MESA, "eglChooseModeMESA(out of memory)");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
/* make array of pointers to qualifying modes */
|
||||
for (i = count = 0; i < scrn->NumModes && count < modes_size; i++) {
|
||||
if (_eglModeQualifies(scrn->Modes + i, &min)) {
|
||||
modeList[count++] = scrn->Modes + i;
|
||||
}
|
||||
}
|
||||
|
||||
/* sort array of pointers */
|
||||
qsort(modeList, count, sizeof(_EGLMode *), _eglCompareModes);
|
||||
|
||||
/* copy mode handles to output array */
|
||||
for (i = 0; i < count; i++) {
|
||||
modes[i] = modeList[i]->Handle;
|
||||
}
|
||||
|
||||
free(modeList);
|
||||
|
||||
*num_modes = count;
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return all possible modes for the given screen. No sorting of results.
|
||||
* Called via eglGetModesMESA() API function.
|
||||
*/
|
||||
EGLBoolean
|
||||
_eglGetModesMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen,
|
||||
EGLModeMESA *modes, EGLint modes_size, EGLint *num_modes)
|
||||
{
|
||||
_EGLScreen *scrn = _eglLookupScreen(dpy, screen);
|
||||
|
||||
if (!scrn) {
|
||||
_eglError(EGL_BAD_SCREEN_MESA, "eglGetModesMESA");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
if (modes) {
|
||||
EGLint i;
|
||||
*num_modes = MIN2(scrn->NumModes, modes_size);
|
||||
for (i = 0; i < *num_modes; i++) {
|
||||
modes[i] = scrn->Modes[i].Handle;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* just return total number of supported modes */
|
||||
*num_modes = scrn->NumModes;
|
||||
}
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Query an attribute of a mode.
|
||||
*/
|
||||
EGLBoolean
|
||||
_eglGetModeAttribMESA(_EGLDriver *drv, EGLDisplay dpy,
|
||||
EGLModeMESA mode, EGLint attribute, EGLint *value)
|
||||
{
|
||||
_EGLMode *m = _eglLookupMode(dpy, mode);
|
||||
EGLint v;
|
||||
|
||||
if (!m) {
|
||||
_eglError(EGL_BAD_MODE_MESA, "eglGetModeAttribMESA");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
v = getModeAttrib(m, attribute);
|
||||
if (v < 0) {
|
||||
_eglError(EGL_BAD_ATTRIBUTE, "eglGetModeAttribMESA");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
*value = v;
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return human-readable string for given mode.
|
||||
* This is the default function called by eglQueryModeStringMESA().
|
||||
*/
|
||||
const char *
|
||||
_eglQueryModeStringMESA(_EGLDriver *drv, EGLDisplay dpy, EGLModeMESA mode)
|
||||
{
|
||||
_EGLMode *m = _eglLookupMode(dpy, mode);
|
||||
if (!m) {
|
||||
_eglError(EGL_BAD_MODE_MESA, "eglQueryModeStringMESA");
|
||||
return NULL;
|
||||
}
|
||||
return m->Name;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
static int
|
||||
_eglRand(int max)
|
||||
{
|
||||
return rand() % max;
|
||||
}
|
||||
|
||||
void
|
||||
_eglTestModeModule(void)
|
||||
{
|
||||
EGLint count = 30;
|
||||
_EGLMode *modes = (_EGLMode *) malloc(count * sizeof(_EGLMode));
|
||||
_EGLMode **modeList = (_EGLMode **) malloc(count * sizeof(_EGLMode*));
|
||||
EGLint i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
modes[i].Handle = _eglRand(20);
|
||||
modes[i].Width = 512 + 256 * _eglRand(2);
|
||||
modes[i].Height = 512 + 256 * _eglRand(2);
|
||||
modes[i].RefreshRate = 50 + 5 * _eglRand(3);
|
||||
modes[i].Interlaced = _eglRand(2);
|
||||
modes[i].Optimal = _eglRand(4) == 0;
|
||||
modeList[i] = modes + i;
|
||||
}
|
||||
|
||||
/* sort array of pointers */
|
||||
qsort(modeList, count, sizeof(_EGLMode *), compareModes);
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
_EGLMode *m = modeList[i];
|
||||
printf("%2d: %3d %4d x %4d @ %3d opt %d int %d\n", i,
|
||||
m->Handle, m->Width, m->Height, m->RefreshRate,
|
||||
m->Optimal, m->Interlaced);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,54 +0,0 @@
|
||||
#ifndef EGLMODE_INCLUDED
|
||||
#define EGLMODE_INCLUDED
|
||||
|
||||
#include "egltypedefs.h"
|
||||
|
||||
|
||||
/**
|
||||
* Data structure which corresponds to an EGLModeMESA.
|
||||
*/
|
||||
struct _egl_mode
|
||||
{
|
||||
EGLModeMESA Handle; /* the public/opaque handle which names this mode */
|
||||
EGLint Width, Height; /* size in pixels */
|
||||
EGLint RefreshRate; /* rate * 1000.0 */
|
||||
EGLint Optimal;
|
||||
EGLint Interlaced;
|
||||
const char *Name;
|
||||
|
||||
/* Other possible attributes */
|
||||
/* interlaced */
|
||||
/* external sync */
|
||||
};
|
||||
|
||||
|
||||
extern _EGLMode *
|
||||
_eglLookupMode(EGLDisplay dpy, EGLModeMESA mode);
|
||||
|
||||
|
||||
extern _EGLMode *
|
||||
_eglAddNewMode(_EGLScreen *screen, EGLint width, EGLint height,
|
||||
EGLint refreshRate, const char *name);
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
_eglChooseModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen,
|
||||
const EGLint *attrib_list, EGLModeMESA *modes,
|
||||
EGLint modes_size, EGLint *num_modes);
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
_eglGetModesMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen,
|
||||
EGLModeMESA *modes, EGLint modes_size, EGLint *num_modes);
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
_eglGetModeAttribMESA(_EGLDriver *drv, EGLDisplay dpy, EGLModeMESA mode,
|
||||
EGLint attribute, EGLint *value);
|
||||
|
||||
|
||||
extern const char *
|
||||
_eglQueryModeStringMESA(_EGLDriver *drv, EGLDisplay dpy, EGLModeMESA mode);
|
||||
|
||||
|
||||
#endif /* EGLMODE_INCLUDED */
|
||||
@@ -1,328 +0,0 @@
|
||||
/*
|
||||
* Ideas for screen management extension to EGL.
|
||||
*
|
||||
* Each EGLDisplay has one or more screens (CRTs, Flat Panels, etc).
|
||||
* The screens' handles can be obtained with eglGetScreensMESA().
|
||||
*
|
||||
* A new kind of EGLSurface is possible- one which can be directly scanned
|
||||
* out on a screen. Such a surface is created with eglCreateScreenSurface().
|
||||
*
|
||||
* To actually display a screen surface on a screen, the eglShowSurface()
|
||||
* function is called.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "egldisplay.h"
|
||||
#include "eglglobals.h"
|
||||
#include "eglmode.h"
|
||||
#include "eglconfig.h"
|
||||
#include "eglsurface.h"
|
||||
#include "eglscreen.h"
|
||||
|
||||
|
||||
/**
|
||||
* Return a new screen handle/ID.
|
||||
* NOTE: we never reuse these!
|
||||
*/
|
||||
EGLScreenMESA
|
||||
_eglAllocScreenHandle(void)
|
||||
{
|
||||
EGLScreenMESA s = _eglGlobal.FreeScreenHandle;
|
||||
_eglGlobal.FreeScreenHandle++;
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize an _EGLScreen object to default values.
|
||||
*/
|
||||
void
|
||||
_eglInitScreen(_EGLScreen *screen)
|
||||
{
|
||||
memset(screen, 0, sizeof(_EGLScreen));
|
||||
screen->StepX = 1;
|
||||
screen->StepY = 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Given a public screen handle, return the internal _EGLScreen object.
|
||||
*/
|
||||
_EGLScreen *
|
||||
_eglLookupScreen(EGLDisplay dpy, EGLScreenMESA screen)
|
||||
{
|
||||
EGLint i;
|
||||
_EGLDisplay *display = _eglLookupDisplay(dpy);
|
||||
|
||||
if (!display)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < display->NumScreens; i++) {
|
||||
if (display->Screens[i]->Handle == screen)
|
||||
return display->Screens[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add the given _EGLScreen to the display's list of screens.
|
||||
*/
|
||||
void
|
||||
_eglAddScreen(_EGLDisplay *display, _EGLScreen *screen)
|
||||
{
|
||||
EGLint n;
|
||||
|
||||
assert(display);
|
||||
assert(screen);
|
||||
|
||||
screen->Handle = _eglAllocScreenHandle();
|
||||
n = display->NumScreens;
|
||||
display->Screens = realloc(display->Screens, (n+1) * sizeof(_EGLScreen *));
|
||||
display->Screens[n] = screen;
|
||||
display->NumScreens++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
EGLBoolean
|
||||
_eglGetScreensMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA *screens,
|
||||
EGLint max_screens, EGLint *num_screens)
|
||||
{
|
||||
_EGLDisplay *display = _eglLookupDisplay(dpy);
|
||||
EGLint n;
|
||||
|
||||
if (!display) {
|
||||
_eglError(EGL_BAD_DISPLAY, "eglGetScreensMESA");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
if (display->NumScreens > max_screens) {
|
||||
n = max_screens;
|
||||
}
|
||||
else {
|
||||
n = display->NumScreens;
|
||||
}
|
||||
|
||||
if (screens) {
|
||||
EGLint i;
|
||||
for (i = 0; i < n; i++)
|
||||
screens[i] = display->Screens[i]->Handle;
|
||||
}
|
||||
if (num_screens)
|
||||
*num_screens = n;
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Example function - drivers should do a proper implementation.
|
||||
*/
|
||||
EGLSurface
|
||||
_eglCreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
|
||||
const EGLint *attrib_list)
|
||||
{
|
||||
#if 0 /* THIS IS JUST EXAMPLE CODE */
|
||||
_EGLSurface *surf;
|
||||
|
||||
surf = (_EGLSurface *) calloc(1, sizeof(_EGLSurface));
|
||||
if (!surf)
|
||||
return EGL_NO_SURFACE;
|
||||
|
||||
if (!_eglInitSurface(drv, dpy, surf, EGL_SCREEN_BIT_MESA,
|
||||
config, attrib_list)) {
|
||||
free(surf);
|
||||
return EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
_eglSaveSurface(surf);
|
||||
|
||||
return surf->Handle;
|
||||
#endif
|
||||
return EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Show the given surface on the named screen.
|
||||
* If surface is EGL_NO_SURFACE, disable the screen's output.
|
||||
*
|
||||
* This is just a placeholder function; drivers will always override
|
||||
* this with code that _really_ shows the surface.
|
||||
*/
|
||||
EGLBoolean
|
||||
_eglShowScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy,
|
||||
EGLScreenMESA screen, EGLSurface surface,
|
||||
EGLModeMESA m)
|
||||
{
|
||||
_EGLScreen *scrn = _eglLookupScreen(dpy, screen);
|
||||
_EGLMode *mode = _eglLookupMode(dpy, m);
|
||||
|
||||
if (!scrn) {
|
||||
_eglError(EGL_BAD_SCREEN_MESA, "eglShowSurfaceMESA");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
if (!mode && (m != EGL_NO_MODE_MESA )) {
|
||||
_eglError(EGL_BAD_MODE_MESA, "eglShowSurfaceMESA");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
if (surface == EGL_NO_SURFACE) {
|
||||
scrn->CurrentSurface = NULL;
|
||||
}
|
||||
else {
|
||||
_EGLSurface *surf = _eglLookupSurface(surface);
|
||||
if (!surf || surf->Type != EGL_SCREEN_BIT_MESA) {
|
||||
_eglError(EGL_BAD_SURFACE, "eglShowSurfaceMESA");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
if (surf->Width < mode->Width || surf->Height < mode->Height) {
|
||||
_eglError(EGL_BAD_SURFACE,
|
||||
"eglShowSurfaceMESA(surface smaller than screen size)");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
scrn->CurrentSurface = surf;
|
||||
scrn->CurrentMode = mode;
|
||||
}
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set a screen's current display mode.
|
||||
* Note: mode = EGL_NO_MODE is valid (turns off the screen)
|
||||
*
|
||||
* This is just a placeholder function; drivers will always override
|
||||
* this with code that _really_ sets the mode.
|
||||
*/
|
||||
EGLBoolean
|
||||
_eglScreenModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen,
|
||||
EGLModeMESA mode)
|
||||
{
|
||||
_EGLScreen *scrn = _eglLookupScreen(dpy, screen);
|
||||
|
||||
if (!scrn) {
|
||||
_eglError(EGL_BAD_SCREEN_MESA, "eglScreenModeMESA");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
scrn->CurrentMode = _eglLookupMode(dpy, mode);
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set a screen's surface origin.
|
||||
*/
|
||||
EGLBoolean
|
||||
_eglScreenPositionMESA(_EGLDriver *drv, EGLDisplay dpy,
|
||||
EGLScreenMESA screen, EGLint x, EGLint y)
|
||||
{
|
||||
_EGLScreen *scrn = _eglLookupScreen(dpy, screen);
|
||||
if (!scrn) {
|
||||
_eglError(EGL_BAD_SCREEN_MESA, "eglScreenPositionMESA");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
scrn->OriginX = x;
|
||||
scrn->OriginY = y;
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Query a screen's current surface.
|
||||
*/
|
||||
EGLBoolean
|
||||
_eglQueryScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy,
|
||||
EGLScreenMESA screen, EGLSurface *surface)
|
||||
{
|
||||
const _EGLScreen *scrn = _eglLookupScreen(dpy, screen);
|
||||
if (scrn->CurrentSurface)
|
||||
*surface = scrn->CurrentSurface->Handle;
|
||||
else
|
||||
*surface = EGL_NO_SURFACE;
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Query a screen's current mode.
|
||||
*/
|
||||
EGLBoolean
|
||||
_eglQueryScreenModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen,
|
||||
EGLModeMESA *mode)
|
||||
{
|
||||
const _EGLScreen *scrn = _eglLookupScreen(dpy, screen);
|
||||
if (scrn->CurrentMode)
|
||||
*mode = scrn->CurrentMode->Handle;
|
||||
else
|
||||
*mode = EGL_NO_MODE_MESA;
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean
|
||||
_eglQueryScreenMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen,
|
||||
EGLint attribute, EGLint *value)
|
||||
{
|
||||
const _EGLScreen *scrn = _eglLookupScreen(dpy, screen);
|
||||
|
||||
if (!scrn) {
|
||||
_eglError(EGL_BAD_SCREEN_MESA, "eglQueryScreenMESA");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
switch (attribute) {
|
||||
case EGL_SCREEN_POSITION_MESA:
|
||||
value[0] = scrn->OriginX;
|
||||
value[1] = scrn->OriginY;
|
||||
break;
|
||||
case EGL_SCREEN_POSITION_GRANULARITY_MESA:
|
||||
value[0] = scrn->StepX;
|
||||
value[1] = scrn->StepY;
|
||||
break;
|
||||
default:
|
||||
_eglError(EGL_BAD_ATTRIBUTE, "eglQueryScreenMESA");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delete the modes associated with given screen.
|
||||
*/
|
||||
void
|
||||
_eglDestroyScreenModes(_EGLScreen *scrn)
|
||||
{
|
||||
EGLint i;
|
||||
for (i = 0; i < scrn->NumModes; i++) {
|
||||
if (scrn->Modes[i].Name)
|
||||
free((char *) scrn->Modes[i].Name); /* cast away const */
|
||||
}
|
||||
if (scrn->Modes)
|
||||
free(scrn->Modes);
|
||||
scrn->Modes = NULL;
|
||||
scrn->NumModes = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Default fallback routine - drivers should usually override this.
|
||||
*/
|
||||
void
|
||||
_eglDestroyScreen(_EGLScreen *scrn)
|
||||
{
|
||||
_eglDestroyScreenModes(scrn);
|
||||
free(scrn);
|
||||
}
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
#ifndef EGLSCREEN_INCLUDED
|
||||
#define EGLSCREEN_INCLUDED
|
||||
|
||||
|
||||
/**
|
||||
* Per-screen information.
|
||||
* Note that an EGL screen doesn't have a size. A screen may be set to
|
||||
* one of several display modes (width/height/scanrate). The screen
|
||||
* then displays a drawing surface. The drawing surface must be at least
|
||||
* as large as the display mode's resolution. If it's larger, the
|
||||
* OriginX and OriginY fields control what part of the surface is visible
|
||||
* on the screen.
|
||||
*/
|
||||
struct _egl_screen
|
||||
{
|
||||
EGLScreenMESA Handle; /* The public/opaque handle which names this object */
|
||||
|
||||
_EGLMode *CurrentMode;
|
||||
_EGLSurface *CurrentSurface;
|
||||
|
||||
EGLint OriginX, OriginY; /**< Origin of scan-out region w.r.t. surface */
|
||||
EGLint StepX, StepY; /**< Screen position/origin granularity */
|
||||
|
||||
EGLint NumModes;
|
||||
_EGLMode *Modes; /**< array [NumModes] */
|
||||
};
|
||||
|
||||
|
||||
extern EGLScreenMESA
|
||||
_eglAllocScreenHandle(void);
|
||||
|
||||
|
||||
extern void
|
||||
_eglInitScreen(_EGLScreen *screen);
|
||||
|
||||
|
||||
extern _EGLScreen *
|
||||
_eglLookupScreen(EGLDisplay dpy, EGLScreenMESA screen);
|
||||
|
||||
|
||||
extern void
|
||||
_eglAddScreen(_EGLDisplay *display, _EGLScreen *screen);
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
_eglGetScreensMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA *screens, EGLint max_screens, EGLint *num_screens);
|
||||
|
||||
|
||||
extern EGLSurface
|
||||
_eglCreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
_eglShowScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLSurface surface, EGLModeMESA mode);
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
_eglScreenModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA mode);
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
_eglScreenPositionMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLint x, EGLint y);
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
_eglQueryDisplayMESA(_EGLDriver *drv, EGLDisplay dpy, EGLint attribute, EGLint *value);
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
_eglQueryScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy,
|
||||
EGLScreenMESA screen, EGLSurface *surface);
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
_eglQueryScreenModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *mode);
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
_eglQueryScreenMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLint attribute, EGLint *value);
|
||||
|
||||
|
||||
extern void
|
||||
_eglDestroyScreenModes(_EGLScreen *scrn);
|
||||
|
||||
|
||||
extern void
|
||||
_eglDestroyScreen(_EGLScreen *scrn);
|
||||
|
||||
|
||||
#endif /* EGLSCREEN_INCLUDED */
|
||||
@@ -1,530 +0,0 @@
|
||||
/**
|
||||
* Surface-related functions.
|
||||
*/
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "eglcontext.h"
|
||||
#include "eglconfig.h"
|
||||
#include "eglglobals.h"
|
||||
#include "eglhash.h"
|
||||
#include "egllog.h"
|
||||
#include "eglsurface.h"
|
||||
|
||||
|
||||
/**
|
||||
* Do error check on parameters and initialize the given _EGLSurface object.
|
||||
* \return EGL_TRUE if no errors, EGL_FALSE otherwise.
|
||||
*/
|
||||
EGLBoolean
|
||||
_eglInitSurface(_EGLDriver *drv, EGLDisplay dpy,
|
||||
_EGLSurface *surf, EGLint type, EGLConfig config,
|
||||
const EGLint *attrib_list)
|
||||
{
|
||||
const char *func;
|
||||
_EGLConfig *conf;
|
||||
EGLint width = 0, height = 0, largest = 0;
|
||||
EGLint texFormat = 0, texTarget = 0, mipmapTex = 0;
|
||||
EGLint renderBuffer = EGL_BACK_BUFFER;
|
||||
#ifdef EGL_VERSION_1_2
|
||||
EGLint colorspace = EGL_COLORSPACE_sRGB;
|
||||
EGLint alphaFormat = EGL_ALPHA_FORMAT_NONPRE;
|
||||
#endif
|
||||
EGLint i;
|
||||
|
||||
switch (type) {
|
||||
case EGL_WINDOW_BIT:
|
||||
func = "eglCreateWindowSurface";
|
||||
break;
|
||||
case EGL_PIXMAP_BIT:
|
||||
func = "eglCreatePixmapSurface";
|
||||
renderBuffer = EGL_SINGLE_BUFFER;
|
||||
break;
|
||||
case EGL_PBUFFER_BIT:
|
||||
func = "eglCreatePBufferSurface";
|
||||
break;
|
||||
case EGL_SCREEN_BIT_MESA:
|
||||
func = "eglCreateScreenSurface";
|
||||
renderBuffer = EGL_SINGLE_BUFFER; /* XXX correct? */
|
||||
break;
|
||||
default:
|
||||
_eglLog(_EGL_WARNING, "Bad type in _eglInitSurface");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
conf = _eglLookupConfig(drv, dpy, config);
|
||||
if (!conf) {
|
||||
_eglError(EGL_BAD_CONFIG, func);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse attribute list. Different kinds of surfaces support different
|
||||
* attributes.
|
||||
*/
|
||||
for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
|
||||
switch (attrib_list[i]) {
|
||||
case EGL_WIDTH:
|
||||
if (type == EGL_PBUFFER_BIT || type == EGL_SCREEN_BIT_MESA) {
|
||||
width = attrib_list[++i];
|
||||
}
|
||||
else {
|
||||
_eglError(EGL_BAD_ATTRIBUTE, func);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
break;
|
||||
case EGL_HEIGHT:
|
||||
if (type == EGL_PBUFFER_BIT || type == EGL_SCREEN_BIT_MESA) {
|
||||
height = attrib_list[++i];
|
||||
}
|
||||
else {
|
||||
_eglError(EGL_BAD_ATTRIBUTE, func);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
break;
|
||||
case EGL_LARGEST_PBUFFER:
|
||||
if (type == EGL_PBUFFER_BIT) {
|
||||
largest = attrib_list[++i];
|
||||
}
|
||||
else {
|
||||
_eglError(EGL_BAD_ATTRIBUTE, func);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
break;
|
||||
case EGL_TEXTURE_FORMAT:
|
||||
if (type == EGL_PBUFFER_BIT) {
|
||||
texFormat = attrib_list[++i];
|
||||
}
|
||||
else {
|
||||
_eglError(EGL_BAD_ATTRIBUTE, func);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
break;
|
||||
case EGL_TEXTURE_TARGET:
|
||||
if (type == EGL_PBUFFER_BIT) {
|
||||
texTarget = attrib_list[++i];
|
||||
}
|
||||
else {
|
||||
_eglError(EGL_BAD_ATTRIBUTE, func);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
break;
|
||||
case EGL_MIPMAP_TEXTURE:
|
||||
if (type == EGL_PBUFFER_BIT) {
|
||||
mipmapTex = attrib_list[++i];
|
||||
}
|
||||
else {
|
||||
_eglError(EGL_BAD_ATTRIBUTE, func);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
break;
|
||||
#ifdef EGL_VERSION_1_2
|
||||
case EGL_RENDER_BUFFER:
|
||||
if (type == EGL_WINDOW_BIT) {
|
||||
renderBuffer = attrib_list[++i];
|
||||
if (renderBuffer != EGL_BACK_BUFFER &&
|
||||
renderBuffer != EGL_SINGLE_BUFFER) {
|
||||
_eglError(EGL_BAD_ATTRIBUTE, func);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
_eglError(EGL_BAD_ATTRIBUTE, func);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
break;
|
||||
case EGL_COLORSPACE:
|
||||
if (type == EGL_WINDOW_BIT ||
|
||||
type == EGL_PBUFFER_BIT ||
|
||||
type == EGL_PIXMAP_BIT) {
|
||||
colorspace = attrib_list[++i];
|
||||
if (colorspace != EGL_COLORSPACE_sRGB &&
|
||||
colorspace != EGL_COLORSPACE_LINEAR) {
|
||||
_eglError(EGL_BAD_ATTRIBUTE, func);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
_eglError(EGL_BAD_ATTRIBUTE, func);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
break;
|
||||
case EGL_ALPHA_FORMAT:
|
||||
if (type == EGL_WINDOW_BIT ||
|
||||
type == EGL_PBUFFER_BIT ||
|
||||
type == EGL_PIXMAP_BIT) {
|
||||
alphaFormat = attrib_list[++i];
|
||||
if (alphaFormat != EGL_ALPHA_FORMAT_NONPRE &&
|
||||
alphaFormat != EGL_ALPHA_FORMAT_PRE) {
|
||||
_eglError(EGL_BAD_ATTRIBUTE, func);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
_eglError(EGL_BAD_ATTRIBUTE, func);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
#endif /* EGL_VERSION_1_2 */
|
||||
default:
|
||||
_eglError(EGL_BAD_ATTRIBUTE, func);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (width <= 0 || height <= 0) {
|
||||
_eglError(EGL_BAD_ATTRIBUTE, func);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
memset(surf, 0, sizeof(_EGLSurface));
|
||||
surf->Config = conf;
|
||||
surf->Type = type;
|
||||
surf->Width = width;
|
||||
surf->Height = height;
|
||||
surf->TextureFormat = texFormat;
|
||||
surf->TextureTarget = texTarget;
|
||||
surf->MipmapTexture = mipmapTex;
|
||||
surf->MipmapLevel = 0;
|
||||
surf->SwapInterval = 0;
|
||||
#ifdef EGL_VERSION_1_2
|
||||
surf->SwapBehavior = EGL_BUFFER_DESTROYED; /* XXX ok? */
|
||||
surf->HorizontalResolution = EGL_UNKNOWN; /* set by caller */
|
||||
surf->VerticalResolution = EGL_UNKNOWN; /* set by caller */
|
||||
surf->AspectRatio = EGL_UNKNOWN; /* set by caller */
|
||||
surf->RenderBuffer = renderBuffer;
|
||||
surf->AlphaFormat = alphaFormat;
|
||||
surf->Colorspace = colorspace;
|
||||
#endif
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_eglSaveSurface(_EGLSurface *surf)
|
||||
{
|
||||
assert(surf);
|
||||
assert(!surf->Handle);
|
||||
surf->Handle = _eglHashGenKey(_eglGlobal.Contexts);
|
||||
assert(surf->Handle);
|
||||
_eglHashInsert(_eglGlobal.Surfaces, surf->Handle, surf);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_eglRemoveSurface(_EGLSurface *surf)
|
||||
{
|
||||
_eglHashRemove(_eglGlobal.Surfaces, surf->Handle);
|
||||
}
|
||||
|
||||
|
||||
_EGLSurface *
|
||||
_eglLookupSurface(EGLSurface surf)
|
||||
{
|
||||
_EGLSurface *c = (_EGLSurface *) _eglHashLookup(_eglGlobal.Surfaces, surf);
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
_EGLSurface *
|
||||
_eglGetCurrentSurface(EGLint readdraw)
|
||||
{
|
||||
_EGLContext *ctx = _eglGetCurrentContext();
|
||||
if (ctx) {
|
||||
switch (readdraw) {
|
||||
case EGL_DRAW:
|
||||
return ctx->DrawSurface;
|
||||
case EGL_READ:
|
||||
return ctx->ReadSurface;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean
|
||||
_eglSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw)
|
||||
{
|
||||
/* Basically just do error checking here. Drivers have to do the
|
||||
* actual buffer swap.
|
||||
*/
|
||||
_EGLContext *context = _eglGetCurrentContext();
|
||||
_EGLSurface *surface = _eglLookupSurface(draw);
|
||||
if (context && context->DrawSurface != surface) {
|
||||
_eglError(EGL_BAD_SURFACE, "eglSwapBuffers");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
if (surface == NULL) {
|
||||
_eglError(EGL_BAD_SURFACE, "eglSwapBuffers");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean
|
||||
_eglCopyBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface,
|
||||
NativePixmapType target)
|
||||
{
|
||||
/* copy surface to native pixmap */
|
||||
/* All implementation burdon for this is in the device driver */
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean
|
||||
_eglQuerySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surf,
|
||||
EGLint attribute, EGLint *value)
|
||||
{
|
||||
_EGLSurface *surface = _eglLookupSurface(surf);
|
||||
if (surface == NULL) {
|
||||
_eglError(EGL_BAD_SURFACE, "eglQuerySurface");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
switch (attribute) {
|
||||
case EGL_WIDTH:
|
||||
*value = surface->Width;
|
||||
return EGL_TRUE;
|
||||
case EGL_HEIGHT:
|
||||
*value = surface->Height;
|
||||
return EGL_TRUE;
|
||||
case EGL_CONFIG_ID:
|
||||
*value = GET_CONFIG_ATTRIB(surface->Config, EGL_CONFIG_ID);
|
||||
return EGL_TRUE;
|
||||
/*XXX case EGL_LARGEST_PBUFFER:*/
|
||||
case EGL_SURFACE_TYPE:
|
||||
*value = surface->Type;
|
||||
return EGL_TRUE;
|
||||
#ifdef EGL_VERSION_1_1
|
||||
case EGL_TEXTURE_FORMAT:
|
||||
/* texture attributes: only for pbuffers, no error otherwise */
|
||||
if (surface->Type == EGL_PBUFFER_BIT)
|
||||
*value = surface->TextureFormat;
|
||||
return EGL_TRUE;
|
||||
case EGL_TEXTURE_TARGET:
|
||||
if (surface->Type == EGL_PBUFFER_BIT)
|
||||
*value = surface->TextureTarget;
|
||||
return EGL_TRUE;
|
||||
case EGL_MIPMAP_TEXTURE:
|
||||
if (surface->Type == EGL_PBUFFER_BIT)
|
||||
*value = surface->MipmapTexture;
|
||||
return EGL_TRUE;
|
||||
case EGL_MIPMAP_LEVEL:
|
||||
if (surface->Type == EGL_PBUFFER_BIT)
|
||||
*value = surface->MipmapLevel;
|
||||
return EGL_TRUE;
|
||||
#endif /* EGL_VERSION_1_1 */
|
||||
#ifdef EGL_VERSION_1_2
|
||||
case EGL_SWAP_BEHAVIOR:
|
||||
*value = surface->SwapBehavior;
|
||||
return EGL_TRUE;
|
||||
case EGL_RENDER_BUFFER:
|
||||
*value = surface->RenderBuffer;
|
||||
return EGL_TRUE;
|
||||
case EGL_PIXEL_ASPECT_RATIO:
|
||||
*value = surface->AspectRatio;
|
||||
return EGL_TRUE;
|
||||
case EGL_HORIZONTAL_RESOLUTION:
|
||||
*value = surface->HorizontalResolution;
|
||||
return EGL_TRUE;
|
||||
case EGL_VERTICAL_RESOLUTION:
|
||||
*value = surface->VerticalResolution;
|
||||
return EGL_TRUE;
|
||||
case EGL_ALPHA_FORMAT:
|
||||
*value = surface->AlphaFormat;
|
||||
return EGL_TRUE;
|
||||
case EGL_COLORSPACE:
|
||||
*value = surface->Colorspace;
|
||||
return EGL_TRUE;
|
||||
#endif /* EGL_VERSION_1_2 */
|
||||
default:
|
||||
_eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Example function - drivers should do a proper implementation.
|
||||
*/
|
||||
EGLSurface
|
||||
_eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
|
||||
NativeWindowType window, const EGLint *attrib_list)
|
||||
{
|
||||
#if 0 /* THIS IS JUST EXAMPLE CODE */
|
||||
_EGLSurface *surf;
|
||||
|
||||
surf = (_EGLSurface *) calloc(1, sizeof(_EGLSurface));
|
||||
if (!surf)
|
||||
return EGL_NO_SURFACE;
|
||||
|
||||
if (!_eglInitSurface(drv, dpy, surf, EGL_WINDOW_BIT, config, attrib_list)) {
|
||||
free(surf);
|
||||
return EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
_eglSaveSurface(surf);
|
||||
|
||||
return surf->Handle;
|
||||
#endif
|
||||
return EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Example function - drivers should do a proper implementation.
|
||||
*/
|
||||
EGLSurface
|
||||
_eglCreatePixmapSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
|
||||
NativePixmapType pixmap, const EGLint *attrib_list)
|
||||
{
|
||||
#if 0 /* THIS IS JUST EXAMPLE CODE */
|
||||
_EGLSurface *surf;
|
||||
|
||||
surf = (_EGLSurface *) calloc(1, sizeof(_EGLSurface));
|
||||
if (!surf)
|
||||
return EGL_NO_SURFACE;
|
||||
|
||||
if (!_eglInitSurface(drv, dpy, surf, EGL_PIXMAP_BIT, config, attrib_list)) {
|
||||
free(surf);
|
||||
return EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
_eglSaveSurface(surf);
|
||||
|
||||
return surf->Handle;
|
||||
#endif
|
||||
return EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Example function - drivers should do a proper implementation.
|
||||
*/
|
||||
EGLSurface
|
||||
_eglCreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
|
||||
const EGLint *attrib_list)
|
||||
{
|
||||
#if 0 /* THIS IS JUST EXAMPLE CODE */
|
||||
_EGLSurface *surf;
|
||||
|
||||
surf = (_EGLSurface *) calloc(1, sizeof(_EGLSurface));
|
||||
if (!surf)
|
||||
return EGL_NO_SURFACE;
|
||||
|
||||
if (!_eglInitSurface(drv, dpy, surf, EGL_PBUFFER_BIT, config, attrib_list)) {
|
||||
free(surf);
|
||||
return EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
_eglSaveSurface(surf);
|
||||
|
||||
return surf->Handle;
|
||||
#endif
|
||||
return EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Default fallback routine - drivers should usually override this.
|
||||
*/
|
||||
EGLBoolean
|
||||
_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
|
||||
{
|
||||
_EGLSurface *surf = _eglLookupSurface(surface);
|
||||
if (surf) {
|
||||
_eglHashRemove(_eglGlobal.Surfaces, surface);
|
||||
if (surf->IsBound) {
|
||||
surf->DeletePending = EGL_TRUE;
|
||||
}
|
||||
else {
|
||||
free(surf);
|
||||
}
|
||||
return EGL_TRUE;
|
||||
}
|
||||
else {
|
||||
_eglError(EGL_BAD_SURFACE, "eglDestroySurface");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Default fallback routine - drivers might override this.
|
||||
*/
|
||||
EGLBoolean
|
||||
_eglSurfaceAttrib(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surf, EGLint attribute, EGLint value)
|
||||
{
|
||||
_EGLSurface *surface = _eglLookupSurface(surf);
|
||||
|
||||
if (surface == NULL) {
|
||||
_eglError(EGL_BAD_SURFACE, "eglSurfaceAttrib");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
switch (attribute) {
|
||||
case EGL_MIPMAP_LEVEL:
|
||||
surface->MipmapLevel = value;
|
||||
break;
|
||||
default:
|
||||
_eglError(EGL_BAD_ATTRIBUTE, "eglSurfaceAttrib");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean
|
||||
_eglBindTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint buffer)
|
||||
{
|
||||
/* XXX unfinished */
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean
|
||||
_eglReleaseTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint buffer)
|
||||
{
|
||||
/* XXX unfinished */
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean
|
||||
_eglSwapInterval(_EGLDriver *drv, EGLDisplay dpy, EGLint interval)
|
||||
{
|
||||
_EGLSurface *surf = _eglGetCurrentSurface(EGL_DRAW);
|
||||
if (surf == NULL) {
|
||||
_eglError(EGL_BAD_SURFACE, "eglSwapInterval");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
surf->SwapInterval = interval;
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
#ifdef EGL_VERSION_1_2
|
||||
|
||||
/**
|
||||
* Example function - drivers should do a proper implementation.
|
||||
*/
|
||||
EGLSurface
|
||||
_eglCreatePbufferFromClientBuffer(_EGLDriver *drv, EGLDisplay dpy,
|
||||
EGLenum buftype, EGLClientBuffer buffer,
|
||||
EGLConfig config, const EGLint *attrib_list)
|
||||
{
|
||||
if (buftype != EGL_OPENVG_IMAGE) {
|
||||
_eglError(EGL_BAD_PARAMETER, "eglCreatePbufferFromClientBuffer");
|
||||
return EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
return EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
#endif /* EGL_VERSION_1_2 */
|
||||
@@ -1,117 +0,0 @@
|
||||
#ifndef EGLSURFACE_INCLUDED
|
||||
#define EGLSURFACE_INCLUDED
|
||||
|
||||
|
||||
#include "egltypedefs.h"
|
||||
|
||||
|
||||
/**
|
||||
* "Base" class for device driver surfaces.
|
||||
*/
|
||||
struct _egl_surface
|
||||
{
|
||||
EGLSurface Handle; /* The public/opaque handle which names this object */
|
||||
_EGLConfig *Config;
|
||||
|
||||
/* May need reference counting here */
|
||||
EGLBoolean IsBound;
|
||||
EGLBoolean DeletePending;
|
||||
|
||||
EGLint Type; /* one of EGL_WINDOW_BIT, EGL_PIXMAP_BIT or EGL_PBUFFER_BIT */
|
||||
EGLint Width, Height;
|
||||
EGLint TextureFormat, TextureTarget;
|
||||
EGLint MipmapTexture, MipmapLevel;
|
||||
EGLint SwapInterval;
|
||||
|
||||
/* If type == EGL_SCREEN_BIT: */
|
||||
EGLint VisibleRefCount; /* number of screens I'm displayed on */
|
||||
|
||||
#ifdef EGL_VERSION_1_2
|
||||
EGLint SwapBehavior; /* one of EGL_BUFFER_PRESERVED/DESTROYED */
|
||||
EGLint HorizontalResolution, VerticalResolution;
|
||||
EGLint AspectRatio;
|
||||
EGLint RenderBuffer; /* EGL_BACK_BUFFER or EGL_SINGLE_BUFFER */
|
||||
EGLint AlphaFormat; /* EGL_ALPHA_FORMAT_NONPRE or EGL_ALPHA_FORMAT_PRE */
|
||||
EGLint Colorspace; /* EGL_COLORSPACE_sRGB or EGL_COLORSPACE_LINEAR */
|
||||
#endif /* EGL_VERSION_1_2 */
|
||||
};
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
_eglInitSurface(_EGLDriver *drv, EGLDisplay dpy,
|
||||
_EGLSurface *surf, EGLint type, EGLConfig config,
|
||||
const EGLint *attrib_list);
|
||||
|
||||
|
||||
extern void
|
||||
_eglSaveSurface(_EGLSurface *surf);
|
||||
|
||||
|
||||
extern void
|
||||
_eglRemoveSurface(_EGLSurface *surf);
|
||||
|
||||
|
||||
extern _EGLSurface *
|
||||
_eglLookupSurface(EGLSurface surf);
|
||||
|
||||
|
||||
extern _EGLSurface *
|
||||
_eglGetCurrentSurface(EGLint readdraw);
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
_eglSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw);
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
_eglCopyBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, NativePixmapType target);
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
_eglQuerySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value);
|
||||
|
||||
|
||||
extern EGLSurface
|
||||
_eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint *attrib_list);
|
||||
|
||||
|
||||
extern EGLSurface
|
||||
_eglCreatePixmapSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativePixmapType pixmap, const EGLint *attrib_list);
|
||||
|
||||
|
||||
extern EGLSurface
|
||||
_eglCreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface);
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
_eglSurfaceAttrib(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value);
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
_eglBindTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint buffer);
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
_eglReleaseTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint buffer);
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
_eglSwapInterval(_EGLDriver *drv, EGLDisplay dpy, EGLint interval);
|
||||
|
||||
|
||||
#ifdef EGL_VERSION_1_2
|
||||
|
||||
extern EGLSurface
|
||||
_eglCreatePbufferFromClientBuffer(_EGLDriver *drv, EGLDisplay dpy,
|
||||
EGLenum buftype, EGLClientBuffer buffer,
|
||||
EGLConfig config, const EGLint *attrib_list);
|
||||
|
||||
#endif /* EGL_VERSION_1_2 */
|
||||
|
||||
|
||||
|
||||
#endif /* EGLSURFACE_INCLUDED */
|
||||
@@ -1,34 +0,0 @@
|
||||
#ifndef EGLTYPEDEFS_INCLUDED
|
||||
#define EGLTYPEDEFS_INCLUDED
|
||||
|
||||
|
||||
#include <GLES/egl.h>
|
||||
|
||||
|
||||
typedef struct _egl_api _EGLAPI;
|
||||
|
||||
typedef struct _egl_config _EGLConfig;
|
||||
|
||||
typedef struct _egl_context _EGLContext;
|
||||
|
||||
typedef struct _egl_display _EGLDisplay;
|
||||
|
||||
typedef struct _egl_driver _EGLDriver;
|
||||
|
||||
typedef struct _egl_extensions _EGLExtensions;
|
||||
|
||||
typedef struct _egl_mode _EGLMode;
|
||||
|
||||
typedef struct _egl_screen _EGLScreen;
|
||||
|
||||
typedef struct _egl_surface _EGLSurface;
|
||||
|
||||
typedef struct _egl_thread_info _EGLThreadInfo;
|
||||
|
||||
|
||||
typedef void (*_EGLProc)();
|
||||
|
||||
typedef _EGLDriver *(*_EGLMain_t)(_EGLDisplay *dpy);
|
||||
|
||||
|
||||
#endif /* EGLTYPEDEFS_INCLUDED */
|
||||
@@ -1,56 +0,0 @@
|
||||
# src/glu/mesa/Makefile
|
||||
|
||||
TOP = ../../..
|
||||
|
||||
include $(TOP)/configs/current
|
||||
|
||||
GLU_MAJOR = 1
|
||||
GLU_MINOR = 1
|
||||
GLU_TINY = 0$(MESA_MAJOR)0$(MESA_MINOR)0$(MESA_TINY)
|
||||
|
||||
C_SOURCES = \
|
||||
glu.c \
|
||||
mipmap.c \
|
||||
nurbs.c \
|
||||
nurbscrv.c \
|
||||
nurbssrf.c \
|
||||
nurbsutl.c \
|
||||
polytest.c \
|
||||
project.c \
|
||||
quadric.c \
|
||||
tess.c \
|
||||
tesselat.c
|
||||
|
||||
OBJECTS = $(C_SOURCES:.c=.o)
|
||||
|
||||
INCLUDES = -I. -I$(TOP)/include
|
||||
|
||||
##### RULES #####
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(INCLUDES) $(CFLAGS) $< -o $@
|
||||
|
||||
##### TARGETS #####
|
||||
|
||||
default:
|
||||
@if [ "${CONFIG_NAME}" = "beos" ] ; then \
|
||||
echo "$(GLU_LIB_NAME) not build under BeOS, but integrated into ${GL_LIB_NAME}." ; \
|
||||
exit 0 ; \
|
||||
else \
|
||||
$(MAKE) $(TOP)/$(LIB_DIR)/$(GLU_LIB_NAME) || exit 1 ; \
|
||||
fi
|
||||
|
||||
$(TOP)/$(LIB_DIR):
|
||||
-mkdir $(TOP)/$(LIB_DIR)
|
||||
|
||||
# Make the library:
|
||||
$(TOP)/$(LIB_DIR)/$(GLU_LIB_NAME): $(OBJECTS)
|
||||
@ $(MKLIB) -o $(GLU_LIB) -linker '$(CC)' -ldflags '$(LDFLAGS)' \
|
||||
-major $(GLU_MAJOR) -minor $(GLU_MINOR) -patch $(GLU_TINY) \
|
||||
$(MKLIB_OPTIONS) -install $(TOP)/$(LIB_DIR) \
|
||||
$(GLU_LIB_DEPS) $(OBJECTS)
|
||||
|
||||
clean:
|
||||
-rm -f *.o */*.o */*/*.o
|
||||
-rm -f *.lo */*.lo */*/*.lo
|
||||
-rm -f *.la */*.la */*/*.la
|
||||
@@ -1,100 +0,0 @@
|
||||
# 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 glu makefile v1.5 for Mesa
|
||||
#
|
||||
# Copyright (C) 2002 - Daniel Borca
|
||||
# Email : dborca@users.sourceforge.net
|
||||
# Web : http://www.geocities.com/dborca
|
||||
|
||||
|
||||
#
|
||||
# Available options:
|
||||
#
|
||||
# Environment variables:
|
||||
# CFLAGS
|
||||
#
|
||||
# Targets:
|
||||
# all: build GLU
|
||||
# clean: remove object files
|
||||
#
|
||||
|
||||
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
TOP = ../../..
|
||||
LIBDIR = $(TOP)/lib
|
||||
GLU_LIB = libglu.a
|
||||
GLU_DXE = glu.dxe
|
||||
GLU_IMP = libiglu.a
|
||||
|
||||
export LD_LIBRARY_PATH := $(LD_LIBRARY_PATH);$(LIBDIR);$(GLIDE)/lib
|
||||
|
||||
CC = gcc
|
||||
CFLAGS += -I$(TOP)/include
|
||||
|
||||
AR = ar
|
||||
ARFLAGS = crus
|
||||
|
||||
HAVEDXE3 = $(wildcard $(DJDIR)/bin/dxe3gen.exe)
|
||||
|
||||
ifeq ($(wildcard $(addsuffix /rm.exe,$(subst ;, ,$(PATH)))),)
|
||||
UNLINK = del $(subst /,\,$(1))
|
||||
else
|
||||
UNLINK = $(RM) $(1)
|
||||
endif
|
||||
|
||||
CORE_SOURCES = \
|
||||
glu.c \
|
||||
mipmap.c \
|
||||
nurbs.c \
|
||||
nurbscrv.c \
|
||||
nurbssrf.c \
|
||||
nurbsutl.c \
|
||||
polytest.c \
|
||||
project.c \
|
||||
quadric.c \
|
||||
tess.c \
|
||||
tesselat.c
|
||||
|
||||
SOURCES = $(CORE_SOURCES)
|
||||
|
||||
OBJECTS = $(SOURCES:.c=.o)
|
||||
|
||||
.c.o:
|
||||
$(CC) -o $@ $(CFLAGS) -c $<
|
||||
|
||||
all: $(LIBDIR)/$(GLU_LIB) $(LIBDIR)/$(GLU_DXE) $(LIBDIR)/$(GLU_IMP)
|
||||
|
||||
$(LIBDIR)/$(GLU_LIB): $(OBJECTS)
|
||||
$(AR) $(ARFLAGS) $@ $^
|
||||
|
||||
$(LIBDIR)/$(GLU_DXE) $(LIBDIR)/$(GLU_IMP): $(OBJECTS)
|
||||
ifeq ($(HAVEDXE3),)
|
||||
$(warning Missing DXE3 package... Skipping $(GLU_DXE))
|
||||
else
|
||||
-dxe3gen -o $(LIBDIR)/$(GLU_DXE) -Y $(LIBDIR)/$(GLU_IMP) -D "MesaGLU DJGPP" -E _glu -P gl.dxe -U $^
|
||||
endif
|
||||
|
||||
clean:
|
||||
-$(call UNLINK,*.o)
|
||||
@@ -1,63 +0,0 @@
|
||||
# Makefile for GLU for GCC-2.95.2/Mingw32 contributed by
|
||||
# Paul Garceau <pgarceau@teleport.com>
|
||||
|
||||
# Mesa 3-D graphics library
|
||||
# Version: 3.3
|
||||
# Copyright (C) 1995-1999 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.
|
||||
|
||||
|
||||
MESA_MAJOR=3
|
||||
MESA_MINOR=3
|
||||
MESA_TINY=0
|
||||
VERSION=$(MESA_MAJOR).$(MESA_MINOR)
|
||||
|
||||
CFLAGS = -I. -DWIN32 -D__WIN32__ -D_WINDOWS \
|
||||
-O2 -funroll-loops \
|
||||
-fexpensive-optimizations -fomit-frame-pointer -ffast-math \
|
||||
-malign-loops=2 -malign-jumps=2 -malign-functions=2 \
|
||||
-mwindows
|
||||
CC = gcc
|
||||
MAKELIB = ar ru
|
||||
GLU_LIB = libGLU.a
|
||||
|
||||
|
||||
##### MACROS #####
|
||||
|
||||
VPATH = RCS
|
||||
|
||||
INCDIR = ../include
|
||||
LIBDIR = ../lib
|
||||
|
||||
SOURCES = glu.c mipmap.c nurbs.c nurbscrv.c nurbssrf.c nurbsutl.c \
|
||||
polytest.c project.c quadric.c tess.c tesselat.c
|
||||
|
||||
OBJECTS = $(SOURCES:.c=.o)
|
||||
|
||||
|
||||
|
||||
##### RULES #####
|
||||
|
||||
.c.o:
|
||||
$(CC) -c -I$(INCDIR) $(CFLAGS) $<
|
||||
|
||||
|
||||
|
||||
##### TARGETS #####
|
||||
|
||||
# Make the library:
|
||||
$(LIBDIR)/$(GLU_LIB): $(OBJECTS)
|
||||
$(MAKELIB) $(GLU_LIB) $(MAJOR) $(MINOR) $(TINY) $(OBJECTS)
|
||||
@@ -1,96 +0,0 @@
|
||||
# Mesa 3-D graphics library
|
||||
# Version: 3.5
|
||||
#
|
||||
# Copyright (C) 2001 Wind River Systems, Inc
|
||||
|
||||
# The MIT License
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a
|
||||
# copy of this software and associated documentation files (the "Software"),
|
||||
# to deal in the Software without restriction, including without limitation
|
||||
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
# and/or sell copies of the Software, and to permit persons to whom the
|
||||
# Software is furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included
|
||||
# in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
# DEALINGS IN THE SOFTWARE.
|
||||
|
||||
# Makefile for GLU library
|
||||
|
||||
##### MACROS #####
|
||||
GLU_MAJOR = 1
|
||||
GLU_MINOR = 3
|
||||
GLU_TINY = 0$(MESA_MAJOR)0$(MESA_MINOR)0$(MESA_TINY)
|
||||
|
||||
##### RULES #####
|
||||
|
||||
include ../rules.windml
|
||||
|
||||
GLU_SOURCES = \
|
||||
glu.c \
|
||||
mipmap.c \
|
||||
nurbs.c \
|
||||
nurbscrv.c \
|
||||
nurbssrf.c \
|
||||
nurbsutl.c \
|
||||
polytest.c \
|
||||
project.c \
|
||||
quadric.c \
|
||||
tess.c \
|
||||
tesselat.c \
|
||||
../src/windml/tornado/torMesaGLUInit.c
|
||||
|
||||
GLU_OBJECTS = $(GLU_SOURCES:.c=.o)
|
||||
GLU_OBJNAME = $(MESA_LIBDIR)/objMesaGLU.o
|
||||
|
||||
SOURCES = $(GLU_SOURCES)
|
||||
|
||||
##### TARGETS #####
|
||||
|
||||
all: depend.$(CPU)$(TOOL) $(GLU_OBJNAME)
|
||||
|
||||
# Make the GLU library
|
||||
$(GLU_OBJNAME): $(GLU_OBJECTS)
|
||||
# $(LD) -r $(GLU_OBJECTS) -o $(MESA_OBJNAME)
|
||||
$(LD) -r $(GLU_OBJECTS) -o $(GLU_OBJNAME)
|
||||
# $(AR) rus $(MESA_LIBNAME) $(GLU_OBJNAME)
|
||||
# $(AR) rus $(VX_LIBNAME) $(GLU_OBJNAME)
|
||||
|
||||
depend.$(CPU)$(TOOL):
|
||||
ifeq ($(WIND_HOST_TYPE),x86-win32)
|
||||
@ $(RM) $@
|
||||
@ $(ECHO) Creating depend.$(CPU)$(TOOL)
|
||||
ifneq ($(SOURCES),)
|
||||
@ for %f in ($(SOURCES)) do \
|
||||
$(CC) -MM $(CFLAGS) %f >>$@
|
||||
endif
|
||||
else
|
||||
Makefile
|
||||
@ $(RM) $@
|
||||
@ $(ECHO) "Creating depend.$(CPU)$(TOOL)"
|
||||
ifneq ($(SOURCES),)
|
||||
@ for FILE in $(filter-out $(NODEPENDOBJS), $(SOURCES)); \
|
||||
do \
|
||||
$(CC) -MM $(CFLAGS) $$FILE \
|
||||
| $(TCL) $(BIN_DIR)/depend.tcl $(TGT_DIR) >>$@; \
|
||||
done
|
||||
endif
|
||||
endif
|
||||
|
||||
.PHONY = clean
|
||||
|
||||
clean:
|
||||
# $(AR) d $(MESA_LIBNAME) $(GLU_OBJNAME)
|
||||
# $(AR) d $(VX_LIBNAME) $(GLU_OBJNAME)
|
||||
$(RM) $(GLU_OBJNAME)
|
||||
$(RM) $(GLU_OBJECTS)
|
||||
$(RM) depend.$(CPU)$(TOOL)
|
||||
|
||||
include depend.$(CPU)$(TOOL)
|
||||
@@ -1,62 +0,0 @@
|
||||
LIBRARY GLU32
|
||||
DESCRIPTION 'GLU for Windows Mesa'
|
||||
EXETYPE WINDOWS
|
||||
CODE MOVEABLE DISCARDABLE
|
||||
DATA MOVEABLE SINGLE
|
||||
HEAPSIZE 256000
|
||||
|
||||
STACKSIZE 4096
|
||||
|
||||
EXPORTS
|
||||
gluLookAt
|
||||
gluOrtho2D
|
||||
gluPerspective
|
||||
gluPickMatrix
|
||||
gluProject
|
||||
gluUnProject
|
||||
gluErrorString
|
||||
gluScaleImage
|
||||
gluBuild1DMipmaps
|
||||
gluBuild2DMipmaps
|
||||
gluNewQuadric
|
||||
gluDeleteQuadric
|
||||
gluQuadricDrawStyle
|
||||
gluQuadricOrientation
|
||||
gluQuadricNormals
|
||||
gluQuadricTexture
|
||||
gluQuadricCallback
|
||||
gluCylinder
|
||||
gluSphere
|
||||
gluDisk
|
||||
gluPartialDisk
|
||||
gluNewNurbsRenderer
|
||||
gluDeleteNurbsRenderer
|
||||
gluLoadSamplingMatrices
|
||||
gluNurbsProperty
|
||||
gluGetNurbsProperty
|
||||
gluBeginCurve
|
||||
gluEndCurve
|
||||
gluNurbsCurve
|
||||
gluBeginSurface
|
||||
gluEndSurface
|
||||
gluNurbsSurface
|
||||
gluBeginTrim
|
||||
gluEndTrim
|
||||
gluPwlCurve
|
||||
gluNurbsCallback
|
||||
gluNewTess
|
||||
gluDeleteTess
|
||||
; gluTessBeginPolygon
|
||||
; gluTessBeginContour
|
||||
gluTessVertex
|
||||
; gluTessEndContour
|
||||
; gluTessEndPolygon
|
||||
; gluTessProperty
|
||||
; gluTessNormal
|
||||
gluTessCallback
|
||||
; gluGetTessProperty
|
||||
gluBeginPolygon
|
||||
gluNextContour
|
||||
gluEndPolygon
|
||||
gluGetString
|
||||
|
||||
@@ -1,195 +0,0 @@
|
||||
|
||||
Notes on the GLU polygon tesselation facility implemented by Bogdan Sikorski...
|
||||
|
||||
|
||||
|
||||
The tesselation module is provided under the same terms as the Mesa
|
||||
package.
|
||||
|
||||
This is the first release of polygon tesselation code for Mesa.
|
||||
It was written during my very little free time, so lets name it:
|
||||
"its not perfect". If someone hates pointers, don't look at the code.
|
||||
I preffer dynamic allocation versus static. But _all_ ideas, suggestions,
|
||||
bug reports and fixes are welcome (if You want, also flames). I am aware
|
||||
that many things could have been written using better techniques, but time
|
||||
that I could devote to this library was very limited. It is not well commented,
|
||||
excuse me. Also I am thinking of continuing working on this code to improve,
|
||||
fix and polish it. And make it as compliant as possible to the OpenGL, so
|
||||
software ports from OpenGL to Mesa will work correctly. If You know of any
|
||||
differences in behaviour, expected input/output between Mesa tesselation library
|
||||
and OpenGL, please send me a note. I explain later on why I am not
|
||||
confident with this code.
|
||||
|
||||
I tried to be fully compliant with the OpenGL routines. By "tried" I mean that
|
||||
up to my knowledge it behaves as OpenGL tesselation routines. Just recently
|
||||
I began to experiment with OpenGL (actually only Mesa), and also have
|
||||
no access to any machine providing official implementation of OpenGL,
|
||||
nor access to books (particulary Addison-Wesley publications). Thus my
|
||||
knowledge on how the original tesselation code works, what kind of data
|
||||
it expects etc. is based _only_ on the publicly available documentation
|
||||
provided by SGI. Namely:
|
||||
|
||||
* "The OpenGL Graphics System Utility Library" by K.P.Smith
|
||||
(Silicon Graphics, 1992)
|
||||
* "The OpenGL Graphics Interface" by M.Segal and K.Akeley
|
||||
(Silicon Graphics, 19??)
|
||||
* "OpenGL and X, Part 1: Introduction" by M.J.Kilgard
|
||||
(Silicon Graphics, 1994)
|
||||
* "OpenGL and X, Part 2: Using OpenGL with Xlib" by M.J.Kilgard
|
||||
(Silicon Graphics, 1994)
|
||||
* "OpenGL Graphics with the X Window System" by P.Karlton
|
||||
(Silicon Graphics, 1993)
|
||||
* Online Docs - Appendix C of OpenGL Programming Guide, Polygon Tesselation
|
||||
(partial text cut and sent by e-mail)
|
||||
|
||||
|
||||
The tesselation routines use slightly different prototypes than the ones
|
||||
specified in the mentioned above publications. The _only_ differences are
|
||||
the enumeration types which are not GLenum, but are GLUenum. So the
|
||||
implemented routines have following prototypes:
|
||||
|
||||
GLUtringulatorObj *gluNewTess(void);
|
||||
|
||||
void gluTessCallback(GLUtriangulatorObj *,GLUenum,void (*)());
|
||||
^^^^^^^
|
||||
void gluBeginPolygon(GLUtriangulatorObj *);
|
||||
|
||||
void gluTessVertex(GLUtriangulatorObj *,GLdouble [3],void *);
|
||||
|
||||
void gluNextContour(GLUtriangulatorObj *,GLUenum);
|
||||
^^^^^^^
|
||||
void gluEndPolygon(GLUtriangulatorObj *);
|
||||
|
||||
const GLubyte *gluErrorString(GLUenum);
|
||||
^^^^^^^
|
||||
prototypes for callback functions:
|
||||
|
||||
void <begin>(GLUenum);
|
||||
^^^^^^^
|
||||
void <edgeFlag>(GLboolean);
|
||||
void <vertex>(void *);
|
||||
void <end>(void);
|
||||
void <error>(GLUenum);
|
||||
^^^^^^^
|
||||
|
||||
The begin callback will be called only with GLU_TRIANGLES. No support
|
||||
for traingle fans or strips yet.
|
||||
|
||||
In case of errors an internal error variable is set to the appropiate
|
||||
error enum values (GLU_TESS_ERROR?). Initially it is set to GLU_NO_ERROR.
|
||||
The OpenGL library provides 8 error conditions, the tesselation code
|
||||
of Mesa provides 9. They are:
|
||||
|
||||
GLU_TESS_ERROR1: missing gluEndPolygon /* same as OpenGL */
|
||||
GLU_TESS_ERROR2: missing gluBeginPolygon /* same as OpenGL */
|
||||
GLU_TESS_ERROR3: misoriented contour /* not used in Mesa
|
||||
in OpenGL is bad orientation or intersecting edges */
|
||||
GLU_TESS_ERROR4: vertex/edge intersection /* same as OpenGL */
|
||||
GLU_TESS_ERROR5: misoriented or self-intersecting loops /* same as OpenGL */
|
||||
GLU_TESS_ERROR6: coincident vertices /* same as OpenGL */
|
||||
GLU_TESS_ERROR7: colinear vertices /* OpenGL's illegal data */
|
||||
GLU_TESS_ERROR8: intersecting edges /* same as OpenGL */
|
||||
GLU_TESS_ERROR9: not coplanar contours /* new for Mesa */
|
||||
|
||||
The Mesa tesselation code ignores all data and calls after detecting an error
|
||||
codition. This means that a _new_ tesselation object must be used for further
|
||||
triangulations. Maybe this is too restrictive, and will be lifted in
|
||||
future versions.
|
||||
|
||||
The tesselation code completely ignores the type parameter passed in
|
||||
gluNextContour. It also doesn't check if the passed parameter is a legal
|
||||
enum value - ignores silently (maybe at least this should be checked).
|
||||
The reason I chose this behaviour is based on what I read in the
|
||||
beforementioned documents. I cite:
|
||||
|
||||
"....
|
||||
void gluNextContour(GLUtriangulatorObj *tessobj, GLenum type);
|
||||
|
||||
Marks the beginning of the next contour when multiple contours make up the
|
||||
boundary of the polygon to be tessellated. type can be GLU_EXTERIOR,
|
||||
GLU_INTERIOR, GLU_CCW, GLU_CW, or GLU_UNKNOWN. These serve only as
|
||||
to the tessellation. If you get them right, the tessellation might
|
||||
go faster. If you get them wrong, they're ignored, and the tesselation still
|
||||
works.
|
||||
....."
|
||||
|
||||
I hope You agree with me that my decision was correct. Mesa tesselation
|
||||
_always_ checks by itself the interrelations between contours. Just as if
|
||||
all contours were specified with the type GLU_UNKNOWN.
|
||||
|
||||
One of OpenGL's policy is not to check all error conditions - rely sometimes
|
||||
that the user "got things right". This is justified, since exhausting
|
||||
error checking is timeconsuming, and would significantly slow down
|
||||
a correct application. The Mesa tesselation code assumes only _one_ condition
|
||||
when triangulating - all vertices in a contour are planar. This is _not_
|
||||
checked for correctness. Trying to tesselate such objects will lead to
|
||||
unpredictable output.
|
||||
|
||||
And now we arrive to the moment where I would like to list the required
|
||||
(but checked for) conditions for triangulation, as well as summarize the
|
||||
library:
|
||||
|
||||
* all contours in a single tesselation cycle _must_ be coplanar - if not
|
||||
an error is raised (and if provided a call to the error callback
|
||||
is made)
|
||||
* the contours can be passed in _any_ order, exteriors and holes can be
|
||||
intermixed within a tesselation cycle and the correct hierarchy
|
||||
will be determined by the library; thus specifying first holes then
|
||||
exteriors, then holes within holes form a valid input.
|
||||
* a hole within a hole is consider to be a yet another exterior contour
|
||||
* multiple exterior contours (polygons) can be tesselated in one cycle;
|
||||
_but_ this significantly degrades performance since many tests will be
|
||||
performed for every contour pair; if You want triangulation to be fast
|
||||
tesselate a single polygon (with possible holes) one at a time.
|
||||
* orientation of exterior contours is arbitray, but if it has holes,
|
||||
all interior holes of this particular exterior contour _must_ have an
|
||||
opposite orientation.
|
||||
* the output triangles have the same orientation as the exterior contour
|
||||
that forms them
|
||||
* each triangle is "enclosed" within the begin and end callbacks;
|
||||
this is not efficent, but was made on purpose; so if triangulation
|
||||
results in 2 triangles the following callbacks will be made in such
|
||||
order:
|
||||
<begin>(GLU_TRAINGLES)
|
||||
<vertex>(...) /* 3 vertices of first triangle */
|
||||
<vertex>(...)
|
||||
<vertex>(...)
|
||||
<end>()
|
||||
<begin>(GLU_TRAINGLES)
|
||||
<vertex>(...) /* 3 vertices of second triangle */
|
||||
<vertex>(...)
|
||||
<vertex>(...)
|
||||
<end>()
|
||||
Of course only when begin, vertex, and end callback were provided,
|
||||
otherwise no output is done (actually tesselation does not take place).
|
||||
* You will notice that some output traingles are very "thin"; there
|
||||
exist possible several ways to traingulate a polygon, but "smart" code
|
||||
avoiding such cases would require time to write, and will impact on
|
||||
execution speed.
|
||||
* like OpenGL, no new vertices are introduced during triangulation
|
||||
* if the edgeflag callback is provided it will be called whenever
|
||||
the just-about-to be output vertex begins a different type of edge
|
||||
than the previous vertices; always before the first output a call
|
||||
is made with GL_TRUE, to allow synchronization.
|
||||
* all intermediate computations are done using GLdouble type, and comparisons
|
||||
are biased with a precision value (EPSILON defined in tess.h)
|
||||
* the point_in_poly function is my adaptation of code from the
|
||||
comp.graphics.alg newsgroup FAQ (originally written by Mr. Wm. Randolph
|
||||
Franklin, modified by Scott Anguish).
|
||||
* the edge_edge_intersect test is also an adopted code from comp.graphics.alg
|
||||
newsgroup FAQ
|
||||
* the general idea for traingulation used in this library is described in
|
||||
the book "Computational Geometry in C" by Joseph O'Rourke.
|
||||
|
||||
|
||||
Excuse my English, its not my mother tongue. I should be available for some
|
||||
time uner the following e-mail address. But For how long I am not certain.
|
||||
Once I am settled in my new place, I'll post on the Mesa mailing list
|
||||
my new address.
|
||||
|
||||
(PS: today is my last day of work here, I'm changing my job).
|
||||
|
||||
Bogdan. ( bogdan@dia.unisa.it )
|
||||
|
||||
Apr 28, 1995.
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
The current NURBS implementation has no trimming facilities yet.
|
||||
|
||||
The code is not well commented.
|
||||
|
||||
1) Normal calculus fails for special cases of NURBS (independent
|
||||
of the NURBS modules)
|
||||
Those cases arise when for u or v, some control points
|
||||
for a fixed value of that parameter form the same point.
|
||||
Imagine a Bezier patch degenerated into a "triangle".
|
||||
|
||||
v ^ 0,1,2 order=3
|
||||
| *
|
||||
|
|
||||
| 3* 4* 5*
|
||||
|
|
||||
| 6* 7* 8*
|
||||
|
|
||||
|
|
||||
+------------------------> u
|
||||
|
||||
The calculus of du derivative at triple point (0,1 and 2) will fail.
|
||||
As a result, the normal vector will be 0.
|
||||
The eval2.c code has to be changed to handle the above situation.
|
||||
|
||||
2) Adjacent NURBS surfaces ("sharing" the same control points along
|
||||
the "joining" edge) will be sampled with the same factor.
|
||||
This prevents the formation of "cracks".
|
||||
When the control polygon of the "shared" edge is not the same,
|
||||
cracks might appear.
|
||||
|
||||
The sampling tolerance is sometimes not respected!
|
||||
A NURBS object is broken into Bezier curves/surfaces. If one of such
|
||||
Bezier objects has a local high curvature with other portions of it
|
||||
relatively flat then the high curvature part will be sampled more dense that
|
||||
its flatter regions.
|
||||
The flat regions might be tesselated into quads having sides of length
|
||||
greater than the current sampling tolernace setting.
|
||||
I believe such behaviour is acceptable, though not along the concept of
|
||||
sampling tolerance.
|
||||
|
||||
February 20, 1996.
|
||||
|
||||
Bogdan.
|
||||
@@ -1,54 +0,0 @@
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
@@ -1,61 +0,0 @@
|
||||
# Makefile for GLU for VMS
|
||||
# contributed by Jouk Jansen joukj@hrem.stm.tudelft.nl
|
||||
|
||||
.first
|
||||
define gl [-.include.gl]
|
||||
|
||||
.include [-]mms-config.
|
||||
|
||||
##### MACROS #####
|
||||
|
||||
VPATH = RCS
|
||||
|
||||
INCDIR = $disk2:[-.include]
|
||||
LIBDIR = [-.lib]
|
||||
CFLAGS = /include=$(INCDIR)/define=(FBIND=1)/name=(as_is,short)/float=ieee/ieee=denorm
|
||||
|
||||
SOURCES = glu.c mipmap.c nurbs.c nurbscrv.c nurbssrf.c nurbsutl.c \
|
||||
polytest.c project.c quadric.c tess.c tesselat.c
|
||||
|
||||
OBJECTS =glu.obj,mipmap.obj,nurbs.obj,nurbscrv.obj,nurbssrf.obj,nurbsutl.obj,\
|
||||
polytest.obj,project.obj,quadric.obj,tess.obj,tesselat.obj
|
||||
|
||||
|
||||
##### RULES #####
|
||||
|
||||
VERSION=MesaGlu V3.2
|
||||
|
||||
##### TARGETS #####
|
||||
|
||||
# Make the library:
|
||||
$(LIBDIR)$(GLU_LIB) : $(OBJECTS)
|
||||
.ifdef SHARE
|
||||
@ WRITE_ SYS$OUTPUT " generating mesagl1.opt"
|
||||
@ OPEN_/WRITE FILE mesagl1.opt
|
||||
@ WRITE_ FILE "!"
|
||||
@ WRITE_ FILE "! mesagl1.opt generated by DESCRIP.$(MMS_EXT)"
|
||||
@ WRITE_ FILE "!"
|
||||
@ WRITE_ FILE "IDENTIFICATION=""$(VERSION)"""
|
||||
@ WRITE_ FILE "GSMATCH=LEQUAL,3,2
|
||||
@ WRITE_ FILE "$(OBJECTS)"
|
||||
@ WRITE_ FILE "[-.lib]libmesagl.exe/SHARE"
|
||||
@ WRITE_ FILE "SYS$SHARE:DECW$XEXTLIBSHR/SHARE"
|
||||
@ WRITE_ FILE "SYS$SHARE:DECW$XLIBSHR/SHARE"
|
||||
@ CLOSE_ FILE
|
||||
@ WRITE_ SYS$OUTPUT " generating mesagl.map ..."
|
||||
@ LINK_/NODEB/NOSHARE/NOEXE/MAP=mesagl.map/FULL mesagl1.opt/OPT
|
||||
@ WRITE_ SYS$OUTPUT " analyzing mesagl.map ..."
|
||||
@ @[-.vms]ANALYZE_MAP.COM mesagl.map mesagl.opt
|
||||
@ WRITE_ SYS$OUTPUT " linking $(GLU_LIB) ..."
|
||||
@ LINK_/noinform/NODEB/SHARE=$(GLU_LIB)/MAP=mesagl.map/FULL mesagl1.opt/opt,mesagl.opt/opt
|
||||
.else
|
||||
@ $(MAKELIB) $(GLU_LIB) $(OBJECTS)
|
||||
.endif
|
||||
@ rename $(GLU_LIB)* $(LIBDIR)
|
||||
|
||||
clean :
|
||||
delete *.obj;*
|
||||
purge
|
||||
|
||||
include mms_depend.
|
||||
|
||||
@@ -1,416 +0,0 @@
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
GLdouble m[16];
|
||||
GLdouble x[3], y[3], z[3];
|
||||
GLdouble 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
|
||||
glMultMatrixd(m);
|
||||
|
||||
/* Translate Eye to Origin */
|
||||
glTranslated(-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(GLdouble left, GLdouble right,
|
||||
GLdouble bottom, GLdouble top,
|
||||
GLdouble nearval, GLdouble farval)
|
||||
{
|
||||
GLdouble x, y, a, b, c, d;
|
||||
GLdouble 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
|
||||
|
||||
glMultMatrixd(m);
|
||||
}
|
||||
|
||||
|
||||
void GLAPIENTRY
|
||||
gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar)
|
||||
{
|
||||
GLdouble 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
|
||||
@@ -1,97 +0,0 @@
|
||||
/*
|
||||
* Mesa 3-D graphics library
|
||||
* Version: 6.3
|
||||
* Copyright (C) 1995-2004 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
|
||||
# define GLCALLBACK __stdcall
|
||||
# if defined(__CYGWIN__)
|
||||
# define GLCALLBACKPCAST *
|
||||
# else
|
||||
# define GLCALLBACKPCAST __stdcall *
|
||||
# endif
|
||||
#else
|
||||
/* non-Windows compilation */
|
||||
# define GLCALLBACK
|
||||
# define GLCALLBACKPCAST *
|
||||
#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
|
||||
#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
|
||||
@@ -1,824 +0,0 @@
|
||||
|
||||
/*
|
||||
* 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;
|
||||
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 */
|
||||
glGetIntegerv(GL_UNPACK_ROW_LENGTH, &unpackrowlength);
|
||||
glGetIntegerv(GL_UNPACK_ALIGNMENT, &unpackalignment);
|
||||
glGetIntegerv(GL_UNPACK_SKIP_ROWS, &unpackskiprows);
|
||||
glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &unpackskippixels);
|
||||
glGetIntegerv(GL_PACK_ROW_LENGTH, &packrowlength);
|
||||
glGetIntegerv(GL_PACK_ALIGNMENT, &packalignment);
|
||||
glGetIntegerv(GL_PACK_SKIP_ROWS, &packskiprows);
|
||||
glGetIntegerv(GL_PACK_SKIP_PIXELS, &packskippixels);
|
||||
|
||||
/* 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)
|
||||
{
|
||||
GLubyte *texture;
|
||||
GLint levels, max_levels;
|
||||
GLint new_width, max_width;
|
||||
GLint i, j, k, l;
|
||||
|
||||
if (width < 1)
|
||||
return GLU_INVALID_VALUE;
|
||||
|
||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_width);
|
||||
max_levels = ilog2(max_width) + 1;
|
||||
|
||||
/* Compute how many mipmap images to make */
|
||||
levels = ilog2(width) + 1;
|
||||
if (levels > max_levels) {
|
||||
levels = max_levels;
|
||||
}
|
||||
|
||||
new_width = 1 << (levels - 1);
|
||||
|
||||
texture = (GLubyte *) malloc(new_width * components);
|
||||
if (!texture) {
|
||||
return GLU_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if (width != new_width) {
|
||||
/* initial rescaling */
|
||||
switch (type) {
|
||||
case GL_UNSIGNED_BYTE:
|
||||
{
|
||||
GLubyte *ub_data = (GLubyte *) data;
|
||||
for (i = 0; i < new_width; i++) {
|
||||
j = i * width / new_width;
|
||||
for (k = 0; k < components; k++) {
|
||||
texture[i * components + k] = ub_data[j * components + k];
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* Not implemented */
|
||||
return GLU_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* generate and load mipmap images */
|
||||
for (l = 0; l < levels; l++) {
|
||||
glTexImage1D(GL_TEXTURE_1D, l, components, new_width, 0,
|
||||
format, GL_UNSIGNED_BYTE, texture);
|
||||
|
||||
/* Scale image down to 1/2 size */
|
||||
new_width = new_width / 2;
|
||||
for (i = 0; i < new_width; i++) {
|
||||
for (k = 0; k < components; k++) {
|
||||
GLint sample1, sample2;
|
||||
sample1 = (GLint) texture[i * 2 * components + k];
|
||||
sample2 = (GLint) texture[(i * 2 + 1) * components + k];
|
||||
texture[i * components + k] = (GLubyte) ((sample1 + sample2) / 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(texture);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
GLint GLAPIENTRY
|
||||
gluBuild2DMipmaps(GLenum target, GLint components,
|
||||
GLsizei width, GLsizei height, GLenum format,
|
||||
GLenum type, const void *data)
|
||||
{
|
||||
GLint w, h, 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;
|
||||
|
||||
if (width < 1 || height < 1)
|
||||
return GLU_INVALID_VALUE;
|
||||
|
||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxsize);
|
||||
|
||||
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 */
|
||||
glGetIntegerv(GL_UNPACK_ROW_LENGTH, &unpackrowlength);
|
||||
glGetIntegerv(GL_UNPACK_ALIGNMENT, &unpackalignment);
|
||||
glGetIntegerv(GL_UNPACK_SKIP_ROWS, &unpackskiprows);
|
||||
glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &unpackskippixels);
|
||||
glGetIntegerv(GL_PACK_ROW_LENGTH, &packrowlength);
|
||||
glGetIntegerv(GL_PACK_ALIGNMENT, &packalignment);
|
||||
glGetIntegerv(GL_PACK_SKIP_ROWS, &packskiprows);
|
||||
glGetIntegerv(GL_PACK_SKIP_PIXELS, &packskippixels);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
|
||||
glu.obj : gluP.h [-.include.gl]gl.h [-.include.gl]glu.h
|
||||
mipmap.obj : gluP.h [-.include.gl]gl.h [-.include.gl]glu.h
|
||||
nurbs.obj : gluP.h [-.include.gl]gl.h [-.include.gl]glu.h nurbs.h
|
||||
nurbscrv.obj : nurbs.h gluP.h [-.include.gl]gl.h [-.include.gl]glu.h
|
||||
nurbssrf.obj : gluP.h [-.include.gl]gl.h [-.include.gl]glu.h nurbs.h
|
||||
nurbsutl.obj : gluP.h [-.include.gl]gl.h [-.include.gl]glu.h nurbs.h
|
||||
project.obj : gluP.h [-.include.gl]gl.h [-.include.gl]glu.h
|
||||
quadric.obj : gluP.h [-.include.gl]gl.h [-.include.gl]glu.h
|
||||
tess.obj : gluP.h [-.include.gl]gl.h [-.include.gl]glu.h tess.h
|
||||
tess_fist.obj : gluP.h [-.include.gl]gl.h [-.include.gl]glu.h tess.h
|
||||
tess_hash.obj : gluP.h [-.include.gl]gl.h [-.include.gl]glu.h tess.h
|
||||
tess_heap.obj : gluP.h [-.include.gl]gl.h [-.include.gl]glu.h tess.h
|
||||
tess_clip.obj : gluP.h [-.include.gl]gl.h [-.include.gl]glu.h tess.h
|
||||
@@ -1,628 +0,0 @@
|
||||
|
||||
/*
|
||||
* 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));
|
||||
if (n) {
|
||||
/* init */
|
||||
n->culling = GL_FALSE;
|
||||
n->nurbs_type = GLU_NURBS_NONE;
|
||||
n->error = GLU_NO_ERROR;
|
||||
n->error_callback = NULL;
|
||||
n->auto_load_matrix = GL_TRUE;
|
||||
n->sampling_tolerance = 50.0;
|
||||
n->parametric_tolerance = 0.5;
|
||||
n->u_step = n->v_step = 100;
|
||||
n->sampling_method = GLU_PATH_LENGTH;
|
||||
n->display_mode = GLU_FILL;
|
||||
/* in case the user doesn't supply the sampling matrices */
|
||||
/* set projection and modelview to identity */
|
||||
for (i = 0; i < 4; i++)
|
||||
for (j = 0; j < 4; j++)
|
||||
if (i == j) {
|
||||
n->sampling_matrices.model[i * 4 + j] = 1.0;
|
||||
n->sampling_matrices.proj[i * 4 + j] = 1.0;
|
||||
}
|
||||
else {
|
||||
n->sampling_matrices.model[i * 4 + j] = 0.0;
|
||||
n->sampling_matrices.proj[i * 4 + j] = 0.0;
|
||||
}
|
||||
/* and set the viewport sampling matrix to current ciewport */
|
||||
glGetFloatv(GL_VIEWPORT, tmp_viewport);
|
||||
for (i = 0; i < 4; i++)
|
||||
n->sampling_matrices.viewport[i] = tmp_viewport[i];
|
||||
n->trim = NULL;
|
||||
}
|
||||
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])
|
||||
{
|
||||
GLint i;
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
nobj->sampling_matrices.model[i] = modelMatrix[i];
|
||||
nobj->sampling_matrices.proj[i] = projMatrix[i];
|
||||
}
|
||||
for (i = 0; i < 4; i++)
|
||||
nobj->sampling_matrices.viewport[i] = viewport[i];
|
||||
}
|
||||
|
||||
|
||||
void GLAPIENTRY
|
||||
gluNurbsProperty(GLUnurbsObj * nobj, GLenum property, GLfloat value)
|
||||
{
|
||||
GLenum val;
|
||||
|
||||
switch (property) {
|
||||
case GLU_SAMPLING_TOLERANCE:
|
||||
if (value <= 0.0) {
|
||||
call_user_error(nobj, GLU_INVALID_VALUE);
|
||||
return;
|
||||
}
|
||||
nobj->sampling_tolerance = value;
|
||||
break;
|
||||
case GLU_PARAMETRIC_TOLERANCE:
|
||||
if (value <= 0.0) {
|
||||
call_user_error(nobj, GLU_INVALID_VALUE);
|
||||
return;
|
||||
}
|
||||
nobj->parametric_tolerance = value;
|
||||
break;
|
||||
case GLU_U_STEP:
|
||||
if (value <= 0.0) {
|
||||
call_user_error(nobj, GLU_INVALID_VALUE);
|
||||
return;
|
||||
}
|
||||
nobj->u_step = (GLint) value;
|
||||
break;
|
||||
case GLU_V_STEP:
|
||||
if (value <= 0.0) {
|
||||
call_user_error(nobj, GLU_INVALID_VALUE);
|
||||
return;
|
||||
}
|
||||
nobj->v_step = (GLint) value;
|
||||
break;
|
||||
case GLU_SAMPLING_METHOD:
|
||||
val = (GLenum) value;
|
||||
if (val != GLU_PATH_LENGTH && val != GLU_PARAMETRIC_ERROR
|
||||
&& val != GLU_DOMAIN_DISTANCE) {
|
||||
call_user_error(nobj, GLU_INVALID_ENUM);
|
||||
return;
|
||||
}
|
||||
nobj->sampling_method = val;
|
||||
break;
|
||||
case GLU_DISPLAY_MODE:
|
||||
val = (GLenum) value;
|
||||
if (val != GLU_FILL && val != GLU_OUTLINE_POLYGON
|
||||
&& val != GLU_OUTLINE_PATCH) {
|
||||
call_user_error(nobj, GLU_INVALID_ENUM);
|
||||
return;
|
||||
}
|
||||
if (nobj->nurbs_type == GLU_NURBS_CURVE) {
|
||||
call_user_error(nobj, GLU_NURBS_ERROR26);
|
||||
return;
|
||||
}
|
||||
nobj->display_mode = val;
|
||||
if (val == GLU_OUTLINE_PATCH)
|
||||
fprintf(stderr,
|
||||
"NURBS, for the moment, can display only in POLYGON mode\n");
|
||||
break;
|
||||
case GLU_CULLING:
|
||||
val = (GLenum) value;
|
||||
if (val != GL_TRUE && val != GL_FALSE) {
|
||||
call_user_error(nobj, GLU_INVALID_ENUM);
|
||||
return;
|
||||
}
|
||||
nobj->culling = (GLboolean) value;
|
||||
break;
|
||||
case GLU_AUTO_LOAD_MATRIX:
|
||||
val = (GLenum) value;
|
||||
if (val != GL_TRUE && val != GL_FALSE) {
|
||||
call_user_error(nobj, GLU_INVALID_ENUM);
|
||||
return;
|
||||
}
|
||||
nobj->auto_load_matrix = (GLboolean) value;
|
||||
break;
|
||||
default:
|
||||
call_user_error(nobj, GLU_NURBS_ERROR26);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GLAPIENTRY
|
||||
gluGetNurbsProperty(GLUnurbsObj * nobj, GLenum property, GLfloat * value)
|
||||
{
|
||||
switch (property) {
|
||||
case GLU_SAMPLING_TOLERANCE:
|
||||
*value = nobj->sampling_tolerance;
|
||||
break;
|
||||
case GLU_DISPLAY_MODE:
|
||||
*value = (GLfloat) (GLint) nobj->display_mode;
|
||||
break;
|
||||
case GLU_CULLING:
|
||||
*value = nobj->culling ? 1.0 : 0.0;
|
||||
break;
|
||||
case GLU_AUTO_LOAD_MATRIX:
|
||||
*value = nobj->auto_load_matrix ? 1.0 : 0.0;
|
||||
break;
|
||||
default:
|
||||
call_user_error(nobj, GLU_INVALID_ENUM);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GLAPIENTRY
|
||||
gluBeginCurve(GLUnurbsObj * nobj)
|
||||
{
|
||||
if (nobj->nurbs_type == GLU_NURBS_CURVE) {
|
||||
call_user_error(nobj, GLU_NURBS_ERROR6);
|
||||
return;
|
||||
}
|
||||
nobj->nurbs_type = GLU_NURBS_CURVE;
|
||||
nobj->curve.geom.type = GLU_INVALID_ENUM;
|
||||
nobj->curve.color.type = GLU_INVALID_ENUM;
|
||||
nobj->curve.texture.type = GLU_INVALID_ENUM;
|
||||
nobj->curve.normal.type = GLU_INVALID_ENUM;
|
||||
}
|
||||
|
||||
|
||||
void GLAPIENTRY
|
||||
gluEndCurve(GLUnurbsObj * nobj)
|
||||
{
|
||||
if (nobj->nurbs_type == GLU_NURBS_NONE) {
|
||||
call_user_error(nobj, GLU_NURBS_ERROR7);
|
||||
return;
|
||||
}
|
||||
if (nobj->curve.geom.type == GLU_INVALID_ENUM) {
|
||||
call_user_error(nobj, GLU_NURBS_ERROR8);
|
||||
nobj->nurbs_type = GLU_NURBS_NONE;
|
||||
return;
|
||||
}
|
||||
glPushAttrib((GLbitfield) (GL_EVAL_BIT | GL_ENABLE_BIT));
|
||||
glDisable(GL_MAP1_VERTEX_3);
|
||||
glDisable(GL_MAP1_VERTEX_4);
|
||||
glDisable(GL_MAP1_INDEX);
|
||||
glDisable(GL_MAP1_COLOR_4);
|
||||
glDisable(GL_MAP1_NORMAL);
|
||||
glDisable(GL_MAP1_TEXTURE_COORD_1);
|
||||
glDisable(GL_MAP1_TEXTURE_COORD_2);
|
||||
glDisable(GL_MAP1_TEXTURE_COORD_3);
|
||||
glDisable(GL_MAP1_TEXTURE_COORD_4);
|
||||
glDisable(GL_MAP2_VERTEX_3);
|
||||
glDisable(GL_MAP2_VERTEX_4);
|
||||
glDisable(GL_MAP2_INDEX);
|
||||
glDisable(GL_MAP2_COLOR_4);
|
||||
glDisable(GL_MAP2_NORMAL);
|
||||
glDisable(GL_MAP2_TEXTURE_COORD_1);
|
||||
glDisable(GL_MAP2_TEXTURE_COORD_2);
|
||||
glDisable(GL_MAP2_TEXTURE_COORD_3);
|
||||
glDisable(GL_MAP2_TEXTURE_COORD_4);
|
||||
do_nurbs_curve(nobj);
|
||||
glPopAttrib();
|
||||
nobj->nurbs_type = GLU_NURBS_NONE;
|
||||
}
|
||||
|
||||
|
||||
void GLAPIENTRY
|
||||
gluNurbsCurve(GLUnurbsObj * nobj, GLint nknots, GLfloat * knot,
|
||||
GLint stride, GLfloat * ctlarray, GLint order, GLenum type)
|
||||
{
|
||||
if (nobj->nurbs_type == GLU_NURBS_TRIM) {
|
||||
#if 0
|
||||
/* TODO: NOT IMPLEMENTED YET */
|
||||
nurbs_trim *ptr1;
|
||||
trim_list *ptr2;
|
||||
|
||||
if (type != GLU_MAP1_TRIM_2 && type != GLU_MAP1_TRIM_3) {
|
||||
call_user_error(nobj, GLU_NURBS_ERROR14);
|
||||
return;
|
||||
}
|
||||
for (ptr1 = nobj->trim; ptr1->next; ptr1 = ptr1->next);
|
||||
if (ptr1->trim_loop) {
|
||||
for (ptr2 = ptr1->trim_loop; ptr2->next; ptr2 = ptr2->next);
|
||||
if ((ptr2->next = (trim_list *) malloc(sizeof(trim_list))) == NULL) {
|
||||
call_user_error(nobj, GLU_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
ptr2 = ptr2->next;
|
||||
}
|
||||
else {
|
||||
if ((ptr2 = (trim_list *) malloc(sizeof(trim_list))) == NULL) {
|
||||
call_user_error(nobj, GLU_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
ptr1->trim_loop = ptr2;
|
||||
}
|
||||
ptr2->trim_type = GLU_TRIM_NURBS;
|
||||
ptr2->curve.nurbs_curve.knot_count = nknots;
|
||||
ptr2->curve.nurbs_curve.knot = knot;
|
||||
ptr2->curve.nurbs_curve.stride = stride;
|
||||
ptr2->curve.nurbs_curve.ctrlarray = ctlarray;
|
||||
ptr2->curve.nurbs_curve.order = order;
|
||||
ptr2->curve.nurbs_curve.dim = (type == GLU_MAP1_TRIM_2 ? 2 : 3);
|
||||
ptr2->curve.nurbs_curve.type = type;
|
||||
ptr2->next = NULL;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
if (type == GLU_MAP1_TRIM_2 || type == GLU_MAP1_TRIM_3) {
|
||||
call_user_error(nobj, GLU_NURBS_ERROR22);
|
||||
return;
|
||||
}
|
||||
if (nobj->nurbs_type != GLU_NURBS_CURVE) {
|
||||
call_user_error(nobj, GLU_NURBS_ERROR10);
|
||||
return;
|
||||
}
|
||||
switch (type) {
|
||||
case GL_MAP1_VERTEX_3:
|
||||
case GL_MAP1_VERTEX_4:
|
||||
if (nobj->curve.geom.type != GLU_INVALID_ENUM) {
|
||||
call_user_error(nobj, GLU_NURBS_ERROR8);
|
||||
return;
|
||||
}
|
||||
nobj->curve.geom.type = type;
|
||||
nobj->curve.geom.knot_count = nknots;
|
||||
nobj->curve.geom.knot = knot;
|
||||
nobj->curve.geom.stride = stride;
|
||||
nobj->curve.geom.ctrlarray = ctlarray;
|
||||
nobj->curve.geom.order = order;
|
||||
break;
|
||||
case GL_MAP1_INDEX:
|
||||
case GL_MAP1_COLOR_4:
|
||||
nobj->curve.color.type = type;
|
||||
nobj->curve.color.knot_count = nknots;
|
||||
nobj->curve.color.knot = knot;
|
||||
nobj->curve.color.stride = stride;
|
||||
nobj->curve.color.ctrlarray = ctlarray;
|
||||
nobj->curve.color.order = order;
|
||||
break;
|
||||
case GL_MAP1_NORMAL:
|
||||
nobj->curve.normal.type = type;
|
||||
nobj->curve.normal.knot_count = nknots;
|
||||
nobj->curve.normal.knot = knot;
|
||||
nobj->curve.normal.stride = stride;
|
||||
nobj->curve.normal.ctrlarray = ctlarray;
|
||||
nobj->curve.normal.order = order;
|
||||
break;
|
||||
case GL_MAP1_TEXTURE_COORD_1:
|
||||
case GL_MAP1_TEXTURE_COORD_2:
|
||||
case GL_MAP1_TEXTURE_COORD_3:
|
||||
case GL_MAP1_TEXTURE_COORD_4:
|
||||
nobj->curve.texture.type = type;
|
||||
nobj->curve.texture.knot_count = nknots;
|
||||
nobj->curve.texture.knot = knot;
|
||||
nobj->curve.texture.stride = stride;
|
||||
nobj->curve.texture.ctrlarray = ctlarray;
|
||||
nobj->curve.texture.order = order;
|
||||
break;
|
||||
default:
|
||||
call_user_error(nobj, GLU_INVALID_ENUM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GLAPIENTRY
|
||||
gluBeginSurface(GLUnurbsObj * nobj)
|
||||
{
|
||||
switch (nobj->nurbs_type) {
|
||||
case GLU_NURBS_NONE:
|
||||
nobj->nurbs_type = GLU_NURBS_SURFACE;
|
||||
nobj->surface.geom.type = GLU_INVALID_ENUM;
|
||||
nobj->surface.color.type = GLU_INVALID_ENUM;
|
||||
nobj->surface.texture.type = GLU_INVALID_ENUM;
|
||||
nobj->surface.normal.type = GLU_INVALID_ENUM;
|
||||
break;
|
||||
case GLU_NURBS_TRIM:
|
||||
call_user_error(nobj, GLU_NURBS_ERROR16);
|
||||
break;
|
||||
case GLU_NURBS_SURFACE:
|
||||
case GLU_NURBS_NO_TRIM:
|
||||
case GLU_NURBS_TRIM_DONE:
|
||||
call_user_error(nobj, GLU_NURBS_ERROR27);
|
||||
break;
|
||||
case GLU_NURBS_CURVE:
|
||||
call_user_error(nobj, GLU_NURBS_ERROR6);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GLAPIENTRY
|
||||
gluEndSurface(GLUnurbsObj * nobj)
|
||||
{
|
||||
switch (nobj->nurbs_type) {
|
||||
case GLU_NURBS_NONE:
|
||||
call_user_error(nobj, GLU_NURBS_ERROR13);
|
||||
break;
|
||||
case GLU_NURBS_TRIM:
|
||||
call_user_error(nobj, GLU_NURBS_ERROR12);
|
||||
break;
|
||||
case GLU_NURBS_TRIM_DONE:
|
||||
/* if(nobj->trim->trim_loop==NULL)
|
||||
{
|
||||
call_user_error(nobj,GLU_NURBS_ERROR18);
|
||||
return;
|
||||
}*/
|
||||
/* no break - fallthrough */
|
||||
case GLU_NURBS_NO_TRIM:
|
||||
glPushAttrib((GLbitfield)
|
||||
(GL_EVAL_BIT | GL_ENABLE_BIT | GL_POLYGON_BIT));
|
||||
glDisable(GL_MAP2_VERTEX_3);
|
||||
glDisable(GL_MAP2_VERTEX_4);
|
||||
glDisable(GL_MAP2_INDEX);
|
||||
glDisable(GL_MAP2_COLOR_4);
|
||||
glDisable(GL_MAP2_NORMAL);
|
||||
glDisable(GL_MAP2_TEXTURE_COORD_1);
|
||||
glDisable(GL_MAP2_TEXTURE_COORD_2);
|
||||
glDisable(GL_MAP2_TEXTURE_COORD_3);
|
||||
glDisable(GL_MAP2_TEXTURE_COORD_4);
|
||||
/* glDisable(GL_MAP1_VERTEX_3);
|
||||
glDisable(GL_MAP1_VERTEX_4);
|
||||
glDisable(GL_MAP1_INDEX);
|
||||
glDisable(GL_MAP1_COLOR_4);
|
||||
glDisable(GL_MAP1_NORMAL);
|
||||
glDisable(GL_MAP1_TEXTURE_COORD_1);
|
||||
glDisable(GL_MAP1_TEXTURE_COORD_2);
|
||||
glDisable(GL_MAP1_TEXTURE_COORD_3);
|
||||
glDisable(GL_MAP1_TEXTURE_COORD_4);*/
|
||||
do_nurbs_surface(nobj);
|
||||
glPopAttrib();
|
||||
break;
|
||||
default:
|
||||
call_user_error(nobj, GLU_NURBS_ERROR8);
|
||||
}
|
||||
nobj->nurbs_type = GLU_NURBS_NONE;
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
if (nobj->nurbs_type == GLU_NURBS_NO_TRIM
|
||||
|| nobj->nurbs_type == GLU_NURBS_TRIM
|
||||
|| nobj->nurbs_type == GLU_NURBS_TRIM_DONE) {
|
||||
if (type == GL_MAP2_VERTEX_3 || type == GL_MAP2_VERTEX_4) {
|
||||
call_user_error(nobj, GLU_NURBS_ERROR8);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (nobj->nurbs_type != GLU_NURBS_SURFACE) {
|
||||
call_user_error(nobj, GLU_NURBS_ERROR11);
|
||||
return;
|
||||
}
|
||||
switch (type) {
|
||||
case GL_MAP2_VERTEX_3:
|
||||
case GL_MAP2_VERTEX_4:
|
||||
nobj->surface.geom.sknot_count = sknot_count;
|
||||
nobj->surface.geom.sknot = sknot;
|
||||
nobj->surface.geom.tknot_count = tknot_count;
|
||||
nobj->surface.geom.tknot = tknot;
|
||||
nobj->surface.geom.s_stride = s_stride;
|
||||
nobj->surface.geom.t_stride = t_stride;
|
||||
nobj->surface.geom.ctrlarray = ctrlarray;
|
||||
nobj->surface.geom.sorder = sorder;
|
||||
nobj->surface.geom.torder = torder;
|
||||
nobj->surface.geom.type = type;
|
||||
nobj->nurbs_type = GLU_NURBS_NO_TRIM;
|
||||
break;
|
||||
case GL_MAP2_INDEX:
|
||||
case GL_MAP2_COLOR_4:
|
||||
nobj->surface.color.sknot_count = sknot_count;
|
||||
nobj->surface.color.sknot = sknot;
|
||||
nobj->surface.color.tknot_count = tknot_count;
|
||||
nobj->surface.color.tknot = tknot;
|
||||
nobj->surface.color.s_stride = s_stride;
|
||||
nobj->surface.color.t_stride = t_stride;
|
||||
nobj->surface.color.ctrlarray = ctrlarray;
|
||||
nobj->surface.color.sorder = sorder;
|
||||
nobj->surface.color.torder = torder;
|
||||
nobj->surface.color.type = type;
|
||||
break;
|
||||
case GL_MAP2_NORMAL:
|
||||
nobj->surface.normal.sknot_count = sknot_count;
|
||||
nobj->surface.normal.sknot = sknot;
|
||||
nobj->surface.normal.tknot_count = tknot_count;
|
||||
nobj->surface.normal.tknot = tknot;
|
||||
nobj->surface.normal.s_stride = s_stride;
|
||||
nobj->surface.normal.t_stride = t_stride;
|
||||
nobj->surface.normal.ctrlarray = ctrlarray;
|
||||
nobj->surface.normal.sorder = sorder;
|
||||
nobj->surface.normal.torder = torder;
|
||||
nobj->surface.normal.type = type;
|
||||
break;
|
||||
case GL_MAP2_TEXTURE_COORD_1:
|
||||
case GL_MAP2_TEXTURE_COORD_2:
|
||||
case GL_MAP2_TEXTURE_COORD_3:
|
||||
case GL_MAP2_TEXTURE_COORD_4:
|
||||
nobj->surface.texture.sknot_count = sknot_count;
|
||||
nobj->surface.texture.sknot = sknot;
|
||||
nobj->surface.texture.tknot_count = tknot_count;
|
||||
nobj->surface.texture.tknot = tknot;
|
||||
nobj->surface.texture.s_stride = s_stride;
|
||||
nobj->surface.texture.t_stride = t_stride;
|
||||
nobj->surface.texture.ctrlarray = ctrlarray;
|
||||
nobj->surface.texture.sorder = sorder;
|
||||
nobj->surface.texture.torder = torder;
|
||||
nobj->surface.texture.type = type;
|
||||
break;
|
||||
default:
|
||||
call_user_error(nobj, GLU_INVALID_ENUM);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GLAPIENTRY
|
||||
gluNurbsCallback(GLUnurbsObj * nobj, GLenum which, void (GLCALLBACK * fn) ())
|
||||
{
|
||||
nobj->error_callback = (void (GLCALLBACKPCAST) (GLenum)) fn;
|
||||
|
||||
if (which != GLU_ERROR)
|
||||
call_user_error(nobj, GLU_INVALID_ENUM);
|
||||
}
|
||||
|
||||
void GLAPIENTRY
|
||||
gluBeginTrim(GLUnurbsObj * nobj)
|
||||
{
|
||||
#if 0
|
||||
nurbs_trim *ptr;
|
||||
#endif
|
||||
|
||||
if (nobj->nurbs_type != GLU_NURBS_TRIM_DONE)
|
||||
if (nobj->nurbs_type != GLU_NURBS_NO_TRIM) {
|
||||
call_user_error(nobj, GLU_NURBS_ERROR15);
|
||||
return;
|
||||
}
|
||||
nobj->nurbs_type = GLU_NURBS_TRIM;
|
||||
fprintf(stderr, "NURBS - trimming not supported yet\n");
|
||||
#if 0
|
||||
if ((ptr = (nurbs_trim *) malloc(sizeof(nurbs_trim))) == NULL) {
|
||||
call_user_error(nobj, GLU_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
if (nobj->trim) {
|
||||
nurbs_trim *tmp_ptr;
|
||||
|
||||
for (tmp_ptr = nobj->trim; tmp_ptr->next; tmp_ptr = tmp_ptr->next);
|
||||
tmp_ptr->next = ptr;
|
||||
}
|
||||
else
|
||||
nobj->trim = ptr;
|
||||
ptr->trim_loop = NULL;
|
||||
ptr->segments = NULL;
|
||||
ptr->next = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
void GLAPIENTRY
|
||||
gluPwlCurve(GLUnurbsObj * nobj, GLint count, GLfloat * array, GLint stride,
|
||||
GLenum type)
|
||||
{
|
||||
#if 0
|
||||
nurbs_trim *ptr1;
|
||||
trim_list *ptr2;
|
||||
#endif
|
||||
if (nobj->nurbs_type == GLU_NURBS_CURVE) {
|
||||
call_user_error(nobj, GLU_NURBS_ERROR9);
|
||||
return;
|
||||
}
|
||||
if (nobj->nurbs_type == GLU_NURBS_NONE) {
|
||||
call_user_error(nobj, GLU_NURBS_ERROR19);
|
||||
return;
|
||||
}
|
||||
if (type != GLU_MAP1_TRIM_2 && type != GLU_MAP1_TRIM_3) {
|
||||
call_user_error(nobj, GLU_NURBS_ERROR14);
|
||||
return;
|
||||
}
|
||||
#if 0
|
||||
for (ptr1 = nobj->trim; ptr1->next; ptr1 = ptr1->next);
|
||||
if (ptr1->trim_loop) {
|
||||
for (ptr2 = ptr1->trim_loop; ptr2->next; ptr2 = ptr2->next);
|
||||
if ((ptr2->next = (trim_list *) malloc(sizeof(trim_list))) == NULL) {
|
||||
call_user_error(nobj, GLU_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
ptr2 = ptr2->next;
|
||||
}
|
||||
else {
|
||||
if ((ptr2 = (trim_list *) malloc(sizeof(trim_list))) == NULL) {
|
||||
call_user_error(nobj, GLU_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
ptr1->trim_loop = ptr2;
|
||||
}
|
||||
ptr2->trim_type = GLU_TRIM_PWL;
|
||||
ptr2->curve.pwl_curve.pt_count = count;
|
||||
ptr2->curve.pwl_curve.ctrlarray = array;
|
||||
ptr2->curve.pwl_curve.stride = stride;
|
||||
ptr2->curve.pwl_curve.dim = (type == GLU_MAP1_TRIM_2 ? 2 : 3);
|
||||
ptr2->curve.pwl_curve.type = type;
|
||||
ptr2->next = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
void GLAPIENTRY
|
||||
gluEndTrim(GLUnurbsObj * nobj)
|
||||
{
|
||||
if (nobj->nurbs_type != GLU_NURBS_TRIM) {
|
||||
call_user_error(nobj, GLU_NURBS_ERROR17);
|
||||
return;
|
||||
}
|
||||
nobj->nurbs_type = GLU_NURBS_TRIM_DONE;
|
||||
}
|
||||
@@ -1,252 +0,0 @@
|
||||
|
||||
/*
|
||||
* 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
|
||||
@@ -1,444 +0,0 @@
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
||||
|
||||
static int
|
||||
get_curve_dim(GLenum type)
|
||||
{
|
||||
switch (type) {
|
||||
case GL_MAP1_VERTEX_3:
|
||||
return 3;
|
||||
case GL_MAP1_VERTEX_4:
|
||||
return 4;
|
||||
case GL_MAP1_INDEX:
|
||||
return 1;
|
||||
case GL_MAP1_COLOR_4:
|
||||
return 4;
|
||||
case GL_MAP1_NORMAL:
|
||||
return 3;
|
||||
case GL_MAP1_TEXTURE_COORD_1:
|
||||
return 1;
|
||||
case GL_MAP1_TEXTURE_COORD_2:
|
||||
return 2;
|
||||
case GL_MAP1_TEXTURE_COORD_3:
|
||||
return 3;
|
||||
case GL_MAP1_TEXTURE_COORD_4:
|
||||
return 4;
|
||||
default:
|
||||
abort(); /* TODO: is this OK? */
|
||||
}
|
||||
return 0; /*never get here */
|
||||
}
|
||||
|
||||
static GLenum
|
||||
test_nurbs_curve(GLUnurbsObj * nobj, curve_attribs * attribs)
|
||||
{
|
||||
GLenum err;
|
||||
GLint tmp_int;
|
||||
|
||||
if (attribs->order < 0) {
|
||||
call_user_error(nobj, GLU_INVALID_VALUE);
|
||||
return GLU_ERROR;
|
||||
}
|
||||
glGetIntegerv(GL_MAX_EVAL_ORDER, &tmp_int);
|
||||
if (attribs->order > tmp_int || attribs->order < 2) {
|
||||
call_user_error(nobj, GLU_NURBS_ERROR1);
|
||||
return GLU_ERROR;
|
||||
}
|
||||
if (attribs->knot_count < attribs->order + 2) {
|
||||
call_user_error(nobj, GLU_NURBS_ERROR2);
|
||||
return GLU_ERROR;
|
||||
}
|
||||
if (attribs->stride < 0) {
|
||||
call_user_error(nobj, GLU_NURBS_ERROR34);
|
||||
return GLU_ERROR;
|
||||
}
|
||||
if (attribs->knot == NULL || attribs->ctrlarray == NULL) {
|
||||
call_user_error(nobj, GLU_NURBS_ERROR36);
|
||||
return GLU_ERROR;
|
||||
}
|
||||
if ((err = test_knot(attribs->knot_count, attribs->knot, attribs->order))
|
||||
!= GLU_NO_ERROR) {
|
||||
call_user_error(nobj, err);
|
||||
return GLU_ERROR;
|
||||
}
|
||||
return GLU_NO_ERROR;
|
||||
}
|
||||
|
||||
static GLenum
|
||||
test_nurbs_curves(GLUnurbsObj * nobj)
|
||||
{
|
||||
/* test the geometric data */
|
||||
if (test_nurbs_curve(nobj, &(nobj->curve.geom)) != GLU_NO_ERROR)
|
||||
return GLU_ERROR;
|
||||
/* now test the attributive data */
|
||||
/* color */
|
||||
if (nobj->curve.color.type != GLU_INVALID_ENUM)
|
||||
if (test_nurbs_curve(nobj, &(nobj->curve.color)) != GLU_NO_ERROR)
|
||||
return GLU_ERROR;
|
||||
/* normal */
|
||||
if (nobj->curve.normal.type != GLU_INVALID_ENUM)
|
||||
if (test_nurbs_curve(nobj, &(nobj->curve.normal)) != GLU_NO_ERROR)
|
||||
return GLU_ERROR;
|
||||
/* texture */
|
||||
if (nobj->curve.texture.type != GLU_INVALID_ENUM)
|
||||
if (test_nurbs_curve(nobj, &(nobj->curve.texture)) != GLU_NO_ERROR)
|
||||
return GLU_ERROR;
|
||||
return GLU_NO_ERROR;
|
||||
}
|
||||
|
||||
/* prepare the knot information structures */
|
||||
static GLenum
|
||||
fill_knot_structures(GLUnurbsObj * nobj, knot_str_type * geom_knot,
|
||||
knot_str_type * color_knot, knot_str_type * normal_knot,
|
||||
knot_str_type * texture_knot)
|
||||
{
|
||||
GLint order;
|
||||
GLfloat *knot;
|
||||
GLint nknots;
|
||||
GLint t_min, t_max;
|
||||
|
||||
geom_knot->unified_knot = NULL;
|
||||
knot = geom_knot->knot = nobj->curve.geom.knot;
|
||||
nknots = geom_knot->nknots = nobj->curve.geom.knot_count;
|
||||
order = geom_knot->order = nobj->curve.geom.order;
|
||||
geom_knot->delta_nknots = 0;
|
||||
t_min = geom_knot->t_min = order - 1;
|
||||
t_max = geom_knot->t_max = nknots - order;
|
||||
if (fabs(knot[t_min] - knot[t_max]) < EPSILON) {
|
||||
call_user_error(nobj, GLU_NURBS_ERROR3);
|
||||
return GLU_ERROR;
|
||||
}
|
||||
if (fabs(knot[0] - knot[t_min]) < EPSILON) {
|
||||
/* knot open at beggining */
|
||||
geom_knot->open_at_begin = GL_TRUE;
|
||||
}
|
||||
else
|
||||
geom_knot->open_at_begin = GL_FALSE;
|
||||
if (fabs(knot[t_max] - knot[nknots - 1]) < EPSILON) {
|
||||
/* knot open at end */
|
||||
geom_knot->open_at_end = GL_TRUE;
|
||||
}
|
||||
else
|
||||
geom_knot->open_at_end = GL_FALSE;
|
||||
if (nobj->curve.color.type != GLU_INVALID_ENUM) {
|
||||
color_knot->unified_knot = (GLfloat *) 1;
|
||||
knot = color_knot->knot = nobj->curve.color.knot;
|
||||
nknots = color_knot->nknots = nobj->curve.color.knot_count;
|
||||
order = color_knot->order = nobj->curve.color.order;
|
||||
color_knot->delta_nknots = 0;
|
||||
t_min = color_knot->t_min = order - 1;
|
||||
t_max = color_knot->t_max = nknots - order;
|
||||
if (fabs(knot[t_min] - knot[t_max]) < EPSILON) {
|
||||
call_user_error(nobj, GLU_NURBS_ERROR3);
|
||||
return GLU_ERROR;
|
||||
}
|
||||
if (fabs(knot[0] - knot[t_min]) < EPSILON) {
|
||||
/* knot open at beggining */
|
||||
color_knot->open_at_begin = GL_TRUE;
|
||||
}
|
||||
else
|
||||
color_knot->open_at_begin = GL_FALSE;
|
||||
if (fabs(knot[t_max] - knot[nknots - 1]) < EPSILON) {
|
||||
/* knot open at end */
|
||||
color_knot->open_at_end = GL_TRUE;
|
||||
}
|
||||
else
|
||||
color_knot->open_at_end = GL_FALSE;
|
||||
}
|
||||
else
|
||||
color_knot->unified_knot = NULL;
|
||||
if (nobj->curve.normal.type != GLU_INVALID_ENUM) {
|
||||
normal_knot->unified_knot = (GLfloat *) 1;
|
||||
knot = normal_knot->knot = nobj->curve.normal.knot;
|
||||
nknots = normal_knot->nknots = nobj->curve.normal.knot_count;
|
||||
order = normal_knot->order = nobj->curve.normal.order;
|
||||
normal_knot->delta_nknots = 0;
|
||||
t_min = normal_knot->t_min = order - 1;
|
||||
t_max = normal_knot->t_max = nknots - order;
|
||||
if (fabs(knot[t_min] - knot[t_max]) < EPSILON) {
|
||||
call_user_error(nobj, GLU_NURBS_ERROR3);
|
||||
return GLU_ERROR;
|
||||
}
|
||||
if (fabs(knot[0] - knot[t_min]) < EPSILON) {
|
||||
/* knot open at beggining */
|
||||
normal_knot->open_at_begin = GL_TRUE;
|
||||
}
|
||||
else
|
||||
normal_knot->open_at_begin = GL_FALSE;
|
||||
if (fabs(knot[t_max] - knot[nknots - 1]) < EPSILON) {
|
||||
/* knot open at end */
|
||||
normal_knot->open_at_end = GL_TRUE;
|
||||
}
|
||||
else
|
||||
normal_knot->open_at_end = GL_FALSE;
|
||||
}
|
||||
else
|
||||
normal_knot->unified_knot = NULL;
|
||||
if (nobj->curve.texture.type != GLU_INVALID_ENUM) {
|
||||
texture_knot->unified_knot = (GLfloat *) 1;
|
||||
knot = texture_knot->knot = nobj->curve.texture.knot;
|
||||
nknots = texture_knot->nknots = nobj->curve.texture.knot_count;
|
||||
order = texture_knot->order = nobj->curve.texture.order;
|
||||
texture_knot->delta_nknots = 0;
|
||||
t_min = texture_knot->t_min = order - 1;
|
||||
t_max = texture_knot->t_max = nknots - order;
|
||||
if (fabs(knot[t_min] - knot[t_max]) < EPSILON) {
|
||||
call_user_error(nobj, GLU_NURBS_ERROR3);
|
||||
return GLU_ERROR;
|
||||
}
|
||||
if (fabs(knot[0] - knot[t_min]) < EPSILON) {
|
||||
/* knot open at beggining */
|
||||
texture_knot->open_at_begin = GL_TRUE;
|
||||
}
|
||||
else
|
||||
texture_knot->open_at_begin = GL_FALSE;
|
||||
if (fabs(knot[t_max] - knot[nknots - 1]) < EPSILON) {
|
||||
/* knot open at end */
|
||||
texture_knot->open_at_end = GL_TRUE;
|
||||
}
|
||||
else
|
||||
texture_knot->open_at_end = GL_FALSE;
|
||||
}
|
||||
else
|
||||
texture_knot->unified_knot = NULL;
|
||||
return GLU_NO_ERROR;
|
||||
}
|
||||
|
||||
/* covert the NURBS curve into a series of adjacent Bezier curves */
|
||||
static GLenum
|
||||
convert_curve(knot_str_type * the_knot, curve_attribs * attrib,
|
||||
GLfloat ** new_ctrl, GLint * ncontrol)
|
||||
{
|
||||
GLenum err;
|
||||
|
||||
if ((err = explode_knot(the_knot)) != GLU_NO_ERROR) {
|
||||
if (the_knot->unified_knot) {
|
||||
free(the_knot->unified_knot);
|
||||
the_knot->unified_knot = NULL;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
if (the_knot->unified_knot) {
|
||||
free(the_knot->unified_knot);
|
||||
the_knot->unified_knot = NULL;
|
||||
}
|
||||
if ((err = calc_alphas(the_knot)) != GLU_NO_ERROR) {
|
||||
free(the_knot->new_knot);
|
||||
return err;
|
||||
}
|
||||
free(the_knot->new_knot);
|
||||
if ((err = calc_new_ctrl_pts(attrib->ctrlarray, attrib->stride, the_knot,
|
||||
attrib->dim, new_ctrl, ncontrol))
|
||||
!= GLU_NO_ERROR) {
|
||||
free(the_knot->alpha);
|
||||
return err;
|
||||
}
|
||||
free(the_knot->alpha);
|
||||
return GLU_NO_ERROR;
|
||||
}
|
||||
|
||||
/* covert curves - geometry and possible attribute ones into equivalent */
|
||||
/* sequence of adjacent Bezier curves */
|
||||
static GLenum
|
||||
convert_curves(GLUnurbsObj * nobj, GLfloat ** new_geom_ctrl,
|
||||
GLint * ncontrol, GLfloat ** new_color_ctrl,
|
||||
GLfloat ** new_normal_ctrl, GLfloat ** new_texture_ctrl)
|
||||
{
|
||||
knot_str_type geom_knot, color_knot, normal_knot, texture_knot;
|
||||
GLint junk;
|
||||
GLenum err;
|
||||
|
||||
*new_color_ctrl = *new_normal_ctrl = *new_texture_ctrl = NULL;
|
||||
|
||||
if (fill_knot_structures(nobj, &geom_knot, &color_knot, &normal_knot,
|
||||
&texture_knot) != GLU_NO_ERROR)
|
||||
return GLU_ERROR;
|
||||
|
||||
/* unify knots - all knots should have the same number of working */
|
||||
/* ranges */
|
||||
if (
|
||||
(err =
|
||||
select_knot_working_range(nobj, &geom_knot, &color_knot, &normal_knot,
|
||||
&texture_knot)) != GLU_NO_ERROR) {
|
||||
return err;
|
||||
}
|
||||
/* convert the geometry curve */
|
||||
nobj->curve.geom.dim = get_curve_dim(nobj->curve.geom.type);
|
||||
if ((err = convert_curve(&geom_knot, &(nobj->curve.geom), new_geom_ctrl,
|
||||
ncontrol)) != GLU_NO_ERROR) {
|
||||
free_unified_knots(&geom_knot, &color_knot, &normal_knot,
|
||||
&texture_knot);
|
||||
call_user_error(nobj, err);
|
||||
return err;
|
||||
}
|
||||
/* if additional attributive curves are given convert them as well */
|
||||
if (color_knot.unified_knot) {
|
||||
nobj->curve.color.dim = get_curve_dim(nobj->curve.color.type);
|
||||
if ((err = convert_curve(&color_knot, &(nobj->curve.color),
|
||||
new_color_ctrl, &junk)) != GLU_NO_ERROR) {
|
||||
free_unified_knots(&geom_knot, &color_knot, &normal_knot,
|
||||
&texture_knot);
|
||||
free(*new_geom_ctrl);
|
||||
call_user_error(nobj, err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
if (normal_knot.unified_knot) {
|
||||
nobj->curve.normal.dim = get_curve_dim(nobj->curve.normal.type);
|
||||
if ((err = convert_curve(&normal_knot, &(nobj->curve.normal),
|
||||
new_normal_ctrl, &junk)) != GLU_NO_ERROR) {
|
||||
free_unified_knots(&geom_knot, &color_knot, &normal_knot,
|
||||
&texture_knot);
|
||||
free(*new_geom_ctrl);
|
||||
if (*new_color_ctrl)
|
||||
free(*new_color_ctrl);
|
||||
call_user_error(nobj, err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
if (texture_knot.unified_knot) {
|
||||
nobj->curve.texture.dim = get_curve_dim(nobj->curve.texture.type);
|
||||
if ((err = convert_curve(&texture_knot, &(nobj->curve.texture),
|
||||
new_texture_ctrl, &junk)) != GLU_NO_ERROR) {
|
||||
free_unified_knots(&geom_knot, &color_knot, &normal_knot,
|
||||
&texture_knot);
|
||||
free(*new_geom_ctrl);
|
||||
if (*new_color_ctrl)
|
||||
free(*new_color_ctrl);
|
||||
if (*new_normal_ctrl)
|
||||
free(*new_normal_ctrl);
|
||||
call_user_error(nobj, err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
return GLU_NO_ERROR;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,937 +0,0 @@
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
@@ -1,403 +0,0 @@
|
||||
|
||||
/*
|
||||
* 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);
|
||||
if (!invert_matrix(A, m))
|
||||
return GL_FALSE;
|
||||
|
||||
/* 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);
|
||||
if (!invert_matrix(A, m))
|
||||
return GL_FALSE;
|
||||
|
||||
/* 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
|
||||
@@ -1,819 +0,0 @@
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
GLdouble mag;
|
||||
|
||||
mag = sqrt(x * x + y * y + z * z);
|
||||
if (mag > 0.00001F) {
|
||||
x /= mag;
|
||||
y /= mag;
|
||||
z /= mag;
|
||||
}
|
||||
glNormal3f(x, y, 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);
|
||||
if (normals)
|
||||
glNormal3f(x * nsign, y * nsign, z * nsign);
|
||||
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);
|
||||
if (normals)
|
||||
glNormal3f(x * nsign, y * nsign, z * nsign);
|
||||
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);
|
||||
if (normals)
|
||||
glNormal3f(x * nsign, y * nsign, z * nsign);
|
||||
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);
|
||||
glNormal3f(0.0, 0.0, -1.0);
|
||||
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);
|
||||
if (normals)
|
||||
glNormal3f(x * nsign, y * nsign, z * nsign);
|
||||
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);
|
||||
if (normals)
|
||||
glNormal3f(x * nsign, y * nsign, z * nsign);
|
||||
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);
|
||||
if (normals)
|
||||
glNormal3f(x * nsign, y * nsign, z * nsign);
|
||||
glVertex3f(x * radius, y * radius, z * radius);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
else if (qobj->DrawStyle == GLU_POINT) {
|
||||
/* top and bottom-most points */
|
||||
glBegin(GL_POINTS);
|
||||
if (normals)
|
||||
glNormal3f(0.0, 0.0, nsign);
|
||||
glVertex3d(0.0, 0.0, radius);
|
||||
if (normals)
|
||||
glNormal3f(0.0, 0.0, -nsign);
|
||||
glVertex3d(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);
|
||||
if (normals)
|
||||
glNormal3f(x * nsign, y * nsign, z * nsign);
|
||||
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
|
||||
|
||||
/* Normal vectors */
|
||||
if (qobj->Normals != GLU_NONE) {
|
||||
if (qobj->Orientation == GLU_OUTSIDE) {
|
||||
glNormal3f(0.0, 0.0, +1.0);
|
||||
}
|
||||
else {
|
||||
glNormal3f(0.0, 0.0, -1.0);
|
||||
}
|
||||
}
|
||||
|
||||
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->Normals != GLU_NONE) {
|
||||
if (qobj->Orientation == GLU_OUTSIDE) {
|
||||
glNormal3f(0.0, 0.0, +1.0);
|
||||
}
|
||||
else {
|
||||
glNormal3f(0.0, 0.0, -1.0);
|
||||
}
|
||||
}
|
||||
|
||||
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++) {
|
||||
glVertex2d(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++) {
|
||||
glVertex2d(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++) {
|
||||
glVertex2d(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++) {
|
||||
glVertex2d(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++) {
|
||||
glVertex2d(innerRadius * sin(angle), innerRadius * cos(angle));
|
||||
angle += delta_angle;
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
/* draw spokes */
|
||||
if (sweepAngle < 360.0) {
|
||||
GLdouble stopAngle = startAngle + sweepAngle;
|
||||
glBegin(GL_LINES);
|
||||
glVertex2d(innerRadius * SIND(startAngle),
|
||||
innerRadius * COSD(startAngle));
|
||||
glVertex2d(outerRadius * SIND(startAngle),
|
||||
outerRadius * COSD(startAngle));
|
||||
glVertex2d(innerRadius * SIND(stopAngle),
|
||||
innerRadius * COSD(stopAngle));
|
||||
glVertex2d(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) {
|
||||
glVertex2d((radius + delta_radius) * sin(angle),
|
||||
(radius + delta_radius) * cos(angle));
|
||||
glVertex2d(radius * sin(angle), radius * cos(angle));
|
||||
}
|
||||
else {
|
||||
glVertex2d(radius * sin(angle), radius * cos(angle));
|
||||
glVertex2d((radius + delta_radius) * sin(angle),
|
||||
(radius + delta_radius) * cos(angle));
|
||||
}
|
||||
angle += delta_angle;
|
||||
}
|
||||
glEnd();
|
||||
radius += delta_radius;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,327 +0,0 @@
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
|
||||
/*
|
||||
* 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
|
||||
@@ -1,406 +0,0 @@
|
||||
|
||||
/*
|
||||
* 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) ();
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
@@ -1,416 +0,0 @@
|
||||
|
||||
/*
|
||||
* 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
|
||||
@@ -1,141 +0,0 @@
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
|
||||
/* compatibility 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
|
||||
@@ -1,763 +0,0 @@
|
||||
|
||||
/*
|
||||
* 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 data type, 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;
|
||||
}
|
||||
@@ -1,157 +0,0 @@
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
}
|
||||
@@ -1,252 +0,0 @@
|
||||
|
||||
/*
|
||||
* 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
|
||||
@@ -1,132 +0,0 @@
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
@@ -1,937 +0,0 @@
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
@@ -1,403 +0,0 @@
|
||||
|
||||
/*
|
||||
* 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);
|
||||
if (!invert_matrix(A, m))
|
||||
return GL_FALSE;
|
||||
|
||||
/* 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);
|
||||
if (!invert_matrix(A, m))
|
||||
return GL_FALSE;
|
||||
|
||||
/* 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
|
||||
@@ -1,773 +0,0 @@
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,327 +0,0 @@
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user