<directory name="mesa32">
<xi:include href="mesa32/mesa32.rbuild" />
</directory>
+
+ <ifnot property="NSWPAT" value="0">
+ <directory name="dxtn">
+ <xi:include href="dxtn/dxtn.rbuild" />
+ </directory>
+ </ifnot>
</group>
\ No newline at end of file
--- /dev/null
+# Texture compression Linux makefile
+# Version: 1.1
+#
+# Copyright (C) 2004 Daniel Borca All Rights Reserved.
+#
+# this is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# this 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Make; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+#
+# Available options:
+#
+# Environment variables:
+#
+# Targets:
+# all: build dynamic module
+# clean: remove object files
+# realclean: remove all generated files
+#
+
+
+.PHONY: all clean realclean
+
+DLLNAME = libdxtn.so
+
+CC = gcc
+CFLAGS = -Wall -W -pedantic -ansi
+CFLAGS += -O2 -ffast-math -funroll-loops
+#CFLAGS += -fomit-frame-pointer -fexpensive-optimizations
+CFLAGS += -fPIC -DPIC
+
+LD = gcc
+LDFLAGS = -shared
+LDLIBS =
+
+SOURCES = \
+ fxt1.c \
+ dxtn.c \
+ wrapper.c \
+ texstore.c
+
+OBJECTS = $(SOURCES:.c=.o)
+
+.c.o:
+ $(CC) -o $@ $(CFLAGS) -c $<
+
+all: $(DLLNAME)
+
+$(DLLNAME): $(OBJECTS)
+ $(LD) -o $@ $(LDFLAGS) $^ $(LDLIBS)
+
+clean:
+ -$(RM) $(OBJECTS)
+
+realclean: clean
+ -$(RM) $(DLLNAME)
+
+-include depend
--- /dev/null
+# Texture compression DJGPP makefile
+# Version: 1.1
+#
+# Copyright (C) 2004 Daniel Borca All Rights Reserved.
+#
+# this is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# this 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Make; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+#
+# Available options:
+#
+# Environment variables:
+#
+# Targets:
+# all: build dynamic module
+# clean: remove object files
+# realclean: remove all generated files
+#
+
+
+.PHONY: all clean realclean
+
+DLLNAME = libdxtn.a
+
+CC = gcc
+CFLAGS = -Wall -W -pedantic -ansi
+CFLAGS += -O2 -ffast-math -funroll-loops
+#CFLAGS += -fomit-frame-pointer -fexpensive-optimizations
+
+AR = ar
+ARFLAGS = crus
+
+RM = del
+
+SOURCES = \
+ fxt1.c \
+ dxtn.c \
+ wrapper.c \
+ texstore.c
+
+OBJECTS = $(SOURCES:.c=.o)
+
+.c.o:
+ $(CC) -o $@ $(CFLAGS) -c $<
+
+all: $(DLLNAME)
+
+$(DLLNAME): $(OBJECTS)
+ $(AR) $(ARFLAGS) $@ $^
+
+clean:
+ -$(RM) $(OBJECTS)
+
+realclean: clean
+ -$(RM) $(DLLNAME)
+
+-include depend
--- /dev/null
+# Texture compression MinGW makefile
+# Version: 1.1
+#
+# Copyright (C) 2004 Daniel Borca All Rights Reserved.
+#
+# this is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# this 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Make; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+#
+# Available options:
+#
+# Environment variables:
+#
+# Targets:
+# all: build dynamic module
+# clean: remove object files
+# realclean: remove all generated files
+#
+
+
+.PHONY: all clean realclean
+
+DLLNAME = dxtn.dll
+
+CC = mingw32-gcc
+CFLAGS = -Wall -W -pedantic -ansi
+CFLAGS += -O2 -ffast-math -funroll-loops
+#CFLAGS += -fomit-frame-pointer -fexpensive-optimizations
+
+LD = mingw32-gcc
+LDFLAGS = -shared
+LDLIBS =
+
+RM = del
+
+SOURCES = \
+ fxt1.c \
+ dxtn.c \
+ wrapper.c \
+ texstore.c
+
+OBJECTS = $(SOURCES:.c=.o)
+
+.c.o:
+ $(CC) -o $@ $(CFLAGS) -c $<
+
+all: $(DLLNAME)
+
+$(DLLNAME): $(OBJECTS)
+ $(LD) -o $@ $(LDFLAGS) $^ $(LDLIBS)
+
+clean:
+ -$(RM) *.o
+
+realclean: clean
+ -$(RM) $(DLLNAME)
+
+-include depend
--- /dev/null
+# Texture compression VisualC(++) makefile
+# Version: 1.1
+#
+# Copyright (C) 2004 Daniel Borca All Rights Reserved.
+#
+# this is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# this 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Make; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+#
+# Available options:
+#
+# Environment variables:
+#
+# Targets:
+# all: build dynamic module
+# clean: remove object files
+# realclean: remove all generated files
+#
+
+
+.PHONY: all clean realclean
+
+DLLNAME = dxtn.dll
+
+CC = cl
+CFLAGS = -nologo -W3 -WX -D__MSC__=1 -D__WIN32__
+CFLAGS += -DNDEBUG -G6 -O2
+
+LD = link
+LDFLAGS = -nologo -dll -opt:WIN98 -machine:IX86
+LDLIBS =
+
+RM = del
+
+SOURCES = \
+ fxt1.c \
+ dxtn.c \
+ wrapper.c \
+ texstore.c
+
+OBJECTS = $(SOURCES:.c=.o)
+
+.c.o:
+ $(CC) -Fo$@ $(CFLAGS) -c $<
+
+all: $(DLLNAME)
+
+$(DLLNAME): $(OBJECTS)
+ $(LD) -out:$@ $(LDFLAGS) $^ $(LDLIBS)
+
+clean:
+ -$(RM) *.o
+
+realclean: clean
+ -$(RM) $(DLLNAME)
+
+-include depend
--- /dev/null
+# Texture compression OpenWatcom makefile
+# Version: 1.1
+#
+# Copyright (C) 2004 Daniel Borca All Rights Reserved.
+#
+# this is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# this 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Make; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+#
+# Available options:
+#
+# Environment variables:
+#
+# Targets:
+# all: build dynamic module
+# clean: remove object files
+# realclean: remove all generated files
+#
+
+
+.PHONY: all clean realclean
+.SUFFIXES: .c .obj
+
+DLLNAME = dxtn.dll
+
+CC = wcl386
+CFLAGS = -wx -zq
+CFLAGS += -ox -6s
+
+LD = wcl386
+LDFLAGS = -zq -bd
+LDLIBS =
+
+RM = del
+
+SOURCES = \
+ fxt1.c \
+ dxtn.c \
+ wrapper.c \
+ texstore.c
+
+OBJECTS = $(SOURCES:.c=.obj)
+
+.c.obj:
+ $(CC) -fo=$@ $(CFLAGS) -c $<
+
+all: $(DLLNAME)
+
+$(DLLNAME): $(OBJECTS)
+ $(LD) -fe=$@ $(LDFLAGS) $^ $(LDLIBS)
+
+clean:
+ $(RM) *.obj
+ $(RM) *.err
+
+realclean: clean
+ $(RM) $(DLLNAME)
+
+-include depend
--- /dev/null
+This is a working codec for FXT1 and DXTn texture compression.
+It has a balanced speed/quality ratio, and is very tweakable.
+
+Both FXT1 and DXTn use vector quantization for lossy encoding.
+The decoder is rather trivial, at the expense of the encoder
+complexity. This means that applications heavily relying on
+texture compression should provide precompressed textures, for
+several obvious reasons:
+1) the encoding phase can be done "off-line" with hi-quality
+ encoders
+2) if the graphic driver does not support precompressed textures,
+ it's still cheap to decode "on-line" application-side
+3) the distributed package gets smaller
+
+The FXT1 and DXTn codecs were written using documentation freely
+available on the world-wide-web, including, but not limited to:
+3DFX_texture_compression_FXT1 and EXT_texture_compression_s3tc
+from http://oss.sgi.com/projects/ogl-sample/registry/
+I just translated the human readable spec into ANSI C. There are
+NO binaries available, as I am NOT using this code! Therefore,
+THE RESPONSIBILITY OF USING THE CODE IS ENTIRELY WITH YOU!
+
+The implementation per-se is made available under GPL, which
+does not necessarily apply to the abstract content (texture
+compression algorithms):
+FXT1 is subject to "3DFX FXT1 Source Code General Public License"
+
+DXTn is basically the S3TC texture compression, a license to the
+ "S3TC Intellectual Property" may be required prior to any use.
+
+ There is significant IP associated with the S3TC format.
+ Existing users probably have executed licenses directly
+ with S3 or its successors (Sonic Blue, S3 Graphics).
+
+ The current ownership of the S3TC IP is unknown to me. It is
+ known that when S3 exited the graphics hardware business, part of
+ their operations were sold to ATI and part were spun off to a joint
+ Taiwanese venture with Via Technologies, called S3 Graphics.
+
+I, DANIEL BORCA, AM NOT AWARE OF ANY LEGAL ISSUE CAUSED BY RELEASING
+THIS CODE. Prior to commencement of legal action, the Plaintiff should
+make an informal demand to Cease and Desist. In deference to the
+regulations of the Federal Communications Commission, which requires
+notice prior to filing an action, and in the spirit of cooperation,
+all complaints, issues and concerns should first be directed to me
+in an effort to resolve them amicably and promptly. FCC s2250.
+
+Daniel Borca
+dborca 'at' yahoo 'dot' com
--- /dev/null
+3DFX FXT1 Source Code General Public License
+
+
+1. PREAMBLE
+
+ This license is for software that provides texture compression and
+ decompression, particularly in the context of video games. The license
+ is intended to offer terms similar to some standard General Public
+ Licenses designed to foster open standards and unrestricted
+ accessibility to source code. Some of these licenses require that, as
+ a condition of the license of the software, any derivative works
+ (that is, new software which is a work containing the original program
+ or a portion of it) must be available for general use, without
+ restriction other than for a minor transfer fee, and that the source
+ code for such derivative works must likewise be made available. The
+ only restriction is that such derivative works must be subject to
+ the same General Public License terms as the original work.
+
+ This 3dfx FXT1 Source Code General Public License differs from the
+ standard licenses of this type in that it does not require the entire
+ derivative work to be made available under the terms of this license
+ nor is the recipient required to make available the source code for
+ the entire derivative work. Rather, the license is limited to only the
+ identifiable portion of the derivative work that is derived from the
+ licensed software. The precise terms and conditions for copying,
+ distribution and modification follow.
+
+
+2. DEFINITIONS
+
+ 2.1 This License applies to any program (or other "work") which
+ contains a notice placed by the copyright holder saying it may be
+ distributed under the terms of this 3dfx FXT1 Source Code General
+ Public License.
+
+ 2.2 The term "Program" as used in this Agreement refers to 3DFX's
+ FXT1 source code and object code and any Derivative Work.
+
+ 2.3 "Derivative Work" means, for the purpose of the License, that
+ portion of any work that contains the Program or the identifiable
+ portion of a work that is derived from the Program, either verbatim or
+ with modifications and/or translated into another language, and that
+ performs texture compression and decompression. It does not include
+ any other portions of a work.
+
+ 2.4 "Modifications of the Program" means any work, which includes a
+ Derivative Work, and includes the whole of such work.
+
+ 2.5 "License" means this 3dfx FXT1 Source Code General Public License.
+
+ 2.6 The "Source Code" for a work means the preferred form of the work
+ for making modifications to it. For an executable work, complete source
+ code means all the source code for all modules it contains, any
+ associated interface definition files, and the scripts used to control
+ compilation and installation of the executable work.
+
+ 2.7 "3dfx" means 3dfx Interactive, Inc.
+
+
+3. LICENSED ACTIVITIES
+
+ 3.1 COPYING - You may copy and distribute verbatim copies of the
+ Program's Source Code as you receive it, in any medium, subject to the
+ provision of section 3.3 and provided also that:
+
+ (a) you conspicuously and appropriately publish on each copy
+ an appropriate copyright notice (3dfx Interactive, Inc. 1999), a notice
+ that recipients who wish to copy, distribute or modify the Program can
+ only do so subject to this License, and a disclaimer of warranty as
+ set forth in section 5;
+
+ (b) keep intact all the notices that refer to this License and
+ to the absence of any warranty; and
+
+ (c) give all recipients of the Program a copy of this License
+ along with the Program or instructions on how to easily receive a copy
+ of this License.
+
+
+ 3.2 MODIFICATION OF THE PROGRAM/DERIVATIVE WORKS - You may modify your
+ copy or copies of the Program or any portion of it, and copy and
+ distribute such modifications subject to the provisions of section 3.3
+ and provided that you also meet all of the following conditions:
+
+ (a) you conspicuously and appropriately publish on each copy
+ of a Derivative Work an appropriate copyright notice, a notice that
+ recipients who wish to copy, distribute or modify the Derivative Work
+ can only do so subject to this License, and a disclaimer of warranty
+ as set forth in section 5;
+
+ (b) keep intact all the notices that refer to this License and
+ to the absence of any warranty; and
+
+ (c) give all recipients of the Derivative Work a copy of this
+ License along with the Derivative Work or instructions on how to easily
+ receive a copy of this License.
+
+ (d) You must cause the modified files of the Derivative Work
+ to carry prominent notices stating that you changed the files and the
+ date of any change.
+
+ (e) You must cause any Derivative Work that you distribute or
+ publish to be licensed at no charge to all third parties under the
+ terms of this License.
+
+ (f) If the Derivative Work normally reads commands
+ interactively when run, you must cause it, when started running for
+ such interactive use, to print or display an announcement as follows:
+
+ "COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED THIS
+ SOFTWARE IS FREE AND PROVIDED "AS IS," WITHOUT WARRANTY OF ANY KIND,
+ EITHER EXPRESSED OR IMPLIED. SEE THE 3DFX FXT1 GENERAL PUBLIC LICENSE
+ FOR A FULL TEXT OF THE DISTRIBUTION AND NON-WARRANTY PROVISIONS
+ (REQUEST COPY FROM INFO@3DFX.COM)."
+
+ (g) The requirements of this section 3.2 do not apply to the
+ modified work as a whole but only to the Derivative Work. It is not
+ the intent of this License to claim rights or contest your rights to
+ work written entirely by you; rather, the intent is to exercise the
+ right to control the distribution of Derivative Works.
+
+
+ 3.3 DISTRIBUTION
+
+ (a) All copies of the Program or Derivative Works which are
+ distributed must include in the file headers the following language
+ verbatim:
+
+ "THIS SOFTWARE IS SUBJECT TO COPYRIGHT PROTECTION AND IS OFFERED
+ ONLY PURSUANT TO THE 3DFX FXT1 GENERAL PUBLIC LICENSE. A COPY OF THIS
+ LICENSE MAY BE OBTAINED FROM THE DISTRIBUTOR OR BY CONTACTING 3DFX
+ INTERACTIVE INC (info@3dfx.com). THIS PROGRAM. IS PROVIDED "AS IS"
+ WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED. SEE THE
+ 3DFX FXT1 GENERAL PUBLIC LICENSE FOR A FULL TEXT OF THE NON-WARRANTY
+ PROVISIONS.
+
+ USE, DUPLICATION OR DISCLOSURE BY THE GOVERNMENT IS SUBJECT TO
+ RESTRICTIONS AS SET FORTH IN SUBDIVISION (C)(1)(II) OF THE RIGHTS
+ IN TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013,
+ AND/OR IN SIMILAR OR SUCCESSOR CLAUSES IN THE FAR, DOD OR NASA FAR
+ SUPPLEMENT. UNPUBLISHED RIGHTS RESERVED UNDER THE COPYRIGHT LAWS OF
+ THE UNITED STATES.
+
+ COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED"
+
+ (b) You may distribute the Program or a Derivative Work in
+ object code or executable form under the terms of Sections 3.1 and 3.2
+ provided that you also do one of the following:
+
+ (1) Accompany it with the complete corresponding
+ machine-readable source code, which must be distributed under the
+ terms of Sections 3.1 and 3.2; or,
+
+ (2) Accompany it with a written offer, valid for at
+ least three years, to give any third party, for a charge no more than
+ your cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 3.1 and 3.2 on a medium
+ customarily used for software interchange; or,
+
+ (3) Accompany it with the information you received as
+ to the offer to distribute corresponding source code. (This alternative
+ is allowed only for noncommercial distribution and only if you received
+ the program in object code or executable form with such an offer, in
+ accord with Subsection 3.3(b)(2) above.)
+
+ (c) The source code distributed need not include anything
+ that is normally distributed (in either source or binary form) with
+ the major components (compiler, kernel, and so on) of the operating
+ system on which the executable runs, unless that component itself
+ accompanies the executable code.
+
+ (d) If distribution of executable code or object code is made
+ by offering access to copy from a designated place, then offering
+ equivalent access to copy the source code from the same place counts
+ as distribution of the source code, even though third parties are not
+ compelled to copy the source along with the object code.
+
+ (e) Each time you redistribute the Program or any Derivative
+ Work, the recipient automatically receives a license from 3dfx and
+ successor licensors to copy, distribute or modify the Program and
+ Derivative Works subject to the terms and conditions of the License.
+ You may not impose any further restrictions on the recipients'
+ exercise of the rights granted herein. You are not responsible for
+ enforcing compliance by third parties to this License.
+
+ (f) You may not copy, modify, sublicense, or distribute the
+ Program or any Derivative Works except as expressly provided under
+ this License. Any attempt otherwise to copy, modify, sublicense or
+ distribute the Program or any Derivative Works is void, and will
+ automatically terminate your rights under this License. However,
+ parties who have received copies, or rights, from you under this
+ License will not have their licenses terminated so long as such
+ parties remain in full compliance.
+
+
+4. MISCELLANEOUS
+
+ 4.1 Acceptance of this License is voluntary. By using, modifying or
+ distributing the Program or any Derivative Work, you indicate your
+ acceptance of this License to do so, and all its terms and conditions
+ for copying, distributing or modifying the Program or works based on
+ it. Nothing else grants you permission to modify or distribute the
+ Program or Derivative Works and doing so without acceptance of this
+ License is in violation of the U.S. and international copyright laws.
+
+ 4.2 If the distribution and/or use of the Program or Derivative Works
+ is restricted in certain countries either by patents or by copyrighted
+ interfaces, the original copyright holder who places the Program under
+ this License may add an explicit geographical distribution limitation
+ excluding those countries, so that distribution is permitted only in
+ or among countries not thus excluded. In such case, this License
+ incorporates the limitation as if written in the body of this License.
+
+ 4.3 This License is to be construed according to the laws of the
+ State of California and you consent to personal jurisdiction in the
+ State of California in the event it is necessary to enforce the
+ provisions of this License.
+
+
+5. NO WARRANTIES
+
+ 5.1 TO THE EXTENT PERMITTED BY APPLICABLE LAW, THERE IS NO WARRANTY
+ FOR THE PROGRAM. OR DERIVATIVE WORKS THE COPYRIGHT HOLDERS AND/OR
+ OTHER PARTIES PROVIDE THE PROGRAM AND ANY DERIVATIVE WORKS"AS IS"
+ WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY
+ AND PERFORMANCE OF THE PROGRAM AND ANY DERIVATIVE WORK IS WITH YOU.
+ SHOULD THE PROGRAM OR ANY DERIVATIVE WORK PROVE DEFECTIVE, YOU ASSUME
+ THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 5.2 IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL 3DFX
+ INTERACTIVE, INC., OR ANY OTHER COPYRIGHT HOLDER, OR ANY OTHER PARTY
+ WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM OR DERIVATIVE WORKS AS
+ PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL,
+ SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
+ INABILITY TO USE THE PROGRAM OR DERIVATIVE WORKS (INCLUDING BUT NOT
+ LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES
+ SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM OR
+ DERIVATIVE WORKS TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH
+ HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ DAMAGES.
+
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+
+<head>
+ <meta name="Author" content="Daniel Borca"/>
+ <meta name="Description" content="Texture compression"/>
+ <meta name="KeyWords" content="FXT1, DXTn, S3TC, DXT1, DXT3, DXT5, texture, compression, codec, compressor, decompressor"/>
+
+ <title>Texture compression</title>
+
+ <link rel="STYLESHEET" type="text/css" href="../style.css"/>
+</head>
+
+<body bgcolor="#500000" text="#FFFF00" background="../bg_deepred1.gif">
+ <center><h2>Texture compression</h2></center>
+ <hr/>
+
+ <p><a href="tc-1.1.tar.gz">tc-1.1.tar.gz</a> is a working codec for <b>FXT1</b> and <b>DXTn</b> texture compression.
+ It has a balanced speed/quality ratio, and is very tweakable.</p>
+ <p>Both <b>FXT1</b> and <b>DXTn</b> use vector quantization for lossy encoding.
+ The decoder is rather trivial, at the expense of the encoder
+ complexity. This means that applications heavily relying on
+ texture compression should provide precompressed textures, for
+ several obvious reasons:</p>
+ <ol>
+ <li>the encoding phase can be done "off-line" with hi-quality
+ encoders</li>
+ <li>if the graphic driver does not support precompressed textures,
+ it's still cheap to decode "on-line" application-side</li>
+ <li>the distributed package gets smaller</li>
+ </ol>
+ <p>The <b>FXT1</b> and <b>DXTn</b> codecs were written using documentation freely
+ available on the world-wide-web, including, but not limited to:
+ 3DFX_texture_compression_FXT1 and EXT_texture_compression_s3tc
+ from <a href="http://oss.sgi.com/projects/ogl-sample/registry/">http://oss.sgi.com/projects/ogl-sample/registry/</a><BR/>
+ I just translated the human readable spec into ANSI C. There are
+ NO binaries available, as I am <b>NOT</b> using this code! <b>Therefore,
+ <font color="#D8D8D8">THE RESPONSIBILITY OF USING THE CODE IS ENTIRELY WITH YOU!</font></b></p>
+ <p>The implementation <I>per-se</I> is made available under GPL, which
+ does not necessarily apply to the abstract content (texture
+ compression algorithms):</p>
+ <p><b>FXT1</b> is subject to "3DFX FXT1 Source Code General Public License"</p>
+ <p><b>DXTn</b> is basically the S3TC texture compression, a license to the
+ "S3TC Intellectual Property" may be required prior to any use.</p>
+ <dir>
+ <p>There is significant IP associated with the S3TC format.
+ Existing users probably have executed licenses directly
+ with S3 or its successors (Sonic Blue, S3 Graphics).</p>
+
+ <p>The current ownership of the S3TC IP is unknown to me. It is
+ known that when S3 exited the graphics hardware business, part of
+ their operations were sold to ATI and part were spun off to a joint
+ Taiwanese venture with Via Technologies, called S3 Graphics.</p>
+ </dir>
+ <p><b><font color="#D8D8D8">I, DANIEL BORCA, AM NOT AWARE OF ANY LEGAL ISSUE CAUSED BY RELEASING
+ THIS CODE.</font> Prior to commencement of legal action, the Plaintiff should
+ make an informal demand to Cease and Desist. In deference to the
+ regulations of the Federal Communications Commission, which requires
+ notice prior to filing an action, and in the spirit of cooperation,
+ all complaints, issues and concerns should first be directed to me
+ in an effort to resolve them amicably and promptly. FCC s2250.</b></p>
+ <p/>Daniel Borca<br/>
+ <a href="mailto:dborca%20'at'%20yahoo%20'dot'%20com">dborca 'at' yahoo 'dot' com</a>
+</body>
+
+</html>
--- /dev/null
+Name
+
+ 3DFX_texture_compression_FXT1
+
+Name Strings
+
+ GL_3DFX_texture_compression_FXT1
+
+Contact
+
+ Don Mullis, 3dfx Interactive (dwm 'at' 3dfx.com)
+
+Status
+
+ CANDIDATE FOR FINAL DRAFT -- NOT YET COMPLETE
+
+Version
+
+ Draft 0.4, 12 Apr 2000
+
+Number
+
+ 206
+
+Dependencies
+
+ OpenGL 1.1 is required.
+ GL_ARB_texture_compression is required.
+ This extension is written against the OpenGL 1.2.1 Specification.
+
+Overview
+
+ This extension additional texture compression functionality 's FXT1
+ format, specific to 3dfxsubject to all the requirements and
+ limitations described by the extension GL_ARB_texture_compression.
+ The FXT1 texture format supports only 2D and 3D images without
+ borders.
+
+ Because 3dfx expects to make continual improvement to its FXT1
+ compressor implementation, 3dfx recommends that to achieve best
+ visual quality applications adopt the following procedure with
+ respect to reuse of textures compressed by the GL:
+
+ 1) Save the RENDERER and VERSION strings along with images
+ compressed by the GL;
+ 2) Before reuse of the textures, compare the stored strings with
+ strings newly returned from the current GL;
+ 3) If out-of-date, repeat the compression and storage steps.
+
+IP Status
+
+ A royalty-free license is available from 3dfx Interactive
+ (http://www.3dfx.com/).
+
+Issues
+
+ (1) Two or only one internalformat tokens:
+ GL_COMPRESSED_RGBA_FXT1_3DFX and GL_COMPRESSED_RGB_FXT1_3DFX, or
+ GL_COMPRESSED_RGBA_FXT1_3DFX only. These names are placeholders,
+ the point in question is whether there should be separate tokens
+ reflecting extrinsic knowledge of whether the image contains any
+ non-unity alpha values. This arises because the FXT1 image
+ format distinguishes non-unity alpha only at the level of an
+ individual 8x4 compression block. If there are two distinct
+ tokens, passing GL_COMPRESSED_RGB_FXT1_3DFX to
+ CompressedTexImage with an image that contained non-unity-alpha
+ blocks would be an error.
+
+ RESOLVED. Two distinct tokens specified. This is largely to
+ follow the usual usage by apps of non-compressed tokens.
+
+ (2) Support for borders.
+
+ RESOLVED. Not supported.
+
+ (3) Support for TexSubImage at a level more general than that
+ guaranteed by ARB_texture_compression.
+
+ RESOLVED. Not supported; See issue (5) of the
+ GL_ARB_texture_compression spec.
+
+New Procedures and Functions
+
+ None
+
+New Tokens
+
+ Accepted by the <internalformat> parameter of TexImage2D,
+ CopyTexImage2D, TexImage3D, CopyTexImage3D, and by the
+ <internalformat> and <format> parameters of
+ CompressedTexImage2D_ARB, CompressedTexSubImage2D_ARB,
+ CompressedTexImage3D_ARB, CompressedTexSubImage3D_ARB:
+
+ COMPRESSED_RGB_FXT1_3DFX 0x86B0
+ COMPRESSED_RGBA_FXT1_3DFX 0x86B1
+
+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 (Rasterization)
+
+ Add Table 3.16.1: Specific Compressed Internal Formats
+
+ Compressed Internal Format Base Internal Format
+ ========================== ====================
+ COMPRESSED_RGB_FXT1_3DFX RGB
+ COMPRESSED_RGBA_FXT1_3DFX RGBA
+
+ Add to Section 3.8.2, Alternate Image Specification (adding to the
+ end of the CompressedTexImage section introduced by the
+ ARB_texture_compression spec)
+
+ If <internalformat> is COMPRESSED_RGB_FXT1_3DFX,
+ COMPRESSED_RGBA_FXT1_3DFX, the compressed texture is stored using
+ one of several FXT1 compressed texture image formats. FXT1 texture
+ compression supports only 2D images without borders.
+ CompressedTexImage1DARB and CompressedTexImage3DARB produce an
+ INVALID_ENUM error if <internalformat> is an FXT1 format.
+ CompressedTexImage2DARB will produce an INVALID_OPERATION error if
+ <border> is non-zero.
+
+
+ Add to Section 3.8.2, Alternate Image Specification (adding to the
+ end of the CompressedTexSubImage section introduced by the
+ ARB_texture_compression spec)
+
+ If the internal format of the texture image being modified is
+ COMPRESSED_RGB_FXT1_3DFX, COMPRESSED_RGBA_FXT1_3DFX, the texture is
+ stored using one of the several FXT1 compressed texture image
+ formats. Since the FXT1 texture compression algorithm supports only
+ 2D images, CompressedTexSubImage1DARB and CompressedTexSubImage3DARB
+ produce an INVALID_ENUM error if <format> is an FXT1 format.
+
+Additions to Chapter 4 of the OpenGL 1.2.1 Specification (Per-Fragment
+Operations and the Frame Buffer)
+
+ None.
+
+Additions to Chapter 5 of the OpenGL 1.2.1 Specification (Special Functions)
+
+ None.
+
+Additions to Chapter 6 of the OpenGL 1.2.1 Specification (State and
+State Requests)
+
+ None.
+
+Additions to Appendix A of the OpenGL 1.2.1 Specification (Invariance)
+
+ None.
+
+Additions to the AGL/GLX/WGL Specifications
+
+ None.
+
+GLX Protocol
+
+ None.
+
+Errors
+
+ INVALID_ENUM is generated by CompressedTexImage1DARB if
+ <internalformat> is GL_COMPRESSED_RGB_FXT1_3DFX or
+ GL_COMPRESSED_RGBA_FXT1_3DFX.
+
+ INVALID_OPERATION is generated by CompressedTexImage2DARB or
+ CompressedTexImage3DARB if <internalformat> is
+ GL_COMPRESSED_RGB_FXT1_3DFX or GL_COMPRESSED_RGBA_FXT1_3DFX and
+ <border> is not equal to zero.
+
+ INVALID_ENUM is generated by CompressedTexSubImage1DARB if <format>
+ is GL_COMPRESSED_RGB_FXT1_3DFX or GL_COMPRESSED_RGBA_FXT1_3DFX.
+
+Appendix
+
+ FXT1 comprises four different compressed texture formats. Each of
+ the formats compress an 8x4 texel blocks into 128 bits. During the
+ compression phase, the encoder selects one of the four formats for
+ each block based on which encoding scheme results in best overall
+ visual quality. Unused pixel locations along the right or bottom
+ edges within a block should contain a repetition of the values in
+ used locations. The total size of an image is ceil(width/8) *
+ ceil(height/4) * 16 bytes.
+
+ In each compression format, the 32 texels of the 8x4 block are
+ partitioned into two 4x4 sub-blocks according to the following
+ diagram:
+
+ t0 t1 t2 t3 t16 t17 t18 t19
+ t4 t5 t6 t7 t20 t21 t22 t23
+ t8 t9 t10 t11 t24 t25 t26 t27
+ t12 t13 t14 t15 t28 t29 t30 t31
+
+ In the following bit-level descriptions, bits of increasing index
+ are stored in bytes at likewise increasing offsets, i.e. the order
+ is "little-endian".
+
+
+ 1. FXT1 Compressed Texture Format CC_HI:
+
+ (rgb555) (3-bit/texel)
+ mode[1:0] color1 color0 texel 31 to 16 texel 15 to 0
+ 2 15 15 48 48
+
+
+ [127:126] mode[1:0]
+ [125:121] red of color1
+ [120:116] green of color1
+ [115:111] blue of color1
+ [110:106] red of color0
+ [105:101] green of color0
+ [100:96] blue of color0
+ [95:93] texel 31
+ ...
+ [50:48] texel 16
+ [47:45] texel 15
+ ...
+ [2:0] texel 0
+
+ In CC_HI format, mode = 00b, the 15-bit color1 (RGB555 format) and
+ color0 (RGB555 format) colors are converted into 24-bit RGB888
+ colors by duplicating the upper 3 bits for the 3 LSBs. The 24-bit
+ converted color1 and color0 are then used to linearly interpolate 5
+ more levels of color to create seven total levels of colors and 1
+ alpha (transparent) color. The first seven colors always have
+ alpha=ffh (opaque), while the eighth color is defined to be
+ transparent black (r,g,b=00h, alpha=00h).
+
+ These eight 32-bit colors are used as the contents of an 8-entry (3
+ bit index) lookup table. For all 32 texels in the block, each
+ texel's 3-bit index value is used to index the lookup table, the
+ output from the lookup table representing the 32-bit color
+ (ARGB8888) for that texel.
+
+ Generating RGB888 from RGB555:
+
+ Color1 (red) = {[125:121], [125:123]}
+ Color1 (green) = {[120:116], [120:118]}
+ Color1 (blue) = {[115:111], [115:113]}
+
+ Color0 (red) = {[110:106], [110:108]}
+ Color0 (green) = {[105:101], [105:103]}
+ Color0 (blue) = {[100:96], [100:98]}
+
+ Creating seven ARGB8888 colors from two RGB888 colors (operations
+ performed individually for each color channel):
+
+ Color[0] = color0[r,g,b], alpha[0] = ffh
+ Color[1] = (5*color0[r,g,b] + color1[r,g,b] +3 )/6 alpha[1] = ffh
+ Color[2] = (4*color0[r,g,b] + 2*color1[r,g,b] +3 )/6 alpha[2] = ffh
+ Color[3] = (3*color0[r,g,b] + 3*color1[r,g,b] +3 )/6 alpha[3] = ffh
+ Color[4] = (2*color0[r,g,b] + 4*color1[r,g,b] +3 )/6 alpha[4] = ffh
+ Color[5] = (color0[r,g,b] + 5*color1[r,g,b] +3 )/6 alpha[5] = ffh
+ Color[6] = color1[r,g,b], alpha[6] = ffh
+ Color[7] = where r,g,b = 00h, alpha[7]=00h
+
+ Table Lookup:
+ 3-bit index of Color for texel 31 to texel 0
+ texel31 to texel0 (ARGB8888)
+
+ 0 color[0] => {a[7:0], r[7:0], g[7:0], b[7:0]}
+ 1 color[1]
+ 2 color[2]
+ 3 color[3]
+ 4 color[4]
+ 5 color[5]
+ 6 color[6]
+ 7 color[7]
+
+
+ 2. FXT1 Compressed Texture Format CC_CHROMA:
+
+ (rgb555) (2-bit/texel)
+ Mode[2:0] unused color3 color2 color1 color0 texel 31 to 16 texel 15 to 0
+ 3 1 15 15 15 15 32 32
+
+ [127:125] mode[2:0]
+ [124] unused
+ [123:119] color3(r5)
+ [118:114] color3(g5)
+ [113:109] color3(b5)
+ [108:104] color2(r5)
+ [103:99] color2(g5)
+ [98:94] color2(b5)
+ [93:89] color1(r5)
+ [88:84] color1(g5)
+ [83:79] color1(b5)
+ [78:74] color0(r5)
+ [73:69] color0(g5)
+ [68:64] color0(b5)
+ [63:62] texel 31
+ ...
+ [33:32] texel 16
+ [31:30] texel 15
+ ...
+ [1:0] texel 0
+
+ In CC_CHROMA format, mode=010b, the 15-bit colors color[3:0]
+ (RGB555) are converted into 24-bit RGB888 colors exactly the same as
+ in the CC_HI format via bit replication. Color3 to Color0 are used
+ as they are (after conversion to RGB888 format), but without
+ interpolation. The 24-bit converted colors color3, color2, color1,
+ and color0 are used as the contents of a 4-entry (2-bit index)
+ lookup table. The Alpha channel of the output of the lookup table is
+ always opaque(ffh), regardless of the 2-bit index value. The 32-bit
+ (ARGB8888) color value for each texel is obtained by performing
+ table lookup using that texel's 2-bit index.
+
+ Table Lookup:
+
+ 2-bit index of Color for texel 31 to texel 0
+ texel 31 to texel 0 (ARGB8888)
+
+ 0 color0, alpha = ffh
+ 1 color1, alpha = ffh
+ 2 color2, alpha = ffh
+ 3 color3, alpha = ffh
+
+
+ 3. FXT1 Compressed Texture Format CC_MIXED:
+
+ (rgb555) (2-bit/texel)
+ mode[0] glsb[1:0] alpha[0] color3 color2 color1 color0 texel 31to16 texel 15to0
+ 1 2 1 15 15 15 15 32 32
+
+
+ [127] mode[0]
+ [126:125] glsb[1:0] (lsbs of green for color 1 & color 3)
+ [124] alpha[0]
+ [123:119] color3(r5)
+ [118:114] color3(g5)
+ [113:109] color3(b5)
+ [108:104] color2(r5)
+ [103:99] color2(g5)
+ [98:94] color2(b5)
+ [93:89] color1(r5)
+ [88:84] color1(g5)
+ [83:79] color1(b5)
+ [78:74] color0(r5)
+ [73:69] color0(g5)
+ [68:64] color0(b5)
+ [63:62] texel 31
+ ...
+ [33:32] texel 16
+ [31:30] texel 15
+ ...
+ [1:0] texel 0
+
+ In CC_MIXED format, mode[0]=1 (only one bit), color2 and color3 are
+ used for texels 31 to 16, and color0 and color1 are used for texels
+ 15 to 0. When alpha[0] = 0, the two pairs of colors (colors 0 and 1
+ for texels 15 to 0 and colors 2 and 3 for texels 31 to 16) are
+ interpreted as 16-bit RGB565 colors. For color1 and color3, the LSB
+ (bit 0) of the green channel comes from the glsb bits
+ (color1.green[0] = bit 125, color3.green[0] = bit 126). For color0
+ and color2, the LSB (bit 0) of the green channel comes from the
+ upper select bit for texel 0 and texel 16, respectively
+ (color0.green[0] = bit 1 xor bit 125, color2.green[0] = bit 33 xor
+ bit 126). The two 16-bit colors are then expanded to a 24-bit RGB888
+ format by bit replication (most significant bits replicated in the
+ least significant bits), and are then used to create 2 more levels
+ of color in between the color0/2 and color1/3 values through linear
+ interpolation. A total of 4 colors are therefore available for 2-bit
+ index per texel selection.
+
+ When alpha[0]=1, color0 and color2 are interpreted as 15-bit RGB555
+ colors, and color 1 and color3 are interpreted as RGB565 colors. For
+ color0 and color2, the 15-bit RGB555 colors are expanded to 24-bit
+ RGB888 colors by bit replication. For color1 and color3, the LSB
+ (bit 0) of the green channel comes from the glsb bits
+ (color1.green[0] = bit 125, color3.green[0] = bit 126), and then bit
+ replication is used to convert from the 16-bit RGB565 format to a
+ 24-bit RGB888 format. A third color is created by linear
+ interpolation (interpolating between the converted 24-bit RGB888
+ color0 and color1 for texels 15 to 0, and interpolating between the
+ converted 24-bit RGB888 color2 and color3 for texels 31 to 16).
+ Finally, a fourth color (texel index 0x3) is defined to be
+ transparent black (r,g,b=00h, alpha=00h). A total of 4 colors are
+ therefore available for 2-bit index per texel selection. The 32-bit
+ (ARGB8888) color value for all texels is obtained by performing
+ table lookup using each texel's 2-bit index.
+
+ Creating the 24-bit (RGB888) base colors color3 and color2:
+
+ Color3(red) = {[123:119], [123:121]}
+ Color3(green) = {[118:114], [126], [118:117]}
+ Color3(blue) = {[113:109], [113:111]}
+ Color2(red) = {[108:104], [108:106]}
+ Color2(green) = (alpha[0]=1) ? {[103:99],[103:101]}
+ : {[103:99],[33]^[126],[103:102]}
+ Color2(blue) = {[98:94], [98:96]}
+
+ Creating the 24-bit (RGB888) base colors color1 and color0:
+
+ Color1(red) = {[93:89], [93:91]}
+ Color1(green) = {[88:84], [125], [88:87]}
+ Color1(blue) = {[83:79], [83:81]}
+ Color0(red) = {[78:74], [78:76]}
+ Color0(green) = (alpha[0]=1) ? {[73:69, [73:71]}
+ : {[73:69], [1]^[125], [73:72]}
+ Color0(blue) = {[68:64], [68:66]}
+
+ When alpha[0]=0, because one of the texel select bits is used to
+ determine a bit of color0 and color2, the software encoder must
+ perform some very tricky operations. The method below describes how
+ to generate color0 and color1 and the associated select bits (the
+ same method applies to determining the lsb of green for color2 and
+ color3):
+
+ 1. Determine the 16-bit RGB565 color values for color0 & color1.
+
+ 2. Determine the select bits for each pixel in the 4x4 sub-block.
+
+ 3. If (pixel[0].select[1] != color0.green[0]^color1.green[0]) then
+ swap color0 &color1, and invert all the select bits.
+
+ Below is a snippet of psuedo-C code to generate bits 0-31, bits
+ 64-93 & bit 125 based on the initial color0, color1 and pixel
+ indices:
+
+ struct RGB565 {Byte red; Byte green; Byte blue};
+
+ struct CSels {Byte index[16]};
+
+ // cc_mixed_right_half derives bits[93:64] of the 128 bit data word of a
+ // CC_MIXED non-alpha compression block and returns them in 'bits_64_to_31'.
+ // Plus, as a bonus, you will receive bit 125, containing the lsb of
+ // the green channel of color1, and bits_0_to_31, containing all of the pixel indices.
+ void
+ cc_mixed_right_half( RGB565 color0, RGB565 color1,
+ CSels pix,
+ Dword &bits_0_to_31,
+ Dword &bits_64_to_93,
+ Bit &bit125)
+ {
+ RGB565 o_color0;
+ RGB565 o_color1;
+
+ // Determine if we need to switch color0 & color1
+ if (((pix.index[0] >> 1) & 1) != ((color0.green ^ color1.green) & 1)) {
+ o_color1 = color0;
+ o_color0 = color1;
+
+ for (int i=0; i<16; i++)
+ pix.index[i] = ~pix.index[i] & 3;
+ } else {
+ o_color0 = color0;
+ o_color1 = color1;
+ }
+
+ // Save lsb of color1.green in bit125
+ bit125 = o_color1.green & 1;
+
+ // Convert color0 & color1 to RGB555, and then munge into bits 64 to 93
+ o_color0.green >>= 1;
+ o_color1.green >>= 1;
+
+ bits_64_to_93 = ( (o_color1.red<<25) | (o_color1.green<<20) | (o_color1.blue<<15)
+ | (o_color0.red<<10) | (o_color0.green<<5) | (o_color0.blue) );
+
+ // Munge the pixel indices into bits 0 to 31
+ bits_0_to_31 = 0;
+
+ for (int i=0; i<16; i++)
+ bits_0_to_31 |= pix.index[i]<<(i*2);
+ }
+
+
+ Generating the 4-entry lookup table for texels 31 to 16:
+
+ If alpha[0]=0,
+ Color[0] = color2[r,g,b] , alpha=ffh
+ Color[1] = (2 * color2[r,g,b] + color3[r,g,b] + 1) / 3, alpha=ffh
+ Color[2] = (color2[r,g,b] + 2 * color3[r,g,b] +1) / 3, alpha=ffh
+ Color[3] = color3[r,g,b], alpha=ffh
+
+ If alpha[0]=1,
+ Color[0] = color2[r,g,b], alpha=ffh
+ Color[1] = (color2[r,g,b] + color3[r,g,b]) / 2, alpha=ffh
+ Color[2] = color3[r,g,b], alpha=ffh
+ Color[3] = [a,r,g,b] = 00h
+
+ Generating the 4-entry lookup table for texels 15 to 0:
+
+ If alpha[0]=0,
+ Color[0] = color0[r,g,b] , alpha=ffh
+ Color[1] = (2 * color0[r,g,b] + color1[r,g,b] + 1) / 3, alpha=ffh
+ Color[2] = (color0[r,g,b] + 2 * color1[r,g,b] + 1) / 3, alpha=ffh
+ Color[3] = color1[r,g,b], alpha=ffh
+
+ If alpha[0]=1,
+ Color[0] = color0[r,g,b], alpha=ffh
+ Color[1] = (color0[r,g,b] + color1[r,g,b]) / 2, alpha=ffh
+ Color[2] = color1[r,g,b], alpha=ffh
+ Color[3] = [a,r,g,b] = 00h
+
+ Table Lookup:
+ 2-bit index of Color for texel 31 to texel 0
+ texel 31 to texel 0 ARGB8888
+
+ 0 color[0], {a[7:0], r[7:0], g[7:0], b[7:0]}
+ 1 color[1]
+ 2 color[2]
+ 3 color[3]
+
+
+ 4. FXT1 Compressed Texture format CC_ALPHA:
+
+ (argb5555) (2-bit/texel)
+ mode[2:0] lerp alpha2 alpha1 alpha0 color2 color1 color0 texel 31 to 16 texel 15 to 0
+ 3 1 5 5 5 15 15 15 32 32
+
+ [127:125] mode[2:0]
+ [124] lerp
+ [123:119] color2(a5)
+ [118:114] color1(a5)
+ [113:109] color0(a5)
+ [108:104] color2(r5)
+ [103:99] color2(g5)
+ [98:94] color2(b5)
+ [93:89] color1(r5)
+ [88:84] color1(g5)
+ [83:79] color1(b5)
+ [78:74] color0(r5)
+ [73:69] color0(g5)
+ [68:64] color0(b5)
+ [63:62] texel 31
+ ...
+ [33:32] texel 16
+ [31:30] texel 15
+ ...
+ [1:0] texel 0
+
+ In CC_ALPHA format, mode[2:0]=011b, three 20-bit colors color2,
+ color1 and color0 (ARGB5555) are converted to a 32-bit (ARGB8888)
+ format by duplicating the upper 3-bits for the 3 LSBs (all the color
+ channels and the alpha channel are converted from 5-bit formats to
+ 8-bit formats using this bit duplication).
+
+ Creating the 32-bit (RGB8888) base colors color2, color1, and color0:
+
+ Color2(alpha) = {[123:119], [123:121]}
+ Color2(red) = {[108:104], [108:106]}
+ Color2(green) = {[103:99], [103:101]}
+ Color2(blue) = {[98:94], [98:96]}
+ Color1(alpha) = {[118:114], [118:116]}
+ Color1(red) = {[93:89], [93:91]}
+ Color1(green) = {[88:84], [88:86]}
+ Color1(blue) = {[83:79], [83:81]}
+ Color0(alpha) = {[113:109], [113:111]}
+ Color0(red) = {[78:74], [78:76]}
+ Color0(green) = {[73:69], [73:71]}
+ Color0(blue) = {[68:64], [68:66]}
+
+ When lerp = 0 (bit 124 = 0), the converted 32-bit colors color2,
+ color1, and color0 are used directly as the first 3 entries in the
+ 4-entry lookup table. The last entry in the 4-entry lookup table,
+ accessed with index=3, is defined to be transparent black (rgb=00h,
+ alpha=00h). A total of 4 colors are therefore available for 2-bit
+ index per texel selection, and the 32-bit (ARGB8888) color value for
+ all texels is obtained by performing table lookup using each texel's
+ 2-bit index.
+
+ Table Lookup (when lerp = 0):
+
+ Index of texel 31 to 0 Color for texel 31 to texel 0
+ (ARGB8888)
+
+ 0 Color[0] = color0 alpha = alpha0
+ 1 Color[1] = color1 alpha = alpha1
+ 2 Color[2] = color2 alpha = alpha2
+ 3 Color[3] = 000000h alpha = 00h
+
+ When lerp = 1 (bit 124 = 1), the converted 32-bit colors color2 and
+ color1 are used as the 32-bit base colors for texels 31 to 16, and
+ the converted 32-bit colors color1 and color0 are used as the base
+ colors for texels 15 to 0. The 32-bit base colors are then used to
+ create 2 more levels of color through linear interpolation. A total
+ of 4 colors are therefore available for 2-bit index per texel
+ selection, and the 32-bit (ARGB8888) color value for all texels is
+ obtained by performing table lookup using each texel's 2-bit index.
+
+ Creating the 4 colors used in the 4-entry lookup table from the
+ 32-bit base colors (when lerp = 1):
+
+ For texel 31 to texel 16
+ Color[0] = color2[a,r,g,b]
+ Color[1] = (2 * color2[a,r,g,b] + color1[a,r,g,b] + 1) / 3
+ Color[2] = (color2[a,r,g,b] + 2 * color1[a,r,g,b] +1) / 3
+ Color[3] = color1[a,r,g,b]
+
+ For texel 15 to texel 0
+ Color[0] = color0[a,r,g,b]
+ Color[1] = (2 * color0[a,r,g,b] + color1[a,r,g,b] +1) / 3
+ Color[2] = (color0[a,r,g,b] + 2 * color1[a,r,g,b] +1) / 3
+ Color[3] = color1[a,r,g,b]
+
+ Table Lookup (when lerp = 1):
+
+ Index of texel 31 to 0 Color for texel 31 to texel 0
+ (ARGB8888)
+
+ 0 color[0]
+ 1 color[1]
+ 2 color[2]
+ 3 color[3]
+
+Revision History
+
+ 0.1, 01/12/00 dwm: Initial revision.
+ 0.2, 02/09/00 dwm: Respond to feedback from Intel.
+ 0.3, 02/23/00 dwm: Respond to feedback from Intel.
+ 0.4, 04/12/00 dwm: Updated to reflect final version of the
+ ARB_texture_compression extension.
+
+
+Copyright 1999-2000, 3dfx Interactive, Inc.
+All rights reserved.
--- /dev/null
+Name
+
+ EXT_texture_compression_s3tc
+
+Name Strings
+
+ GL_EXT_texture_compression_s3tc
+
+Contact
+
+ Pat Brown, Intel Corporation (patrick.r.brown 'at' intel.com)
+
+Status
+
+ CANDIDATE FOR FINAL DRAFT -- NOT YET COMPLETE
+
+Version
+
+ Draft 0.7, 11 April 2000
+
+Number
+
+ 198
+
+Dependencies
+
+ OpenGL 1.1 is required.
+
+ GL_ARB_texture_compression is required.
+
+ This extension is written against the OpenGL 1.2.1 Specification.
+
+Overview
+
+ This extension provides additional texture compression functionality
+ specific to S3's S3TC format (called DXTC in Microsoft's DirectX API),
+ subject to all the requirements and limitations described by the extension
+ GL_ARB_texture_compression.
+
+ This extension supports DXT1, DXT3, and DXT5 texture compression formats.
+ For the DXT1 image format, this specification supports an RGB-only mode
+ and a special RGBA mode with single-bit "transparent" alpha.
+
+IP Status
+
+ Contact S3 Incorporated (http://www.s3.com) regarding any intellectual
+ property issues associated with implementing this extension.
+
+ WARNING: Vendors able to support S3TC texture compression in Direct3D
+ drivers do not necessarily have the right to use the same functionality in
+ OpenGL.
+
+Issues
+
+ (1) Should DXT2 and DXT4 (premultiplied alpha) formats be supported?
+
+ RESOLVED: No -- insufficient interest. Supporting DXT2 and DXT4
+ would require some rework to the TexEnv definition (maybe add a new
+ base internal format RGBA_PREMULTIPLIED_ALPHA) for these formats.
+ Note that the EXT_texture_env_combine extension (which extends normal
+ TexEnv modes) can be used to support textures with premultipled alpha.
+
+ (2) Should generic "RGB_S3TC_EXT" and "RGBA_S3TC_EXT" enums be supported
+ or should we use only the DXT<n> enums?
+
+ RESOLVED: No. A generic RGBA_S3TC_EXT is problematic because DXT3
+ and DXT5 are both nominally RGBA (and DXT1 with the 1-bit alpha is
+ also) yet one format must be chosen up front.
+
+ (3) Should TexSubImage support all block-aligned edits or just the minimal
+ functionality required by the the ARB_texture_compression extension?
+
+ RESOLVED: Allow all valid block-aligned edits.
+
+ (4) A pre-compressed image with a DXT1 format can be used as either an
+ RGB_S3TC_DXT1 or an RGBA_S3TC_DXT1 image. If the image has
+ transparent texels, how are they treated in each format?
+
+ RESOLVED: The renderer has to make sure that an RGB_S3TC_DXT1 format
+ is decoded as RGB (where alpha is effectively one for all texels),
+ while RGBA_S3TC_DXT1 is decoded as RGBA (where alpha is zero for all
+ texels with "transparent" encodings). Otherwise, the formats are
+ identical.
+
+ (5) Is the encoding of the RGB components for DXT1 formats correct in this
+ spec? MSDN documentation does not specify an RGB color for the
+ "transparent" encoding. Is it really black?
+
+ RESOLVED: Yes. The specification for the DXT1 format initially
+ required black, but later changed that requirement to a
+ recommendation. All vendors involved in the definition of this
+ specification support black. In addition, specifying black has a
+ useful behavior.
+
+ When blending multiple texels (GL_LINEAR filtering), mixing opaque and
+ transparent samples is problematic. Defining a black color on
+ transparent texels achieves a sensible result that works like a
+ texture with premultiplied alpha. For example, if three opaque white
+ and one transparent sample is being averaged, the result would be a
+ 75% intensity gray (with an alpha of 75%). This is the same result on
+ the color channels as would be obtained using a white color, 75%
+ alpha, and a SRC_ALPHA blend factor.
+
+ (6) Is the encoding of the RGB components for DXT3 and DXT5 formats
+ correct in this spec? MSDN documentation suggests that the RGB blocks
+ for DXT3 and DXT5 are decoded as described the the DXT1 format.
+
+ RESOLVED: Yes -- this appears to be a bug in the MSDN documentation.
+ The specification for the DXT2-DXT5 formats require decoding using the
+ opaque block encoding, regardless of the relative values of "color0"
+ and "color1".
+
+New Procedures and Functions
+
+ None.
+
+New Tokens
+
+ Accepted by the <internalformat> parameter of TexImage2D, CopyTexImage2D,
+ and CompressedTexImage2DARB and the <format> parameter of
+ CompressedTexSubImage2DARB:
+
+ COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
+ COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
+ COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
+ COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
+
+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 (Rasterization)
+
+ Add to Table 3.16.1: Specific Compressed Internal Formats
+
+ Compressed Internal Format Base Internal Format
+ ========================== ====================
+ COMPRESSED_RGB_S3TC_DXT1_EXT RGB
+ COMPRESSED_RGBA_S3TC_DXT1_EXT RGBA
+ COMPRESSED_RGBA_S3TC_DXT3_EXT RGBA
+ COMPRESSED_RGBA_S3TC_DXT5_EXT RGBA
+
+
+ Modify Section 3.8.2, Alternate Image Specification
+
+ (add to end of TexSubImage discussion, p.123 -- after edit from the
+ ARB_texture_compression spec)
+
+ If the internal format of the texture image being modified is
+ COMPRESSED_RGB_S3TC_DXT1_EXT, COMPRESSED_RGBA_S3TC_DXT1_EXT,
+ COMPRESSED_RGBA_S3TC_DXT3_EXT, or COMPRESSED_RGBA_S3TC_DXT5_EXT, the
+ texture is stored using one of the several S3TC compressed texture image
+ formats. Such images are easily edited along 4x4 texel boundaries, so the
+ limitations on TexSubImage2D or CopyTexSubImage2D parameters are relaxed.
+ TexSubImage2D and CopyTexSubImage2D will result in an INVALID_OPERATION
+ error only if one of the following conditions occurs:
+
+ * <width> is not a multiple of four or equal to TEXTURE_WIDTH.
+ * <height> is not a multiple of four or equal to TEXTURE_HEIGHT.
+ * <xoffset> or <yoffset> is not a multiple of four.
+
+
+ Add to Section 3.8.2, Alternate Image Specification (adding to the end of
+ the CompressedTexImage section introduced by the ARB_texture_compression
+ spec)
+
+ If <internalformat> is COMPRESSED_RGB_S3TC_DXT1_EXT,
+ COMPRESSED_RGBA_S3TC_DXT1_EXT, COMPRESSED_RGBA_S3TC_DXT3_EXT, or
+ COMPRESSED_RGBA_S3TC_DXT5_EXT, the compressed texture is stored using one
+ of several S3TC compressed texture image formats. The S3TC texture
+ compression algorithm supports only 2D images without borders.
+ CompressedTexImage1DARB and CompressedTexImage3DARB produce an
+ INVALID_ENUM error if <internalformat> is an S3TC format.
+ CompressedTexImage2DARB will produce an INVALID_OPERATION error if
+ <border> is non-zero.
+
+
+ Add to Section 3.8.2, Alternate Image Specification (adding to the end of
+ the CompressedTexSubImage section introduced by the
+ ARB_texture_compression spec)
+
+ If the internal format of the texture image being modified is
+ COMPRESSED_RGB_S3TC_DXT1_EXT, COMPRESSED_RGBA_S3TC_DXT1_EXT,
+ COMPRESSED_RGBA_S3TC_DXT3_EXT, or COMPRESSED_RGBA_S3TC_DXT5_EXT, the
+ texture is stored using one of the several S3TC compressed texture image
+ formats. Since the S3TC texture compression algorithm supports only 2D
+ images, CompressedTexSubImage1DARB and CompressedTexSubImage3DARB produce
+ an INVALID_ENUM error if <format> is an S3TC format. Since S3TC images
+ are easily edited along 4x4 texel boundaries, the limitations on
+ CompressedTexSubImage2D are relaxed. CompressedTexSubImage2D will result
+ in an INVALID_OPERATION error only if one of the following conditions
+ occurs:
+
+ * <width> is not a multiple of four or equal to TEXTURE_WIDTH.
+ * <height> is not a multiple of four or equal to TEXTURE_HEIGHT.
+ * <xoffset> or <yoffset> is not a multiple of four.
+
+
+Additions to Chapter 4 of the OpenGL 1.2.1 Specification (Per-Fragment
+Operations and the Frame Buffer)
+
+ None.
+
+Additions to Chapter 5 of the OpenGL 1.2.1 Specification (Special Functions)
+
+ None.
+
+Additions to Chapter 6 of the OpenGL 1.2.1 Specification (State and
+State Requests)
+
+ None.
+
+Additions to Appendix A of the OpenGL 1.2.1 Specification (Invariance)
+
+ None.
+
+Additions to the AGL/GLX/WGL Specifications
+
+ None.
+
+GLX Protocol
+
+ None.
+
+Errors
+
+ INVALID_ENUM is generated by CompressedTexImage1DARB or
+ CompressedTexImage3DARB if <internalformat> is
+ COMPRESSED_RGB_S3TC_DXT1_EXT, COMPRESSED_RGBA_S3TC_DXT1_EXT,
+ COMPRESSED_RGBA_S3TC_DXT3_EXT, or COMPRESSED_RGBA_S3TC_DXT5_EXT.
+
+ INVALID_OPERATION is generated by CompressedTexImage2DARB if if
+ <internalformat> is COMPRESSED_RGB_S3TC_DXT1_EXT,
+ COMPRESSED_RGBA_S3TC_DXT1_EXT, COMPRESSED_RGBA_S3TC_DXT3_EXT, or
+ COMPRESSED_RGBA_S3TC_DXT5_EXT and <border> is not equal to zero.
+
+ INVALID_ENUM is generated by CompressedTexSubImage1DARB or
+ CompressedTexSubImage3DARB if <format> is COMPRESSED_RGB_S3TC_DXT1_EXT,
+ COMPRESSED_RGBA_S3TC_DXT1_EXT, COMPRESSED_RGBA_S3TC_DXT3_EXT, or
+ COMPRESSED_RGBA_S3TC_DXT5_EXT.
+
+ INVALID_OPERATION is generated by TexSubImage2D CopyTexSubImage2D, or
+ CompressedTexSubImage2D if INTERNAL_FORMAT is
+ COMPRESSED_RGB_S3TC_DXT1_EXT, COMPRESSED_RGBA_S3TC_DXT1_EXT,
+ COMPRESSED_RGBA_S3TC_DXT3_EXT, or COMPRESSED_RGBA_S3TC_DXT5_EXT and any of
+ the following apply: <width> is not a multiple of four or equal to
+ TEXTURE_WIDTH; <height> is not a multiple of four or equal to
+ TEXTURE_HEIGHT; <xoffset> or <yoffset> is not a multiple of four.
+
+
+ The following restrictions from the ARB_texture_compression specification
+ do not apply to S3TC texture formats, since subimage modification is
+ straightforward as long as the subimage is properly aligned.
+
+ DELETE: INVALID_OPERATION is generated by TexSubImage1D, TexSubImage2D,
+ DELETE: TexSubImage3D, CopyTexSubImage1D, CopyTexSubImage2D, or
+ DELETE: CopyTexSubImage3D if the internal format of the texture image is
+ DELETE: compressed and <xoffset>, <yoffset>, or <zoffset> does not equal
+ DELETE: -b, where b is value of TEXTURE_BORDER.
+
+ DELETE: INVALID_VALUE is generated by CompressedTexSubImage1DARB,
+ DELETE: CompressedTexSubImage2DARB, or CompressedTexSubImage3DARB if the
+ DELETE: entire texture image is not being edited: if <xoffset>,
+ DELETE: <yoffset>, or <zoffset> is greater than -b, <xoffset> + <width> is
+ DELETE: less than w+b, <yoffset> + <height> is less than h+b, or <zoffset>
+ DELETE: + <depth> is less than d+b, where b is the value of
+ DELETE: TEXTURE_BORDER, w is the value of TEXTURE_WIDTH, h is the value of
+ DELETE: TEXTURE_HEIGHT, and d is the value of TEXTURE_DEPTH.
+
+ See also errors in the GL_ARB_texture_compression specification.
+
+New State
+
+ None.
+
+Appendix
+
+ S3TC Compressed Texture Image Formats
+
+ Compressed texture images stored using the S3TC compressed image formats
+ are represented as a collection of 4x4 texel blocks, where each block
+ contains 64 or 128 bits of texel data. The image is encoded as a normal
+ 2D raster image in which each 4x4 block is treated as a single pixel. If
+ an S3TC image has a width or height less than four, the data corresponding
+ to texels outside the image are irrelevant and undefined.
+
+ When an S3TC image with a width of <w>, height of <h>, and block size of
+ <blocksize> (8 or 16 bytes) is decoded, the corresponding image size (in
+ bytes) is:
+
+ ceil(<w>/4) * ceil(<h>/4) * blocksize.
+
+ When decoding an S3TC image, the block containing the texel at offset
+ (<x>, <y>) begins at an offset (in bytes) relative to the beginning of the
+ image of:
+
+ blocksize * (ceil(<w>/4) * floor(<y>/4) + floor(<x>/4)).
+
+
+ There are four distinct S3TC image formats:
+
+ COMPRESSED_RGB_S3TC_DXT1_EXT: Each 4x4 block of texels consists of 64
+ bits of RGB image data.
+
+ Each RGB image data block is encoded as a sequence of 8 bytes, called (in
+ order of increasing address):
+
+ c0_lo, c0_hi, c1_lo, c1_hi, bits_0, bits_1, bits_2, bits_3
+
+ The 8 bytes of the block are decoded into three quantities:
+
+ color0 = c0_lo + c0_hi * 256
+ color1 = c1_lo + c1_hi * 256
+ bits = bits_0 + 256 * (bits_1 + 256 * (bits_2 + 256 * bits_3))
+
+ color0 and color1 are 16-bit unsigned integers that are unpacked to
+ RGB colors RGB0 and RGB1 as though they were 16-bit packed pixels with
+ a <format> of RGB and a type of UNSIGNED_SHORT_5_6_5.
+
+ bits is a 32-bit unsigned integer, from which a two-bit control code
+ is extracted for a texel at location (x,y) in the block using:
+
+ code(x,y) = bits[2*(4*y+x)+1..2*(4*y+x)+0]
+
+ where bit 31 is the most significant and bit 0 is the least
+ significant bit.
+
+ The RGB color for a texel at location (x,y) in the block is given by:
+
+ RGB0, if color0 > color1 and code(x,y) == 0
+ RGB1, if color0 > color1 and code(x,y) == 1
+ (2*RGB0+RGB1)/3, if color0 > color1 and code(x,y) == 2
+ (RGB0+2*RGB1)/3, if color0 > color1 and code(x,y) == 3
+
+ RGB0, if color0 <= color1 and code(x,y) == 0
+ RGB1, if color0 <= color1 and code(x,y) == 1
+ (RGB0+RGB1)/2, if color0 <= color1 and code(x,y) == 2
+ BLACK, if color0 <= color1 and code(x,y) == 3
+
+ Arithmetic operations are done per component, and BLACK refers to an
+ RGB color where red, green, and blue are all zero.
+
+ Since this image has an RGB format, there is no alpha component and the
+ image is considered fully opaque.
+
+
+ COMPRESSED_RGBA_S3TC_DXT1_EXT: Each 4x4 block of texels consists of 64
+ bits of RGB image data and minimal alpha information. The RGB components
+ of a texel are extracted in the same way as COMPRESSED_RGB_S3TC_DXT1_EXT.
+
+ The alpha component for a texel at location (x,y) in the block is
+ given by:
+
+ 0.0, if color0 <= color1 and code(x,y) == 3
+ 1.0, otherwise
+
+ IMPORTANT: When encoding an RGBA image into a format using 1-bit
+ alpha, any texels with an alpha component less than 0.5 end up with an
+ alpha of 0.0 and any texels with an alpha component greater than or
+ equal to 0.5 end up with an alpha of 1.0. When encoding an RGBA image
+ into the COMPRESSED_RGBA_S3TC_DXT1_EXT format, the resulting red,
+ green, and blue components of any texels with a final alpha of 0.0
+ will automatically be zero (black). If this behavior is not desired
+ by an application, it should not use COMPRESSED_RGBA_S3TC_DXT1_EXT.
+ This format will never be used when a generic compressed internal
+ format (Table 3.16.2) is specified, although the nearly identical
+ format COMPRESSED_RGB_S3TC_DXT1_EXT (above) may be.
+
+
+ COMPRESSED_RGBA_S3TC_DXT3_EXT: Each 4x4 block of texels consists of 64
+ bits of uncompressed alpha image data followed by 64 bits of RGB image
+ data.
+
+ Each RGB image data block is encoded according to the
+ COMPRESSED_RGB_S3TC_DXT1_EXT format, with the exception that the two code
+ bits always use the non-transparent encodings. In other words, they are
+ treated as though color0 > color1, regardless of the actual values of
+ color0 and color1.
+
+ Each alpha image data block is encoded as a sequence of 8 bytes, called
+ (in order of increasing address):
+
+ a0, a1, a2, a3, a4, a5, a6, a7
+
+ The 8 bytes of the block are decoded into one 64-bit integer:
+
+ alpha = a0 + 256 * (a1 + 256 * (a2 + 256 * (a3 + 256 * (a4 +
+ 256 * (a5 + 256 * (a6 + 256 * a7))))))
+
+ alpha is a 64-bit unsigned integer, from which a four-bit alpha value
+ is extracted for a texel at location (x,y) in the block using:
+
+ alpha(x,y) = bits[4*(4*y+x)+3..4*(4*y+x)+0]
+
+ where bit 63 is the most significant and bit 0 is the least
+ significant bit.
+
+ The alpha component for a texel at location (x,y) in the block is
+ given by alpha(x,y) / 15.
+
+
+ COMPRESSED_RGBA_S3TC_DXT5_EXT: Each 4x4 block of texels consists of 64
+ bits of compressed alpha image data followed by 64 bits of RGB image data.
+
+ Each RGB image data block is encoded according to the
+ COMPRESSED_RGB_S3TC_DXT1_EXT format, with the exception that the two code
+ bits always use the non-transparent encodings. In other words, they are
+ treated as though color0 > color1, regardless of the actual values of
+ color0 and color1.
+
+ Each alpha image data block is encoded as a sequence of 8 bytes, called
+ (in order of increasing address):
+
+ alpha0, alpha1, bits_0, bits_1, bits_2, bits_3, bits_4, bits_5
+
+ The alpha0 and alpha1 are 8-bit unsigned bytesw converted to alpha
+ components by multiplying by 1/255.
+
+ The 6 "bits" bytes of the block are decoded into one 48-bit integer:
+
+ bits = bits_0 + 256 * (bits_1 + 256 * (bits_2 + 256 * (bits_3 +
+ 256 * (bits_4 + 256 * bits_5))))
+
+ bits is a 48-bit unsigned integer, from which a three-bit control code
+ is extracted for a texel at location (x,y) in the block using:
+
+ code(x,y) = bits[3*(4*y+x)+1..3*(4*y+x)+0]
+
+ where bit 47 is the most significant and bit 0 is the least
+ significant bit.
+
+ The alpha component for a texel at location (x,y) in the block is
+ given by:
+
+ alpha0, code(x,y) == 0
+ alpha1, code(x,y) == 1
+
+ (6*alpha0 + 1*alpha1)/7, alpha0 > alpha1 and code(x,y) == 2
+ (5*alpha0 + 2*alpha1)/7, alpha0 > alpha1 and code(x,y) == 3
+ (4*alpha0 + 3*alpha1)/7, alpha0 > alpha1 and code(x,y) == 4
+ (3*alpha0 + 4*alpha1)/7, alpha0 > alpha1 and code(x,y) == 5
+ (2*alpha0 + 5*alpha1)/7, alpha0 > alpha1 and code(x,y) == 6
+ (1*alpha0 + 6*alpha1)/7, alpha0 > alpha1 and code(x,y) == 7
+
+ (4*alpha0 + 1*alpha1)/5, alpha0 <= alpha1 and code(x,y) == 2
+ (3*alpha0 + 2*alpha1)/5, alpha0 <= alpha1 and code(x,y) == 3
+ (2*alpha0 + 3*alpha1)/5, alpha0 <= alpha1 and code(x,y) == 4
+ (1*alpha0 + 4*alpha1)/5, alpha0 <= alpha1 and code(x,y) == 5
+ 0.0, alpha0 <= alpha1 and code(x,y) == 6
+ 1.0, alpha0 <= alpha1 and code(x,y) == 7
+
+
+Revision History
+
+ 0.7, 04/11/00 prbrown1: Added issues on DXT1, DXT3, and DXT5 encodings
+ where the MSDN documentation doesn't match what
+ is really done. Added enum values from the
+ extension registry.
+
+ 0.4, 03/28/00 prbrown1: Updated to reflect final version of the
+ ARB_texture_compression extension. Allowed
+ block-aligned TexSubImage calls.
+
+ 0.3, 03/07/00 prbrown1: Resolved issues pertaining to the format of RGB
+ blocks in the DXT3 and DXT5 formats (they don't
+ ever use the "transparent" encoding). Fixed
+ decoding of DXT1 blocks. Pointed out issue of
+ "transparent" texels in DXT1 encodings having
+ different behaviors for RGB and RGBA internal
+ formats.
+
+ 0.2, 02/23/00 prbrown1: Minor revisions; added several issues.
+
+ 0.11, 02/17/00 prbrown1: Slight modification to error semantics
+ (INVALID_ENUM instead of INVALID_OPERATION).
+
+ 0.1, 02/15/00 prbrown1: Initial revision.
--- /dev/null
+/*
+ * FXT1 codec
+ * Version: 1.0
+ *
+ * Copyright (C) 2004 Daniel Borca All Rights Reserved.
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+Problem:
+~~~~~~~~
+having 3 points P1(x1, y1), P2(x2, y2) and P3(x3, y3), we need to find
+a point P(x, y) on the P1-P2 line, so that distance form P3 to that P is
+minimal. we shall use the oblong squared distance function:
+ d(P1, P2) = (X*(x2 - x1))^ + (Y*(y2 - y1))^
+
+Solution:
+~~~~~~~~~
+analytical equation of P1-P2 line:
+ x - x1 y - y1
+ ------- = ------- = t
+ x2 - x1 y2 - y1
+
+ or
+
+ x = t * (x2 - x1) + x1
+ y = t * (y2 - y1) + y1
+
+ where
+
+ x1 <= x <= x2 ==> 0 <= t <= 1
+
+thus d(P3, P) will be:
+ d = (X*(x3 - x))^ + (Y*(y3 - y))^
+ = (X*(x3 - (t * (x2 - x1) + x1)))^ + (Y*(y3 - (t * (x2 - x1) + x1)))^
+ = X^*(x3 - x1)^ + Y^*(y3 - y1)^
+ - 2 * t * (X^*(x3 - x1)*dx + Y^*(y3 - y1)*dy)
+ + t^ * (X^*dx^ + Y^*dy^)
+
+ where dx = (x2 - x1) and dy = (y2 - y1)
+
+given the function f = C + Bt + At^, we can find its extrema by using the
+first derivative:
+ (f' = 2At + B) = 0 when t = -B / 2A
+
+having that said, d will have a minimum at:
+ X^*(x3 - x1)*dx + Y^*(y3 - y1)*dy
+ tmin = ---------------------------------
+ X^*dx^ + Y^*dy^
+
+ X^*dx Y^*dy x1*X^*dx + y1*Y^*dy
+ = x3 * --------------- + y3 * --------------- - -------------------
+ X^*dx^ + Y^*dy^ X^*dx^ + Y^*dy^ X^*dx^ + Y^*dy^
+
+we can note:
+ X^*dx Y^*dy
+ ivec = ( ---------------, --------------- )
+ X^*dx^ + Y^*dy^ X^*dx^ + Y^*dy^
+
+ x1*X^*dx + y1*Y^*dy
+ base = - -------------------
+ X^*dx^ + Y^*dy^
+
+ tmin = ivecx * x3 + ivecy * y3 + base
+
+discretizing the line with N equidistant points, we scale:
+ N * X^*dx N * Y^*dy
+ iv = ( ---------------, --------------- )
+ X^*dx^ + Y^*dy^ X^*dx^ + Y^*dy^
+
+ x1*X^*dx + y1*Y^*dy
+ b = - N * -------------------
+ X^*dx^ + Y^*dy^
+
+ n = (iv . P3) + b
+
+ Note1: this formula stands for n-component vector
+ Note2: (int)n = {0, 1, ... N}, because 0 <= t <= 1
+ Note3: when X=Y=1, d is squared euclidean distance!
--- /dev/null
+/*
+ * DXTn codec
+ * Version: 1.1
+ *
+ * Copyright (C) 2004 Daniel Borca All Rights Reserved.
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "types.h"
+#include "internal.h"
+#include "dxtn.h"
+
+
+/***************************************************************************\
+ * DXTn encoder
+ *
+ * The encoder was built by reversing the decoder,
+ * and is vaguely based on FXT1 codec. Note that this code
+ * is merely a proof of concept, since it is highly UNoptimized!
+\***************************************************************************/
+
+
+#define MAX_COMP 4 /* ever needed maximum number of components in texel */
+#define MAX_VECT 4 /* ever needed maximum number of base vectors to find */
+#define N_TEXELS 16 /* number of texels in a block (always 16) */
+#define COLOR565(v) (word)((((v)[RCOMP] & 0xf8) << 8) | (((v)[GCOMP] & 0xfc) << 3) | ((v)[BCOMP] >> 3))
+
+
+static const int dxtn_color_tlat[2][4] = {
+ { 0, 2, 3, 1 },
+ { 0, 2, 1, 3 }
+};
+
+static const int dxtn_alpha_tlat[2][8] = {
+ { 0, 2, 3, 4, 5, 6, 7, 1 },
+ { 0, 2, 3, 4, 5, 1, 6, 7 }
+};
+
+
+static void
+dxt1_rgb_quantize (dword *cc, const byte *lines[], int comps)
+{
+ float b, iv[MAX_COMP]; /* interpolation vector */
+
+ dword hi; /* high doubleword */
+ int color0, color1;
+ int n_vect;
+ const int n_comp = 3;
+ int black = 0;
+
+ int minSum = 2000; /* big enough */
+ int maxSum = -1; /* small enough */
+ int minCol = 0; /* phoudoin: silent compiler! */
+ int maxCol = 0; /* phoudoin: silent compiler! */
+
+ byte input[N_TEXELS][MAX_COMP];
+ int i, k, l;
+
+ /* make the whole block opaque */
+ /* we will NEVER reference ACOMP of any pixel */
+
+ /* 4 texels each line */
+ for (l = 0; l < 4; l++) {
+ for (k = 0; k < 4; k++) {
+ for (i = 0; i < comps; i++) {
+ input[k + l * 4][i] = *lines[l]++;
+ }
+ }
+ }
+
+ /* Our solution here is to find the darkest and brightest colors in
+ * the 4x4 tile and use those as the two representative colors.
+ * There are probably better algorithms to use (histogram-based).
+ */
+ for (k = 0; k < N_TEXELS; k++) {
+ int sum = 0;
+ for (i = 0; i < n_comp; i++) {
+ sum += input[k][i];
+ }
+ if (minSum > sum) {
+ minSum = sum;
+ minCol = k;
+ }
+ if (maxSum < sum) {
+ maxSum = sum;
+ maxCol = k;
+ }
+ if (sum == 0) {
+ black = 1;
+ }
+ }
+
+ color0 = COLOR565(input[minCol]);
+ color1 = COLOR565(input[maxCol]);
+
+ if (color0 == color1) {
+ /* we'll use 3-vector */
+ cc[0] = color0 | (color1 << 16);
+ hi = black ? -1 : 0;
+ } else {
+ if (black && ((color0 == 0) || (color1 == 0))) {
+ /* we still can use 4-vector */
+ black = 0;
+ }
+
+ if (black ^ (color0 <= color1)) {
+ int aux;
+ aux = color0;
+ color0 = color1;
+ color1 = aux;
+ aux = minCol;
+ minCol = maxCol;
+ maxCol = aux;
+ }
+ n_vect = (color0 <= color1) ? 2 : 3;
+
+ MAKEIVEC(n_vect, n_comp, iv, b, input[minCol], input[maxCol]);
+
+ /* add in texels */
+ cc[0] = color0 | (color1 << 16);
+ hi = 0;
+ for (k = N_TEXELS - 1; k >= 0; k--) {
+ int texel = 3;
+ int sum = 0;
+ if (black) {
+ for (i = 0; i < n_comp; i++) {
+ sum += input[k][i];
+ }
+ }
+ if (!black || sum) {
+ /* interpolate color */
+ CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
+ texel = dxtn_color_tlat[black][texel];
+ }
+ /* add in texel */
+ hi <<= 2;
+ hi |= texel;
+ }
+ }
+ cc[1] = hi;
+}
+
+
+static void
+dxt1_rgba_quantize (dword *cc, const byte *lines[], int comps)
+{
+ float b, iv[MAX_COMP]; /* interpolation vector */
+
+ dword hi; /* high doubleword */
+ int color0, color1;
+ int n_vect;
+ const int n_comp = 3;
+ int transparent = 0;
+
+ int minSum = 2000; /* big enough */
+ int maxSum = -1; /* small enough */
+ int minCol = 0; /* phoudoin: silent compiler! */
+ int maxCol = 0; /* phoudoin: silent compiler! */
+
+ byte input[N_TEXELS][MAX_COMP];
+ int i, k, l;
+
+ if (comps == 3) {
+ /* make the whole block opaque */
+ memset(input, -1, sizeof(input));
+ }
+
+ /* 4 texels each line */
+ for (l = 0; l < 4; l++) {
+ for (k = 0; k < 4; k++) {
+ for (i = 0; i < comps; i++) {
+ input[k + l * 4][i] = *lines[l]++;
+ }
+ }
+ }
+
+ /* Our solution here is to find the darkest and brightest colors in
+ * the 4x4 tile and use those as the two representative colors.
+ * There are probably better algorithms to use (histogram-based).
+ */
+ for (k = 0; k < N_TEXELS; k++) {
+ int sum = 0;
+ for (i = 0; i < n_comp; i++) {
+ sum += input[k][i];
+ }
+ if (minSum > sum) {
+ minSum = sum;
+ minCol = k;
+ }
+ if (maxSum < sum) {
+ maxSum = sum;
+ maxCol = k;
+ }
+ if (input[k][ACOMP] < 128) {
+ transparent = 1;
+ }
+ }
+
+ color0 = COLOR565(input[minCol]);
+ color1 = COLOR565(input[maxCol]);
+
+ if (color0 == color1) {
+ /* we'll use 3-vector */
+ cc[0] = color0 | (color1 << 16);
+ hi = transparent ? -1 : 0;
+ } else {
+ if (transparent ^ (color0 <= color1)) {
+ int aux;
+ aux = color0;
+ color0 = color1;
+ color1 = aux;
+ aux = minCol;
+ minCol = maxCol;
+ maxCol = aux;
+ }
+ n_vect = (color0 <= color1) ? 2 : 3;
+
+ MAKEIVEC(n_vect, n_comp, iv, b, input[minCol], input[maxCol]);
+
+ /* add in texels */
+ cc[0] = color0 | (color1 << 16);
+ hi = 0;
+ for (k = N_TEXELS - 1; k >= 0; k--) {
+ int texel = 3;
+ if (input[k][ACOMP] >= 128) {
+ /* interpolate color */
+ CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
+ texel = dxtn_color_tlat[transparent][texel];
+ }
+ /* add in texel */
+ hi <<= 2;
+ hi |= texel;
+ }
+ }
+ cc[1] = hi;
+}
+
+
+static void
+dxt3_rgba_quantize (dword *cc, const byte *lines[], int comps)
+{
+ float b, iv[MAX_COMP]; /* interpolation vector */
+
+ dword lolo, lohi; /* low quadword: lo dword, hi dword */
+ dword hihi; /* high quadword: high dword */
+ int color0, color1;
+ const int n_vect = 3;
+ const int n_comp = 3;
+
+ int minSum = 2000; /* big enough */
+ int maxSum = -1; /* small enough */
+ int minCol = 0; /* phoudoin: silent compiler! */
+ int maxCol = 0; /* phoudoin: silent compiler! */
+
+ byte input[N_TEXELS][MAX_COMP];
+ int i, k, l;
+
+ if (comps == 3) {
+ /* make the whole block opaque */
+ memset(input, -1, sizeof(input));
+ }
+
+ /* 4 texels each line */
+ for (l = 0; l < 4; l++) {
+ for (k = 0; k < 4; k++) {
+ for (i = 0; i < comps; i++) {
+ input[k + l * 4][i] = *lines[l]++;
+ }
+ }
+ }
+
+ /* Our solution here is to find the darkest and brightest colors in
+ * the 4x4 tile and use those as the two representative colors.
+ * There are probably better algorithms to use (histogram-based).
+ */
+ for (k = 0; k < N_TEXELS; k++) {
+ int sum = 0;
+ for (i = 0; i < n_comp; i++) {
+ sum += input[k][i];
+ }
+ if (minSum > sum) {
+ minSum = sum;
+ minCol = k;
+ }
+ if (maxSum < sum) {
+ maxSum = sum;
+ maxCol = k;
+ }
+ }
+
+ /* add in alphas */
+ lolo = lohi = 0;
+ for (k = N_TEXELS - 1; k >= N_TEXELS / 2; k--) {
+ /* add in alpha */
+ lohi <<= 4;
+ lohi |= input[k][ACOMP] >> 4;
+ }
+ cc[1] = lohi;
+ for (; k >= 0; k--) {
+ /* add in alpha */
+ lolo <<= 4;
+ lolo |= input[k][ACOMP] >> 4;
+ }
+ cc[0] = lolo;
+
+ color0 = COLOR565(input[minCol]);
+ color1 = COLOR565(input[maxCol]);
+ cc[2] = color0 | (color1 << 16);
+
+ hihi = 0;
+ if (color0 != color1) {
+ MAKEIVEC(n_vect, n_comp, iv, b, input[minCol], input[maxCol]);
+
+ /* add in texels */
+ for (k = N_TEXELS - 1; k >= 0; k--) {
+ int texel;
+ /* interpolate color */
+ CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
+ texel = dxtn_color_tlat[0][texel];
+ /* add in texel */
+ hihi <<= 2;
+ hihi |= texel;
+ }
+ }
+ cc[3] = hihi;
+}
+
+
+static void
+dxt5_rgba_quantize (dword *cc, const byte *lines[], int comps)
+{
+ float b, iv[MAX_COMP]; /* interpolation vector */
+
+ qword lo; /* low quadword */
+ dword hihi; /* high quadword: high dword */
+ int color0, color1;
+ const int n_vect = 3;
+ const int n_comp = 3;
+
+ int minSum = 2000; /* big enough */
+ int maxSum = -1; /* small enough */
+ int minCol = 0; /* phoudoin: silent compiler! */
+ int maxCol = 0; /* phoudoin: silent compiler! */
+ int alpha0 = 2000; /* big enough */
+ int alpha1 = -1; /* small enough */
+ int anyZero = 0, anyOne = 0;
+ int a_vect;
+
+ byte input[N_TEXELS][MAX_COMP];
+ int i, k, l;
+
+ if (comps == 3) {
+ /* make the whole block opaque */
+ memset(input, -1, sizeof(input));
+ }
+
+ /* 4 texels each line */
+ for (l = 0; l < 4; l++) {
+ for (k = 0; k < 4; k++) {
+ for (i = 0; i < comps; i++) {
+ input[k + l * 4][i] = *lines[l]++;
+ }
+ }
+ }
+
+ /* Our solution here is to find the darkest and brightest colors in
+ * the 4x4 tile and use those as the two representative colors.
+ * There are probably better algorithms to use (histogram-based).
+ */
+ for (k = 0; k < N_TEXELS; k++) {
+ int sum = 0;
+ for (i = 0; i < n_comp; i++) {
+ sum += input[k][i];
+ }
+ if (minSum > sum) {
+ minSum = sum;
+ minCol = k;
+ }
+ if (maxSum < sum) {
+ maxSum = sum;
+ maxCol = k;
+ }
+ if (alpha0 > input[k][ACOMP]) {
+ alpha0 = input[k][ACOMP];
+ }
+ if (alpha1 < input[k][ACOMP]) {
+ alpha1 = input[k][ACOMP];
+ }
+ if (input[k][ACOMP] == 0) {
+ anyZero = 1;
+ }
+ if (input[k][ACOMP] == 255) {
+ anyOne = 1;
+ }
+ }
+
+ /* add in alphas */
+ if (alpha0 == alpha1) {
+ /* we'll use 6-vector */
+ cc[0] = alpha0 | (alpha1 << 8);
+ cc[1] = 0;
+ } else {
+ if (anyZero && ((alpha0 == 0) || (alpha1 == 0))) {
+ /* we still might use 8-vector */
+ anyZero = 0;
+ }
+ if (anyOne && ((alpha0 == 255) || (alpha1 == 255))) {
+ /* we still might use 8-vector */
+ anyOne = 0;
+ }
+ if ((anyZero | anyOne) ^ (alpha0 <= alpha1)) {
+ int aux;
+ aux = alpha0;
+ alpha0 = alpha1;
+ alpha1 = aux;
+ }
+ a_vect = (alpha0 <= alpha1) ? 5 : 7;
+
+ /* compute interpolation vector */
+ iv[ACOMP] = (float)a_vect / (alpha1 - alpha0);
+ b = -iv[ACOMP] * alpha0 + 0.5F;
+
+ /* add in alphas */
+ Q_MOV32(lo, 0);
+ for (k = N_TEXELS - 1; k >= 0; k--) {
+ int texel = -1;
+ if (anyZero | anyOne) {
+ if (input[k][ACOMP] == 0) {
+ texel = 6;
+ } else if (input[k][ACOMP] == 255) {
+ texel = 7;
+ }
+ }
+ /* interpolate alpha */
+ if (texel == -1) {
+ float dot = input[k][ACOMP] * iv[ACOMP];
+ texel = (int)(dot + b);
+#if SAFECDOT
+ if (texel < 0) {
+ texel = 0;
+ } else if (texel > a_vect) {
+ texel = a_vect;
+ }
+#endif
+ texel = dxtn_alpha_tlat[anyZero | anyOne][texel];
+ }
+ /* add in texel */
+ Q_SHL(lo, 3);
+ Q_OR32(lo, texel);
+ }
+ Q_SHL(lo, 16);
+ Q_OR32(lo, alpha0 | (alpha1 << 8));
+ ((qword *)cc)[0] = lo;
+ }
+
+ color0 = COLOR565(input[minCol]);
+ color1 = COLOR565(input[maxCol]);
+ cc[2] = color0 | (color1 << 16);
+
+ hihi = 0;
+ if (color0 != color1) {
+ MAKEIVEC(n_vect, n_comp, iv, b, input[minCol], input[maxCol]);
+
+ /* add in texels */
+ for (k = N_TEXELS - 1; k >= 0; k--) {
+ int texel;
+ /* interpolate color */
+ CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
+ texel = dxtn_color_tlat[0][texel];
+ /* add in texel */
+ hihi <<= 2;
+ hihi |= texel;
+ }
+ }
+ cc[3] = hihi;
+}
+
+
+#define ENCODER(dxtn, n) \
+int TAPIENTRY \
+dxtn##_encode (int width, int height, int comps, \
+ const void *source, int srcRowStride, \
+ void *dest, int destRowStride) \
+{ \
+ int x, y; \
+ const byte *data; \
+ dword *encoded = (dword *)dest; \
+ void *newSource = NULL; \
+ \
+ /* Replicate image if width is not M4 or height is not M4 */ \
+ if ((width & 3) | (height & 3)) { \
+ int newWidth = (width + 3) & ~3; \
+ int newHeight = (height + 3) & ~3; \
+ newSource = malloc(comps * newWidth * newHeight * sizeof(byte *));\
+ _mesa_upscale_teximage2d(width, height, newWidth, newHeight, \
+ comps, (const byte *)source, \
+ srcRowStride, (byte *)newSource); \
+ source = newSource; \
+ width = newWidth; \
+ height = newHeight; \
+ srcRowStride = comps * newWidth; \
+ } \
+ \
+ data = (const byte *)source; \
+ destRowStride = (destRowStride - width * n) / 4; \
+ for (y = 0; y < height; y += 4) { \
+ unsigned int offs = 0 + (y + 0) * srcRowStride; \
+ for (x = 0; x < width; x += 4) { \
+ const byte *lines[4]; \
+ lines[0] = &data[offs]; \
+ lines[1] = lines[0] + srcRowStride; \
+ lines[2] = lines[1] + srcRowStride; \
+ lines[3] = lines[2] + srcRowStride; \
+ offs += 4 * comps; \
+ dxtn##_quantize(encoded, lines, comps); \
+ /* 4x4 block */ \
+ encoded += n; \
+ } \
+ encoded += destRowStride; \
+ } \
+ \
+ if (newSource != NULL) { \
+ free(newSource); \
+ } \
+ \
+ return 0; \
+}
+
+ENCODER(dxt1_rgb, 2)
+ENCODER(dxt1_rgba, 2)
+ENCODER(dxt3_rgba, 4)
+ENCODER(dxt5_rgba, 4)
+
+
+/***************************************************************************\
+ * DXTn decoder
+ *
+ * The decoder is based on GL_EXT_texture_compression_s3tc
+ * specification and serves as a concept for the encoder.
+\***************************************************************************/
+
+
+/* lookup table for scaling 4 bit colors up to 8 bits */
+static const byte _rgb_scale_4[] = {
+ 0, 17, 34, 51, 68, 85, 102, 119,
+ 136, 153, 170, 187, 204, 221, 238, 255
+};
+
+/* lookup table for scaling 5 bit colors up to 8 bits */
+static const byte _rgb_scale_5[] = {
+ 0, 8, 16, 25, 33, 41, 49, 58,
+ 66, 74, 82, 90, 99, 107, 115, 123,
+ 132, 140, 148, 156, 165, 173, 181, 189,
+ 197, 206, 214, 222, 230, 239, 247, 255
+};
+
+/* lookup table for scaling 6 bit colors up to 8 bits */
+static const byte _rgb_scale_6[] = {
+ 0, 4, 8, 12, 16, 20, 24, 28,
+ 32, 36, 40, 45, 49, 53, 57, 61,
+ 65, 69, 73, 77, 81, 85, 89, 93,
+ 97, 101, 105, 109, 113, 117, 121, 125,
+ 130, 134, 138, 142, 146, 150, 154, 158,
+ 162, 166, 170, 174, 178, 182, 186, 190,
+ 194, 198, 202, 206, 210, 215, 219, 223,
+ 227, 231, 235, 239, 243, 247, 251, 255
+};
+
+
+#define CC_SEL(cc, which) (((dword *)(cc))[(which) / 32] >> ((which) & 31))
+#define UP4(c) _rgb_scale_4[(c) & 15]
+#define UP5(c) _rgb_scale_5[(c) & 31]
+#define UP6(c) _rgb_scale_6[(c) & 63]
+#define ZERO_4UBV(v) *((dword *)(v)) = 0
+
+
+void TAPIENTRY
+dxt1_rgb_decode_1 (const void *texture, int stride,
+ int i, int j, byte *rgba)
+{
+ const byte *src = (const byte *)texture
+ + ((j / 4) * ((stride + 3) / 4) + i / 4) * 8;
+ const int code = (src[4 + (j & 3)] >> ((i & 3) * 2)) & 0x3;
+ if (code == 0) {
+ rgba[RCOMP] = UP5(CC_SEL(src, 11));
+ rgba[GCOMP] = UP6(CC_SEL(src, 5));
+ rgba[BCOMP] = UP5(CC_SEL(src, 0));
+ } else if (code == 1) {
+ rgba[RCOMP] = UP5(CC_SEL(src, 27));
+ rgba[GCOMP] = UP6(CC_SEL(src, 21));
+ rgba[BCOMP] = UP5(CC_SEL(src, 16));
+ } else {
+ const word col0 = src[0] | (src[1] << 8);
+ const word col1 = src[2] | (src[3] << 8);
+ if (col0 > col1) {
+ if (code == 2) {
+ rgba[RCOMP] = (UP5(col0 >> 11) * 2 + UP5(col1 >> 11)) / 3;
+ rgba[GCOMP] = (UP6(col0 >> 5) * 2 + UP6(col1 >> 5)) / 3;
+ rgba[BCOMP] = (UP5(col0 ) * 2 + UP5(col1 )) / 3;
+ } else {
+ rgba[RCOMP] = (UP5(col0 >> 11) + 2 * UP5(col1 >> 11)) / 3;
+ rgba[GCOMP] = (UP6(col0 >> 5) + 2 * UP6(col1 >> 5)) / 3;
+ rgba[BCOMP] = (UP5(col0 ) + 2 * UP5(col1 )) / 3;
+ }
+ } else {
+ if (code == 2) {
+ rgba[RCOMP] = (UP5(col0 >> 11) + UP5(col1 >> 11)) / 2;
+ rgba[GCOMP] = (UP6(col0 >> 5) + UP6(col1 >> 5)) / 2;
+ rgba[BCOMP] = (UP5(col0 ) + UP5(col1 )) / 2;
+ } else {
+ ZERO_4UBV(rgba);
+ }
+ }
+ }
+ rgba[ACOMP] = 255;
+}
+
+
+void TAPIENTRY
+dxt1_rgba_decode_1 (const void *texture, int stride,
+ int i, int j, byte *rgba)
+{
+ /* Same as rgb_dxt1 above, except alpha=0 if col0<=col1 and code=3. */
+ const byte *src = (const byte *)texture
+ + ((j / 4) * ((stride + 3) / 4) + i / 4) * 8;
+ const int code = (src[4 + (j & 3)] >> ((i & 3) * 2)) & 0x3;
+ if (code == 0) {
+ rgba[RCOMP] = UP5(CC_SEL(src, 11));
+ rgba[GCOMP] = UP6(CC_SEL(src, 5));
+ rgba[BCOMP] = UP5(CC_SEL(src, 0));
+ rgba[ACOMP] = 255;
+ } else if (code == 1) {
+ rgba[RCOMP] = UP5(CC_SEL(src, 27));
+ rgba[GCOMP] = UP6(CC_SEL(src, 21));
+ rgba[BCOMP] = UP5(CC_SEL(src, 16));
+ rgba[ACOMP] = 255;
+ } else {
+ const word col0 = src[0] | (src[1] << 8);
+ const word col1 = src[2] | (src[3] << 8);
+ if (col0 > col1) {
+ if (code == 2) {
+ rgba[RCOMP] = (UP5(col0 >> 11) * 2 + UP5(col1 >> 11)) / 3;
+ rgba[GCOMP] = (UP6(col0 >> 5) * 2 + UP6(col1 >> 5)) / 3;
+ rgba[BCOMP] = (UP5(col0 ) * 2 + UP5(col1 )) / 3;
+ } else {
+ rgba[RCOMP] = (UP5(col0 >> 11) + 2 * UP5(col1 >> 11)) / 3;
+ rgba[GCOMP] = (UP6(col0 >> 5) + 2 * UP6(col1 >> 5)) / 3;
+ rgba[BCOMP] = (UP5(col0 ) + 2 * UP5(col1 )) / 3;
+ }
+ rgba[ACOMP] = 255;
+ } else {
+ if (code == 2) {
+ rgba[RCOMP] = (UP5(col0 >> 11) + UP5(col1 >> 11)) / 2;
+ rgba[GCOMP] = (UP6(col0 >> 5) + UP6(col1 >> 5)) / 2;
+ rgba[BCOMP] = (UP5(col0 ) + UP5(col1 )) / 2;
+ rgba[ACOMP] = 255;
+ } else {
+ ZERO_4UBV(rgba);
+ }
+ }
+ }
+}
+
+
+void TAPIENTRY
+dxt3_rgba_decode_1 (const void *texture, int stride,
+ int i, int j, byte *rgba)
+{
+ const byte *src = (const byte *)texture
+ + ((j / 4) * ((stride + 3) / 4) + i / 4) * 16;
+ const int code = (src[12 + (j & 3)] >> ((i & 3) * 2)) & 0x3;
+ const dword *cc = (const dword *)(src + 8);
+ if (code == 0) {
+ rgba[RCOMP] = UP5(CC_SEL(cc, 11));
+ rgba[GCOMP] = UP6(CC_SEL(cc, 5));
+ rgba[BCOMP] = UP5(CC_SEL(cc, 0));
+ } else if (code == 1) {
+ rgba[RCOMP] = UP5(CC_SEL(cc, 27));
+ rgba[GCOMP] = UP6(CC_SEL(cc, 21));
+ rgba[BCOMP] = UP5(CC_SEL(cc, 16));
+ } else if (code == 2) {
+ /* (col0 * (4 - code) + col1 * (code - 1)) / 3 */
+ rgba[RCOMP] = (UP5(CC_SEL(cc, 11)) * 2 + UP5(CC_SEL(cc, 27))) / 3;
+ rgba[GCOMP] = (UP6(CC_SEL(cc, 5)) * 2 + UP6(CC_SEL(cc, 21))) / 3;
+ rgba[BCOMP] = (UP5(CC_SEL(cc, 0)) * 2 + UP5(CC_SEL(cc, 16))) / 3;
+ } else {
+ rgba[RCOMP] = (UP5(CC_SEL(cc, 11)) + 2 * UP5(CC_SEL(cc, 27))) / 3;
+ rgba[GCOMP] = (UP6(CC_SEL(cc, 5)) + 2 * UP6(CC_SEL(cc, 21))) / 3;
+ rgba[BCOMP] = (UP5(CC_SEL(cc, 0)) + 2 * UP5(CC_SEL(cc, 16))) / 3;
+ }
+ rgba[ACOMP] = UP4(src[((j & 3) * 4 + (i & 3)) / 2] >> ((i & 1) * 4));
+}
+
+
+void TAPIENTRY
+dxt5_rgba_decode_1 (const void *texture, int stride,
+ int i, int j, byte *rgba)
+{
+ const byte *src = (const byte *)texture
+ + ((j / 4) * ((stride + 3) / 4) + i / 4) * 16;
+ const int code = (src[12 + (j & 3)] >> ((i & 3) * 2)) & 0x3;
+ const dword *cc = (const dword *)(src + 8);
+ const byte alpha0 = src[0];
+ const byte alpha1 = src[1];
+ const int alphaShift = (((j & 3) * 4) + (i & 3)) * 3 + 16;
+ const int acode = ((alphaShift == 31)
+ ? CC_SEL(src + 2, alphaShift - 16)
+ : CC_SEL(src, alphaShift)) & 0x7;
+ if (code == 0) {
+ rgba[RCOMP] = UP5(CC_SEL(cc, 11));
+ rgba[GCOMP] = UP6(CC_SEL(cc, 5));
+ rgba[BCOMP] = UP5(CC_SEL(cc, 0));
+ } else if (code == 1) {
+ rgba[RCOMP] = UP5(CC_SEL(cc, 27));
+ rgba[GCOMP] = UP6(CC_SEL(cc, 21));
+ rgba[BCOMP] = UP5(CC_SEL(cc, 16));
+ } else if (code == 2) {
+ /* (col0 * (4 - code) + col1 * (code - 1)) / 3 */
+ rgba[RCOMP] = (UP5(CC_SEL(cc, 11)) * 2 + UP5(CC_SEL(cc, 27))) / 3;
+ rgba[GCOMP] = (UP6(CC_SEL(cc, 5)) * 2 + UP6(CC_SEL(cc, 21))) / 3;
+ rgba[BCOMP] = (UP5(CC_SEL(cc, 0)) * 2 + UP5(CC_SEL(cc, 16))) / 3;
+ } else {
+ rgba[RCOMP] = (UP5(CC_SEL(cc, 11)) + 2 * UP5(CC_SEL(cc, 27))) / 3;
+ rgba[GCOMP] = (UP6(CC_SEL(cc, 5)) + 2 * UP6(CC_SEL(cc, 21))) / 3;
+ rgba[BCOMP] = (UP5(CC_SEL(cc, 0)) + 2 * UP5(CC_SEL(cc, 16))) / 3;
+ }
+ if (acode == 0) {
+ rgba[ACOMP] = alpha0;
+ } else if (acode == 1) {
+ rgba[ACOMP] = alpha1;
+ } else if (alpha0 > alpha1) {
+ rgba[ACOMP] = ((8 - acode) * alpha0 + (acode - 1) * alpha1) / 7;
+ } else if (acode == 6) {
+ rgba[ACOMP] = 0;
+ } else if (acode == 7) {
+ rgba[ACOMP] = 255;
+ } else {
+ rgba[ACOMP] = ((6 - acode) * alpha0 + (acode - 1) * alpha1) / 5;
+ }
+}
--- /dev/null
+LIBRARY dxtn
+EXPORTS
+dxt1_rgb_encode@28
+dxt1_rgba_encode@28
+dxt3_rgba_encode@28
+dxt5_rgba_encode@28
+dxt1_rgba_decode_1@20
+dxt3_rgba_decode_1@20
+dxt5_rgba_decode_1@20
+fxt1_encode@28
+fxt1_decode_1@20
+fetch_2d_texel_rgb_dxt1@20
+fetch_2d_texel_rgba_dxt1@20
+fetch_2d_texel_rgba_dxt3@20
+fetch_2d_texel_rgba_dxt5@20
+tx_compress_dxtn@28
--- /dev/null
+/*
+ * DXTn codec
+ * Version: 1.1
+ *
+ * Copyright (C) 2004 Daniel Borca All Rights Reserved.
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#ifndef DXTN_H_included
+#define DXTN_H_included
+
+TAPI int TAPIENTRY
+dxt1_rgb_encode (int width, int height, int comps,
+ const void *source, int srcRowStride,
+ void *dest, int destRowStride);
+
+TAPI int TAPIENTRY
+dxt1_rgba_encode (int width, int height, int comps,
+ const void *source, int srcRowStride,
+ void *dest, int destRowStride);
+
+TAPI int TAPIENTRY
+dxt3_rgba_encode (int width, int height, int comps,
+ const void *source, int srcRowStride,
+ void *dest, int destRowStride);
+
+TAPI int TAPIENTRY
+dxt5_rgba_encode (int width, int height, int comps,
+ const void *source, int srcRowStride,
+ void *dest, int destRowStride);
+
+TAPI void TAPIENTRY
+dxt1_rgb_decode_1 (const void *texture, int stride /* in pixels */,
+ int i, int j, byte *rgba);
+
+TAPI void TAPIENTRY
+dxt1_rgba_decode_1 (const void *texture, int stride /* in pixels */,
+ int i, int j, byte *rgba);
+
+TAPI void TAPIENTRY
+dxt3_rgba_decode_1 (const void *texture, int stride /* in pixels */,
+ int i, int j, byte *rgba);
+
+TAPI void TAPIENTRY
+dxt5_rgba_decode_1 (const void *texture, int stride /* in pixels */,
+ int i, int j, byte *rgba);
+
+#endif
--- /dev/null
+<module name="dxtn" type="win32dll" entrypoint="0" installbase="system32" installname="dxnt.dll" allowwarnings="true">
+ <importlibrary definition="dxtn.def" />
+ <include base="dxtn">.</include>
+ <define name="__USE_W32API" />
+
+ <library>msvcrt</library>
+
+ <file>fxt1.c</file>
+ <file>dxtn.c</file>
+ <file>wrapper.c</file>
+ <file>texstore.c</file>
+</module>
\ No newline at end of file
--- /dev/null
+/*
+ * FXT1 codec
+ * Version: 1.1
+ *
+ * Copyright (C) 2004 Daniel Borca 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
+ * DANIEL BORCA 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.
+ */
+
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "types.h"
+#include "internal.h"
+#include "fxt1.h"
+
+
+/***************************************************************************\
+ * FXT1 encoder
+ *
+ * The encoder was built by reversing the decoder,
+ * and is vaguely based on Texus2 by 3dfx. Note that this code
+ * is merely a proof of concept, since it is highly UNoptimized;
+ * moreover, it is sub-optimal due to initial conditions passed
+ * to Lloyd's algorithm (the interpolation modes are even worse).
+\***************************************************************************/
+
+
+#define MAX_COMP 4 /* ever needed maximum number of components in texel */
+#define MAX_VECT 4 /* ever needed maximum number of base vectors to find */
+#define N_TEXELS 32 /* number of texels in a block (always 32) */
+#define LL_N_REP 50 /* number of iterations in lloyd's vq */
+#define LL_RMS_D 10 /* fault tolerance (maximum delta) */
+#define LL_RMS_E 255 /* fault tolerance (maximum error) */
+#define ALPHA_TS 2 /* alpha threshold: (255 - ALPHA_TS) deemed opaque */
+#define ISTBLACK(v) (*((dword *)(v)) == 0)
+#define COPY_4UBV(DST, SRC) *((dword *)(DST)) = *((dword *)(SRC))
+
+
+static int
+fxt1_bestcol (float vec[][MAX_COMP], int nv,
+ byte input[MAX_COMP], int nc)
+{
+ int i, j, best = -1;
+ float err = 1e9; /* big enough */
+
+ for (j = 0; j < nv; j++) {
+ float e = 0.0F;
+ for (i = 0; i < nc; i++) {
+ e += (vec[j][i] - input[i]) * (vec[j][i] - input[i]);
+ }
+ if (e < err) {
+ err = e;
+ best = j;
+ }
+ }
+
+ return best;
+}
+
+
+static int
+fxt1_worst (float vec[MAX_COMP],
+ byte input[N_TEXELS][MAX_COMP], int nc, int n)
+{
+ int i, k, worst = -1;
+ float err = -1.0F; /* small enough */
+
+ for (k = 0; k < n; k++) {
+ float e = 0.0F;
+ for (i = 0; i < nc; i++) {
+ e += (vec[i] - input[k][i]) * (vec[i] - input[k][i]);
+ }
+ if (e > err) {
+ err = e;
+ worst = k;
+ }
+ }
+
+ return worst;
+}
+
+
+static int
+fxt1_variance (double variance[MAX_COMP],
+ byte input[N_TEXELS][MAX_COMP], int nc, int n)
+{
+ int i, k, best = 0;
+ dword sx, sx2;
+ double var, maxvar = -1; /* small enough */
+ double teenth = 1.0 / n;
+
+ for (i = 0; i < nc; i++) {
+ sx = sx2 = 0;
+ for (k = 0; k < n; k++) {
+ int t = input[k][i];
+ sx += t;
+ sx2 += t * t;
+ }
+ var = sx2 * teenth - sx * sx * teenth * teenth;
+ if (maxvar < var) {
+ maxvar = var;
+ best = i;
+ }
+ if (variance) {
+ variance[i] = var;
+ }
+ }
+
+ return best;
+}
+
+
+static int
+fxt1_choose (float vec[][MAX_COMP], int nv,
+ byte input[N_TEXELS][MAX_COMP], int nc, int n)
+{
+#if 0
+ /* Choose colors from a grid.
+ */
+ int i, j;
+
+ for (j = 0; j < nv; j++) {
+ int m = j * (n - 1) / (nv - 1);
+ for (i = 0; i < nc; i++) {
+ vec[j][i] = input[m][i];
+ }
+ }
+#else
+ /* Our solution here is to find the darkest and brightest colors in
+ * the 8x4 tile and use those as the two representative colors.
+ * There are probably better algorithms to use (histogram-based).
+ */
+ int i, j, k;
+ int minSum = 2000; /* big enough */
+ int maxSum = -1; /* small enough */
+ int minCol = 0; /* phoudoin: silent compiler! */
+ int maxCol = 0; /* phoudoin: silent compiler! */
+
+ struct {
+ int flag;
+ dword key;
+ int freq;
+ int idx;
+ } hist[N_TEXELS];
+ int lenh = 0;
+
+ memset(hist, 0, sizeof(hist));
+
+ for (k = 0; k < n; k++) {
+ int l;
+ dword key = 0;
+ int sum = 0;
+ for (i = 0; i < nc; i++) {
+ key <<= 8;
+ key |= input[k][i];
+ sum += input[k][i];
+ }
+ for (l = 0; l < n; l++) {
+ if (!hist[l].flag) {
+ /* alloc new slot */
+ hist[l].flag = !0;
+ hist[l].key = key;
+ hist[l].freq = 1;
+ hist[l].idx = k;
+ lenh = l + 1;
+ break;
+ } else if (hist[l].key == key) {
+ hist[l].freq++;
+ break;
+ }
+ }
+ if (minSum > sum) {
+ minSum = sum;
+ minCol = k;
+ }
+ if (maxSum < sum) {
+ maxSum = sum;
+ maxCol = k;
+ }
+ }
+
+ if (lenh <= nv) {
+ for (j = 0; j < lenh; j++) {
+ for (i = 0; i < nc; i++) {
+ vec[j][i] = (float)input[hist[j].idx][i];
+ }
+ }
+ for (; j < nv; j++) {
+ for (i = 0; i < nc; i++) {
+ vec[j][i] = vec[0][i];
+ }
+ }
+ return 0;
+ }
+
+ for (j = 0; j < nv; j++) {
+ for (i = 0; i < nc; i++) {
+ vec[j][i] = ((nv - 1 - j) * input[minCol][i] + j * input[maxCol][i] + (nv - 1) / 2) / (float)(nv - 1);
+ }
+ }
+#endif
+
+ return !0;
+}
+
+
+static int
+fxt1_lloyd (float vec[][MAX_COMP], int nv,
+ byte input[N_TEXELS][MAX_COMP], int nc, int n)
+{
+ /* Use the generalized lloyd's algorithm for VQ:
+ * find 4 color vectors.
+ *
+ * for each sample color
+ * sort to nearest vector.
+ *
+ * replace each vector with the centroid of it's matching colors.
+ *
+ * repeat until RMS doesn't improve.
+ *
+ * if a color vector has no samples, or becomes the same as another
+ * vector, replace it with the color which is farthest from a sample.
+ *
+ * vec[][MAX_COMP] initial vectors and resulting colors
+ * nv number of resulting colors required
+ * input[N_TEXELS][MAX_COMP] input texels
+ * nc number of components in input / vec
+ * n number of input samples
+ */
+
+ int sum[MAX_VECT][MAX_COMP]; /* used to accumulate closest texels */
+ int cnt[MAX_VECT]; /* how many times a certain vector was chosen */
+ float error, lasterror = 1e9;
+
+ int i, j, k, rep;
+
+ /* the quantizer */
+ for (rep = 0; rep < LL_N_REP; rep++) {
+ /* reset sums & counters */
+ for (j = 0; j < nv; j++) {
+ for (i = 0; i < nc; i++) {
+ sum[j][i] = 0;
+ }
+ cnt[j] = 0;
+ }
+ error = 0;
+
+ /* scan whole block */
+ for (k = 0; k < n; k++) {
+#if 1
+ int best = -1;
+ float err = 1e9; /* big enough */
+ /* determine best vector */
+ for (j = 0; j < nv; j++) {
+ float e = (vec[j][0] - input[k][0]) * (vec[j][0] - input[k][0]) +
+ (vec[j][1] - input[k][1]) * (vec[j][1] - input[k][1]) +
+ (vec[j][2] - input[k][2]) * (vec[j][2] - input[k][2]);
+ if (nc == 4) {
+ e += (vec[j][3] - input[k][3]) * (vec[j][3] - input[k][3]);
+ }
+ if (e < err) {
+ err = e;
+ best = j;
+ }
+ }
+#else
+ int best = fxt1_bestcol(vec, nv, input[k], nc, &err);
+#endif
+ /* add in closest color */
+ for (i = 0; i < nc; i++) {
+ sum[best][i] += input[k][i];
+ }
+ /* mark this vector as used */
+ cnt[best]++;
+ /* accumulate error */
+ error += err;
+ }
+
+ /* check RMS */
+ if ((error < LL_RMS_E) ||
+ ((error < lasterror) && ((lasterror - error) < LL_RMS_D))) {
+ return !0; /* good match */
+ }
+ lasterror = error;
+
+ /* move each vector to the barycenter of its closest colors */
+ for (j = 0; j < nv; j++) {
+ if (cnt[j]) {
+ float div = 1.0F / cnt[j];
+ for (i = 0; i < nc; i++) {
+ vec[j][i] = div * sum[j][i];
+ }
+ } else {
+ /* this vec has no samples or is identical with a previous vec */
+ int worst = fxt1_worst(vec[j], input, nc, n);
+ for (i = 0; i < nc; i++) {
+ vec[j][i] = input[worst][i];
+ }
+ }
+ }
+ }
+
+ return 0; /* could not converge fast enough */
+}
+
+
+static void
+fxt1_quantize_CHROMA (dword *cc,
+ byte input[N_TEXELS][MAX_COMP])
+{
+ const int n_vect = 4; /* 4 base vectors to find */
+ const int n_comp = 3; /* 3 components: R, G, B */
+ float vec[MAX_VECT][MAX_COMP];
+ int i, j, k;
+ qword hi; /* high quadword */
+ dword lohi, lolo; /* low quadword: hi dword, lo dword */
+
+ if (fxt1_choose(vec, n_vect, input, n_comp, N_TEXELS) != 0) {
+ fxt1_lloyd(vec, n_vect, input, n_comp, N_TEXELS);
+ }
+
+ Q_MOV32(hi, 4); /* cc-chroma = "010" + unused bit */
+ for (j = n_vect - 1; j >= 0; j--) {
+ for (i = 0; i < n_comp; i++) {
+ /* add in colors */
+ Q_SHL(hi, 5);
+ Q_OR32(hi, (dword)(vec[j][i] / 8.0F));
+ }
+ }
+ ((qword *)cc)[1] = hi;
+
+ lohi = lolo = 0;
+ /* right microtile */
+ for (k = N_TEXELS - 1; k >= N_TEXELS / 2; k--) {
+ lohi <<= 2;
+ lohi |= fxt1_bestcol(vec, n_vect, input[k], n_comp);
+ }
+ /* left microtile */
+ for (; k >= 0; k--) {
+ lolo <<= 2;
+ lolo |= fxt1_bestcol(vec, n_vect, input[k], n_comp);
+ }
+ cc[1] = lohi;
+ cc[0] = lolo;
+}
+
+
+static void
+fxt1_quantize_ALPHA0 (dword *cc,
+ byte input[N_TEXELS][MAX_COMP],
+ byte reord[N_TEXELS][MAX_COMP], int n)
+{
+ const int n_vect = 3; /* 3 base vectors to find */
+ const int n_comp = 4; /* 4 components: R, G, B, A */
+ float vec[MAX_VECT][MAX_COMP];
+ int i, j, k;
+ qword hi; /* high quadword */
+ dword lohi, lolo; /* low quadword: hi dword, lo dword */
+
+ /* the last vector indicates zero */
+ for (i = 0; i < n_comp; i++) {
+ vec[n_vect][i] = 0;
+ }
+
+ /* the first n texels in reord are guaranteed to be non-zero */
+ if (fxt1_choose(vec, n_vect, reord, n_comp, n) != 0) {
+ fxt1_lloyd(vec, n_vect, reord, n_comp, n);
+ }
+
+ Q_MOV32(hi, 6); /* alpha = "011" + lerp = 0 */
+ for (j = n_vect - 1; j >= 0; j--) {
+ /* add in alphas */
+ Q_SHL(hi, 5);
+ Q_OR32(hi, (dword)(vec[j][ACOMP] / 8.0F));
+ }
+ for (j = n_vect - 1; j >= 0; j--) {
+ for (i = 0; i < n_comp - 1; i++) {
+ /* add in colors */
+ Q_SHL(hi, 5);
+ Q_OR32(hi, (dword)(vec[j][i] / 8.0F));
+ }
+ }
+ ((qword *)cc)[1] = hi;
+
+ lohi = lolo = 0;
+ /* right microtile */
+ for (k = N_TEXELS - 1; k >= N_TEXELS / 2; k--) {
+ lohi <<= 2;
+ lohi |= fxt1_bestcol(vec, n_vect + 1, input[k], n_comp);
+ }
+ /* left microtile */
+ for (; k >= 0; k--) {
+ lolo <<= 2;
+ lolo |= fxt1_bestcol(vec, n_vect + 1, input[k], n_comp);
+ }
+ cc[1] = lohi;
+ cc[0] = lolo;
+}
+
+
+static void
+fxt1_quantize_ALPHA1 (dword *cc,
+ byte input[N_TEXELS][MAX_COMP])
+{
+ const int n_vect = 3; /* highest vector number in each microtile */
+ const int n_comp = 4; /* 4 components: R, G, B, A */
+ float vec[1 + 1 + 1][MAX_COMP]; /* 1.5 extrema for each sub-block */
+ float b, iv[MAX_COMP]; /* interpolation vector */
+ int i, j, k;
+ qword hi; /* high quadword */
+ dword lohi, lolo; /* low quadword: hi dword, lo dword */
+
+ int minSum;
+ int maxSum;
+ int minColL = 0, maxColL = 0;
+ int minColR = 0, maxColR = 0;
+ int sumL = 0, sumR = 0;
+
+ /* Our solution here is to find the darkest and brightest colors in
+ * the 4x4 tile and use those as the two representative colors.
+ * There are probably better algorithms to use (histogram-based).
+ */
+ minSum = 2000; /* big enough */
+ maxSum = -1; /* small enough */
+ for (k = 0; k < N_TEXELS / 2; k++) {
+ int sum = 0;
+ for (i = 0; i < n_comp; i++) {
+ sum += input[k][i];
+ }
+ if (minSum > sum) {
+ minSum = sum;
+ minColL = k;
+ }
+ if (maxSum < sum) {
+ maxSum = sum;
+ maxColL = k;
+ }
+ sumL += sum;
+ }
+ minSum = 2000; /* big enough */
+ maxSum = -1; /* small enough */
+ for (; k < N_TEXELS; k++) {
+ int sum = 0;
+ for (i = 0; i < n_comp; i++) {
+ sum += input[k][i];
+ }
+ if (minSum > sum) {
+ minSum = sum;
+ minColR = k;
+ }
+ if (maxSum < sum) {
+ maxSum = sum;
+ maxColR = k;
+ }
+ sumR += sum;
+ }
+
+ /* choose the common vector (yuck!) */
+ {
+ int j1, j2;
+ int v1 = 0, v2 = 0;
+ float err = 1e9; /* big enough */
+ float tv[2 * 2][MAX_COMP]; /* 2 extrema for each sub-block */
+ for (i = 0; i < n_comp; i++) {
+ tv[0][i] = input[minColL][i];
+ tv[1][i] = input[maxColL][i];
+ tv[2][i] = input[minColR][i];
+ tv[3][i] = input[maxColR][i];
+ }
+ for (j1 = 0; j1 < 2; j1++) {
+ for (j2 = 2; j2 < 4; j2++) {
+ float e = 0.0F;
+ for (i = 0; i < n_comp; i++) {
+ e += (tv[j1][i] - tv[j2][i]) * (tv[j1][i] - tv[j2][i]);
+ }
+ if (e < err) {
+ err = e;
+ v1 = j1;
+ v2 = j2;
+ }
+ }
+ }
+ for (i = 0; i < n_comp; i++) {
+ vec[0][i] = tv[1 - v1][i];
+ vec[1][i] = (tv[v1][i] * sumL + tv[v2][i] * sumR) / (sumL + sumR);
+ vec[2][i] = tv[5 - v2][i];
+ }
+ }
+
+ /* left microtile */
+ cc[0] = 0;
+ if (minColL != maxColL) {
+ /* compute interpolation vector */
+ MAKEIVEC(n_vect, n_comp, iv, b, vec[0], vec[1]);
+
+ /* add in texels */
+ lolo = 0;
+ for (k = N_TEXELS / 2 - 1; k >= 0; k--) {
+ int texel;
+ /* interpolate color */
+ CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
+ /* add in texel */
+ lolo <<= 2;
+ lolo |= texel;
+ }
+
+ cc[0] = lolo;
+ }
+
+ /* right microtile */
+ cc[1] = 0;
+ if (minColR != maxColR) {
+ /* compute interpolation vector */
+ MAKEIVEC(n_vect, n_comp, iv, b, vec[2], vec[1]);
+
+ /* add in texels */
+ lohi = 0;
+ for (k = N_TEXELS - 1; k >= N_TEXELS / 2; k--) {
+ int texel;
+ /* interpolate color */
+ CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
+ /* add in texel */
+ lohi <<= 2;
+ lohi |= texel;
+ }
+
+ cc[1] = lohi;
+ }
+
+ Q_MOV32(hi, 7); /* alpha = "011" + lerp = 1 */
+ for (j = n_vect - 1; j >= 0; j--) {
+ /* add in alphas */
+ Q_SHL(hi, 5);
+ Q_OR32(hi, (dword)(vec[j][ACOMP] / 8.0F));
+ }
+ for (j = n_vect - 1; j >= 0; j--) {
+ for (i = 0; i < n_comp - 1; i++) {
+ /* add in colors */
+ Q_SHL(hi, 5);
+ Q_OR32(hi, (dword)(vec[j][i] / 8.0F));
+ }
+ }
+ ((qword *)cc)[1] = hi;
+}
+
+
+static void
+fxt1_quantize_HI (dword *cc,
+ byte input[N_TEXELS][MAX_COMP],
+ byte reord[N_TEXELS][MAX_COMP], int n)
+{
+ const int n_vect = 6; /* highest vector number */
+ const int n_comp = 3; /* 3 components: R, G, B */
+ float b = 0.0F; /* phoudoin: silent compiler! */
+ float iv[MAX_COMP]; /* interpolation vector */
+ int i, k;
+ dword hihi; /* high quadword: hi dword */
+
+ int minSum = 2000; /* big enough */
+ int maxSum = -1; /* small enough */
+ int minCol = 0; /* phoudoin: silent compiler! */
+ int maxCol = 0; /* phoudoin: silent compiler! */
+
+ /* Our solution here is to find the darkest and brightest colors in
+ * the 8x4 tile and use those as the two representative colors.
+ * There are probably better algorithms to use (histogram-based).
+ */
+ for (k = 0; k < n; k++) {
+ int sum = 0;
+ for (i = 0; i < n_comp; i++) {
+ sum += reord[k][i];
+ }
+ if (minSum > sum) {
+ minSum = sum;
+ minCol = k;
+ }
+ if (maxSum < sum) {
+ maxSum = sum;
+ maxCol = k;
+ }
+ }
+
+ hihi = 0; /* cc-hi = "00" */
+ for (i = 0; i < n_comp; i++) {
+ /* add in colors */
+ hihi <<= 5;
+ hihi |= reord[maxCol][i] >> 3;
+ }
+ for (i = 0; i < n_comp; i++) {
+ /* add in colors */
+ hihi <<= 5;
+ hihi |= reord[minCol][i] >> 3;
+ }
+ cc[3] = hihi;
+ cc[0] = cc[1] = cc[2] = 0;
+
+ /* compute interpolation vector */
+ if (minCol != maxCol) {
+ MAKEIVEC(n_vect, n_comp, iv, b, reord[minCol], reord[maxCol]);
+ }
+
+ /* add in texels */
+ for (k = N_TEXELS - 1; k >= 0; k--) {
+ int t = k * 3;
+ dword *kk = (dword *)((byte *)cc + t / 8);
+ int texel = n_vect + 1; /* transparent black */
+
+ if (!ISTBLACK(input[k])) {
+ if (minCol != maxCol) {
+ /* interpolate color */
+ CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
+ /* add in texel */
+ kk[0] |= texel << (t & 7);
+ }
+ } else {
+ /* add in texel */
+ kk[0] |= texel << (t & 7);
+ }
+ }
+}
+
+
+static void
+fxt1_quantize_MIXED1 (dword *cc,
+ byte input[N_TEXELS][MAX_COMP])
+{
+ const int n_vect = 2; /* highest vector number in each microtile */
+ const int n_comp = 3; /* 3 components: R, G, B */
+ byte vec[2 * 2][MAX_COMP]; /* 2 extrema for each sub-block */
+ float b, iv[MAX_COMP]; /* interpolation vector */
+ int i, j, k;
+ qword hi; /* high quadword */
+ dword lohi, lolo; /* low quadword: hi dword, lo dword */
+
+ int minSum;
+ int maxSum;
+ int minColL = 0, maxColL = -1;
+ int minColR = 0, maxColR = -1;
+
+ /* Our solution here is to find the darkest and brightest colors in
+ * the 4x4 tile and use those as the two representative colors.
+ * There are probably better algorithms to use (histogram-based).
+ */
+ minSum = 2000; /* big enough */
+ maxSum = -1; /* small enough */
+ for (k = 0; k < N_TEXELS / 2; k++) {
+ if (!ISTBLACK(input[k])) {
+ int sum = 0;
+ for (i = 0; i < n_comp; i++) {
+ sum += input[k][i];
+ }
+ if (minSum > sum) {
+ minSum = sum;
+ minColL = k;
+ }
+ if (maxSum < sum) {
+ maxSum = sum;
+ maxColL = k;
+ }
+ }
+ }
+ minSum = 2000; /* big enough */
+ maxSum = -1; /* small enough */
+ for (; k < N_TEXELS; k++) {
+ if (!ISTBLACK(input[k])) {
+ int sum = 0;
+ for (i = 0; i < n_comp; i++) {
+ sum += input[k][i];
+ }
+ if (minSum > sum) {
+ minSum = sum;
+ minColR = k;
+ }
+ if (maxSum < sum) {
+ maxSum = sum;
+ maxColR = k;
+ }
+ }
+ }
+
+ /* left microtile */
+ if (maxColL == -1) {
+ /* all transparent black */
+ cc[0] = ~0UL;
+ for (i = 0; i < n_comp; i++) {
+ vec[0][i] = 0;
+ vec[1][i] = 0;
+ }
+ } else {
+ cc[0] = 0;
+ for (i = 0; i < n_comp; i++) {
+ vec[0][i] = input[minColL][i];
+ vec[1][i] = input[maxColL][i];
+ }
+ if (minColL != maxColL) {
+ /* compute interpolation vector */
+ MAKEIVEC(n_vect, n_comp, iv, b, vec[0], vec[1]);
+
+ /* add in texels */
+ lolo = 0;
+ for (k = N_TEXELS / 2 - 1; k >= 0; k--) {
+ int texel = n_vect + 1; /* transparent black */
+ if (!ISTBLACK(input[k])) {
+ /* interpolate color */
+ CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
+ }
+ /* add in texel */
+ lolo <<= 2;
+ lolo |= texel;
+ }
+ cc[0] = lolo;
+ }
+ }
+
+ /* right microtile */
+ if (maxColR == -1) {
+ /* all transparent black */
+ cc[1] = ~0UL;
+ for (i = 0; i < n_comp; i++) {
+ vec[2][i] = 0;
+ vec[3][i] = 0;
+ }
+ } else {
+ cc[1] = 0;
+ for (i = 0; i < n_comp; i++) {
+ vec[2][i] = input[minColR][i];
+ vec[3][i] = input[maxColR][i];
+ }
+ if (minColR != maxColR) {
+ /* compute interpolation vector */
+ MAKEIVEC(n_vect, n_comp, iv, b, vec[2], vec[3]);
+
+ /* add in texels */
+ lohi = 0;
+ for (k = N_TEXELS - 1; k >= N_TEXELS / 2; k--) {
+ int texel = n_vect + 1; /* transparent black */
+ if (!ISTBLACK(input[k])) {
+ /* interpolate color */
+ CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
+ }
+ /* add in texel */
+ lohi <<= 2;
+ lohi |= texel;
+ }
+ cc[1] = lohi;
+ }
+ }
+
+ Q_MOV32(hi, 9 | (vec[3][GCOMP] & 4) | ((vec[1][GCOMP] >> 1) & 2)); /* chroma = "1" */
+ for (j = 2 * 2 - 1; j >= 0; j--) {
+ for (i = 0; i < n_comp; i++) {
+ /* add in colors */
+ Q_SHL(hi, 5);
+ Q_OR32(hi, vec[j][i] >> 3);
+ }
+ }
+ ((qword *)cc)[1] = hi;
+}
+
+
+static void
+fxt1_quantize_MIXED0 (dword *cc,
+ byte input[N_TEXELS][MAX_COMP])
+{
+ const int n_vect = 3; /* highest vector number in each microtile */
+ const int n_comp = 3; /* 3 components: R, G, B */
+ byte vec[2 * 2][MAX_COMP]; /* 2 extrema for each sub-block */
+ float b, iv[MAX_COMP]; /* interpolation vector */
+ int i, j, k;
+ qword hi; /* high quadword */
+ dword lohi, lolo; /* low quadword: hi dword, lo dword */
+
+ int minColL = 0, maxColL = 0;
+ int minColR = 0, maxColR = 0;
+#if 0
+ int minSum;
+ int maxSum;
+
+ /* Our solution here is to find the darkest and brightest colors in
+ * the 4x4 tile and use those as the two representative colors.
+ * There are probably better algorithms to use (histogram-based).
+ */
+ minSum = 2000; /* big enough */
+ maxSum = -1; /* small enough */
+ for (k = 0; k < N_TEXELS / 2; k++) {
+ int sum = 0;
+ for (i = 0; i < n_comp; i++) {
+ sum += input[k][i];
+ }
+ if (minSum > sum) {
+ minSum = sum;
+ minColL = k;
+ }
+ if (maxSum < sum) {
+ maxSum = sum;
+ maxColL = k;
+ }
+ }
+ minSum = 2000; /* big enough */
+ maxSum = -1; /* small enough */
+ for (; k < N_TEXELS; k++) {
+ int sum = 0;
+ for (i = 0; i < n_comp; i++) {
+ sum += input[k][i];
+ }
+ if (minSum > sum) {
+ minSum = sum;
+ minColR = k;
+ }
+ if (maxSum < sum) {
+ maxSum = sum;
+ maxColR = k;
+ }
+ }
+#else
+ int minVal;
+ int maxVal;
+ int maxVarL = fxt1_variance(NULL, input, n_comp, N_TEXELS / 2);
+ int maxVarR = fxt1_variance(NULL, &input[N_TEXELS / 2], n_comp, N_TEXELS / 2);
+
+ /* Scan the channel with max variance for lo & hi
+ * and use those as the two representative colors.
+ */
+ minVal = 2000; /* big enough */
+ maxVal = -1; /* small enough */
+ for (k = 0; k < N_TEXELS / 2; k++) {
+ int t = input[k][maxVarL];
+ if (minVal > t) {
+ minVal = t;
+ minColL = k;
+ }
+ if (maxVal < t) {
+ maxVal = t;
+ maxColL = k;
+ }
+ }
+ minVal = 2000; /* big enough */
+ maxVal = -1; /* small enough */
+ for (; k < N_TEXELS; k++) {
+ int t = input[k][maxVarR];
+ if (minVal > t) {
+ minVal = t;
+ minColR = k;
+ }
+ if (maxVal < t) {
+ maxVal = t;
+ maxColR = k;
+ }
+ }
+#endif
+
+ /* left microtile */
+ cc[0] = 0;
+ for (i = 0; i < n_comp; i++) {
+ vec[0][i] = input[minColL][i];
+ vec[1][i] = input[maxColL][i];
+ }
+ if (minColL != maxColL) {
+ /* compute interpolation vector */
+ MAKEIVEC(n_vect, n_comp, iv, b, vec[0], vec[1]);
+
+ /* add in texels */
+ lolo = 0;
+ for (k = N_TEXELS / 2 - 1; k >= 0; k--) {
+ int texel;
+ /* interpolate color */
+ CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
+ /* add in texel */
+ lolo <<= 2;
+ lolo |= texel;
+ }
+
+ /* funky encoding for LSB of green */
+ if ((int)((lolo >> 1) & 1) != (((vec[1][GCOMP] ^ vec[0][GCOMP]) >> 2) & 1)) {
+ for (i = 0; i < n_comp; i++) {
+ vec[1][i] = input[minColL][i];
+ vec[0][i] = input[maxColL][i];
+ }
+ lolo = ~lolo;
+ }
+
+ cc[0] = lolo;
+ }
+
+ /* right microtile */
+ cc[1] = 0;
+ for (i = 0; i < n_comp; i++) {
+ vec[2][i] = input[minColR][i];
+ vec[3][i] = input[maxColR][i];
+ }
+ if (minColR != maxColR) {
+ /* compute interpolation vector */
+ MAKEIVEC(n_vect, n_comp, iv, b, vec[2], vec[3]);
+
+ /* add in texels */
+ lohi = 0;
+ for (k = N_TEXELS - 1; k >= N_TEXELS / 2; k--) {
+ int texel;
+ /* interpolate color */
+ CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
+ /* add in texel */
+ lohi <<= 2;
+ lohi |= texel;
+ }
+
+ /* funky encoding for LSB of green */
+ if ((int)((lohi >> 1) & 1) != (((vec[3][GCOMP] ^ vec[2][GCOMP]) >> 2) & 1)) {
+ for (i = 0; i < n_comp; i++) {
+ vec[3][i] = input[minColR][i];
+ vec[2][i] = input[maxColR][i];
+ }
+ lohi = ~lohi;
+ }
+
+ cc[1] = lohi;
+ }
+
+ Q_MOV32(hi, 8 | (vec[3][GCOMP] & 4) | ((vec[1][GCOMP] >> 1) & 2)); /* chroma = "1" */
+ for (j = 2 * 2 - 1; j >= 0; j--) {
+ for (i = 0; i < n_comp; i++) {
+ /* add in colors */
+ Q_SHL(hi, 5);
+ Q_OR32(hi, vec[j][i] >> 3);
+ }
+ }
+ ((qword *)cc)[1] = hi;
+}
+
+
+static void
+fxt1_quantize (dword *cc, const byte *lines[], int comps)
+{
+ int trualpha;
+ byte reord[N_TEXELS][MAX_COMP];
+
+ byte input[N_TEXELS][MAX_COMP];
+ int i, k, l;
+
+ if (comps == 3) {
+ /* make the whole block opaque */
+ memset(input, -1, sizeof(input));
+ }
+
+ /* 8 texels each line */
+ for (l = 0; l < 4; l++) {
+ for (k = 0; k < 4; k++) {
+ for (i = 0; i < comps; i++) {
+ input[k + l * 4][i] = *lines[l]++;
+ }
+ }
+ for (; k < 8; k++) {
+ for (i = 0; i < comps; i++) {
+ input[k + l * 4 + 12][i] = *lines[l]++;
+ }
+ }
+ }
+
+ /* block layout:
+ * 00, 01, 02, 03, 08, 09, 0a, 0b
+ * 10, 11, 12, 13, 18, 19, 1a, 1b
+ * 04, 05, 06, 07, 0c, 0d, 0e, 0f
+ * 14, 15, 16, 17, 1c, 1d, 1e, 1f
+ */
+
+ /* [dBorca]
+ * stupidity flows forth from this
+ */
+ l = N_TEXELS;
+ trualpha = 0;
+ if (comps == 4) {
+ /* skip all transparent black texels */
+ l = 0;
+ for (k = 0; k < N_TEXELS; k++) {
+ /* test all components against 0 */
+ if (!ISTBLACK(input[k])) {
+ /* texel is not transparent black */
+ COPY_4UBV(reord[l], input[k]);
+ if (reord[l][ACOMP] < (255 - ALPHA_TS)) {
+ /* non-opaque texel */
+ trualpha = !0;
+ }
+ l++;
+ }
+ }
+ }
+
+#if 0
+ if (trualpha) {
+ fxt1_quantize_ALPHA0(cc, input, reord, l);
+ } else if (l == 0) {
+ cc[0] = cc[1] = cc[2] = -1;
+ cc[3] = 0;
+ } else if (l < N_TEXELS) {
+ fxt1_quantize_HI(cc, input, reord, l);
+ } else {
+ fxt1_quantize_CHROMA(cc, input);
+ }
+ (void)fxt1_quantize_ALPHA1;
+ (void)fxt1_quantize_MIXED1;
+ (void)fxt1_quantize_MIXED0;
+#else
+ if (trualpha) {
+ fxt1_quantize_ALPHA1(cc, input);
+ } else if (l == 0) {
+ cc[0] = cc[1] = cc[2] = ~0UL;
+ cc[3] = 0;
+ } else if (l < N_TEXELS) {
+ fxt1_quantize_MIXED1(cc, input);
+ } else {
+ fxt1_quantize_MIXED0(cc, input);
+ }
+ (void)fxt1_quantize_ALPHA0;
+ (void)fxt1_quantize_HI;
+ (void)fxt1_quantize_CHROMA;
+#endif
+}
+
+
+TAPI int TAPIENTRY
+fxt1_encode (int width, int height, int comps,
+ const void *source, int srcRowStride,
+ void *dest, int destRowStride)
+{
+ int x, y;
+ const byte *data;
+ dword *encoded = (dword *)dest;
+ void *newSource = NULL;
+
+ /* Replicate image if width is not M8 or height is not M4 */
+ if ((width & 7) | (height & 3)) {
+ int newWidth = (width + 7) & ~7;
+ int newHeight = (height + 3) & ~3;
+ newSource = malloc(comps * newWidth * newHeight * sizeof(byte *));
+ _mesa_upscale_teximage2d(width, height, newWidth, newHeight,
+ comps, (const byte *)source,
+ srcRowStride, (byte *)newSource);
+ source = newSource;
+ width = newWidth;
+ height = newHeight;
+ srcRowStride = comps * newWidth;
+ }
+
+ data = (const byte *)source;
+ destRowStride = (destRowStride - width * 2) / 4;
+ for (y = 0; y < height; y += 4) {
+ unsigned int offs = 0 + (y + 0) * srcRowStride;
+ for (x = 0; x < width; x += 8) {
+ const byte *lines[4];
+ lines[0] = &data[offs];
+ lines[1] = lines[0] + srcRowStride;
+ lines[2] = lines[1] + srcRowStride;
+ lines[3] = lines[2] + srcRowStride;
+ offs += 8 * comps;
+ fxt1_quantize(encoded, lines, comps);
+ /* 128 bits per 8x4 block */
+ encoded += 4;
+ }
+ encoded += destRowStride;
+ }
+
+ if (newSource != NULL) {
+ free(newSource);
+ }
+
+ return 0;
+}
+
+
+/***************************************************************************\
+ * FXT1 decoder
+ *
+ * The decoder is based on GL_3DFX_texture_compression_FXT1
+ * specification and serves as a concept for the encoder.
+\***************************************************************************/
+
+
+/* lookup table for scaling 5 bit colors up to 8 bits */
+static const byte _rgb_scale_5[] = {
+ 0, 8, 16, 25, 33, 41, 49, 58,
+ 66, 74, 82, 90, 99, 107, 115, 123,
+ 132, 140, 148, 156, 165, 173, 181, 189,
+ 197, 206, 214, 222, 230, 239, 247, 255
+};
+
+/* lookup table for scaling 6 bit colors up to 8 bits */
+static const byte _rgb_scale_6[] = {
+ 0, 4, 8, 12, 16, 20, 24, 28,
+ 32, 36, 40, 45, 49, 53, 57, 61,
+ 65, 69, 73, 77, 81, 85, 89, 93,
+ 97, 101, 105, 109, 113, 117, 121, 125,
+ 130, 134, 138, 142, 146, 150, 154, 158,
+ 162, 166, 170, 174, 178, 182, 186, 190,
+ 194, 198, 202, 206, 210, 215, 219, 223,
+ 227, 231, 235, 239, 243, 247, 251, 255
+};
+
+
+#define CC_SEL(cc, which) (((dword *)(cc))[(which) / 32] >> ((which) & 31))
+#define UP5(c) _rgb_scale_5[(c) & 31]
+#define UP6(c, b) _rgb_scale_6[(((c) & 31) << 1) | ((b) & 1)]
+#define LERP(n, t, c0, c1) (((n) - (t)) * (c0) + (t) * (c1) + (n) / 2) / (n)
+#define ZERO_4UBV(v) *((dword *)(v)) = 0
+
+
+static void
+fxt1_decode_1HI (const byte *code, int t, byte *rgba)
+{
+ const dword *cc;
+
+ t *= 3;
+ cc = (const dword *)(code + t / 8);
+ t = (cc[0] >> (t & 7)) & 7;
+
+ if (t == 7) {
+ ZERO_4UBV(rgba);
+ } else {
+ cc = (const dword *)(code + 12);
+ if (t == 0) {
+ rgba[BCOMP] = UP5(CC_SEL(cc, 0));
+ rgba[GCOMP] = UP5(CC_SEL(cc, 5));
+ rgba[RCOMP] = UP5(CC_SEL(cc, 10));
+ } else if (t == 6) {
+ rgba[BCOMP] = UP5(CC_SEL(cc, 15));
+ rgba[GCOMP] = UP5(CC_SEL(cc, 20));
+ rgba[RCOMP] = UP5(CC_SEL(cc, 25));
+ } else {
+ rgba[BCOMP] = LERP(6, t, UP5(CC_SEL(cc, 0)), UP5(CC_SEL(cc, 15)));
+ rgba[GCOMP] = LERP(6, t, UP5(CC_SEL(cc, 5)), UP5(CC_SEL(cc, 20)));
+ rgba[RCOMP] = LERP(6, t, UP5(CC_SEL(cc, 10)), UP5(CC_SEL(cc, 25)));
+ }
+ rgba[ACOMP] = 255;
+ }
+}
+
+
+static void
+fxt1_decode_1CHROMA (const byte *code, int t, byte *rgba)
+{
+ const dword *cc;
+ dword kk;
+
+ cc = (const dword *)code;
+ if (t & 16) {
+ cc++;
+ t &= 15;
+ }
+ t = (cc[0] >> (t * 2)) & 3;
+
+ t *= 15;
+ cc = (const dword *)(code + 8 + t / 8);
+ kk = cc[0] >> (t & 7);
+ rgba[BCOMP] = UP5(kk);
+ rgba[GCOMP] = UP5(kk >> 5);
+ rgba[RCOMP] = UP5(kk >> 10);
+ rgba[ACOMP] = 255;
+}
+
+
+static void
+fxt1_decode_1MIXED (const byte *code, int t, byte *rgba)
+{
+ const dword *cc;
+ int col[2][3];
+ int glsb, selb;
+
+ cc = (const dword *)code;
+ if (t & 16) {
+ t &= 15;
+ t = (cc[1] >> (t * 2)) & 3;
+ /* col 2 */
+ col[0][BCOMP] = (*(const dword *)(code + 11)) >> 6;
+ col[0][GCOMP] = CC_SEL(cc, 99);
+ col[0][RCOMP] = CC_SEL(cc, 104);
+ /* col 3 */
+ col[1][BCOMP] = CC_SEL(cc, 109);
+ col[1][GCOMP] = CC_SEL(cc, 114);
+ col[1][RCOMP] = CC_SEL(cc, 119);
+ glsb = CC_SEL(cc, 126);
+ selb = CC_SEL(cc, 33);
+ } else {
+ t = (cc[0] >> (t * 2)) & 3;
+ /* col 0 */
+ col[0][BCOMP] = CC_SEL(cc, 64);
+ col[0][GCOMP] = CC_SEL(cc, 69);
+ col[0][RCOMP] = CC_SEL(cc, 74);
+ /* col 1 */
+ col[1][BCOMP] = CC_SEL(cc, 79);
+ col[1][GCOMP] = CC_SEL(cc, 84);
+ col[1][RCOMP] = CC_SEL(cc, 89);
+ glsb = CC_SEL(cc, 125);
+ selb = CC_SEL(cc, 1);
+ }
+
+ if (CC_SEL(cc, 124) & 1) {
+ /* alpha[0] == 1 */
+
+ if (t == 3) {
+ ZERO_4UBV(rgba);
+ } else {
+ if (t == 0) {
+ rgba[BCOMP] = UP5(col[0][BCOMP]);
+ rgba[GCOMP] = UP5(col[0][GCOMP]);
+ rgba[RCOMP] = UP5(col[0][RCOMP]);
+ } else if (t == 2) {
+ rgba[BCOMP] = UP5(col[1][BCOMP]);
+ rgba[GCOMP] = UP6(col[1][GCOMP], glsb);
+ rgba[RCOMP] = UP5(col[1][RCOMP]);
+ } else {
+ rgba[BCOMP] = (UP5(col[0][BCOMP]) + UP5(col[1][BCOMP])) / 2;
+ rgba[GCOMP] = (UP5(col[0][GCOMP]) + UP6(col[1][GCOMP], glsb)) / 2;
+ rgba[RCOMP] = (UP5(col[0][RCOMP]) + UP5(col[1][RCOMP])) / 2;
+ }
+ rgba[ACOMP] = 255;
+ }
+ } else {
+ /* alpha[0] == 0 */
+
+ if (t == 0) {
+ rgba[BCOMP] = UP5(col[0][BCOMP]);
+ rgba[GCOMP] = UP6(col[0][GCOMP], glsb ^ selb);
+ rgba[RCOMP] = UP5(col[0][RCOMP]);
+ } else if (t == 3) {
+ rgba[BCOMP] = UP5(col[1][BCOMP]);
+ rgba[GCOMP] = UP6(col[1][GCOMP], glsb);
+ rgba[RCOMP] = UP5(col[1][RCOMP]);
+ } else {
+ rgba[BCOMP] = LERP(3, t, UP5(col[0][BCOMP]), UP5(col[1][BCOMP]));
+ rgba[GCOMP] = LERP(3, t, UP6(col[0][GCOMP], glsb ^ selb),
+ UP6(col[1][GCOMP], glsb));
+ rgba[RCOMP] = LERP(3, t, UP5(col[0][RCOMP]), UP5(col[1][RCOMP]));
+ }
+ rgba[ACOMP] = 255;
+ }
+}
+
+
+static void
+fxt1_decode_1ALPHA (const byte *code, int t, byte *rgba)
+{
+ const dword *cc;
+
+ cc = (const dword *)code;
+ if (CC_SEL(cc, 124) & 1) {
+ /* lerp == 1 */
+ int col0[4];
+
+ if (t & 16) {
+ t &= 15;
+ t = (cc[1] >> (t * 2)) & 3;
+ /* col 2 */
+ col0[BCOMP] = (*(const dword *)(code + 11)) >> 6;
+ col0[GCOMP] = CC_SEL(cc, 99);
+ col0[RCOMP] = CC_SEL(cc, 104);
+ col0[ACOMP] = CC_SEL(cc, 119);
+ } else {
+ t = (cc[0] >> (t * 2)) & 3;
+ /* col 0 */
+ col0[BCOMP] = CC_SEL(cc, 64);
+ col0[GCOMP] = CC_SEL(cc, 69);
+ col0[RCOMP] = CC_SEL(cc, 74);
+ col0[ACOMP] = CC_SEL(cc, 109);
+ }
+
+ if (t == 0) {
+ rgba[BCOMP] = UP5(col0[BCOMP]);
+ rgba[GCOMP] = UP5(col0[GCOMP]);
+ rgba[RCOMP] = UP5(col0[RCOMP]);
+ rgba[ACOMP] = UP5(col0[ACOMP]);
+ } else if (t == 3) {
+ rgba[BCOMP] = UP5(CC_SEL(cc, 79));
+ rgba[GCOMP] = UP5(CC_SEL(cc, 84));
+ rgba[RCOMP] = UP5(CC_SEL(cc, 89));
+ rgba[ACOMP] = UP5(CC_SEL(cc, 114));
+ } else {
+ rgba[BCOMP] = LERP(3, t, UP5(col0[BCOMP]), UP5(CC_SEL(cc, 79)));
+ rgba[GCOMP] = LERP(3, t, UP5(col0[GCOMP]), UP5(CC_SEL(cc, 84)));
+ rgba[RCOMP] = LERP(3, t, UP5(col0[RCOMP]), UP5(CC_SEL(cc, 89)));
+ rgba[ACOMP] = LERP(3, t, UP5(col0[ACOMP]), UP5(CC_SEL(cc, 114)));
+ }
+ } else {
+ /* lerp == 0 */
+
+ if (t & 16) {
+ cc++;
+ t &= 15;
+ }
+ t = (cc[0] >> (t * 2)) & 3;
+
+ if (t == 3) {
+ ZERO_4UBV(rgba);
+ } else {
+ dword kk;
+ cc = (const dword *)code;
+ rgba[ACOMP] = UP5(cc[3] >> (t * 5 + 13));
+ t *= 15;
+ cc = (const dword *)(code + 8 + t / 8);
+ kk = cc[0] >> (t & 7);
+ rgba[BCOMP] = UP5(kk);
+ rgba[GCOMP] = UP5(kk >> 5);
+ rgba[RCOMP] = UP5(kk >> 10);
+ }
+ }
+}
+
+
+TAPI void TAPIENTRY
+fxt1_decode_1 (const void *texture, int stride,
+ int i, int j, byte *rgba)
+{
+ static void (*decode_1[]) (const byte *, int, byte *) = {
+ fxt1_decode_1HI, /* cc-high = "00?" */
+ fxt1_decode_1HI, /* cc-high = "00?" */
+ fxt1_decode_1CHROMA, /* cc-chroma = "010" */
+ fxt1_decode_1ALPHA, /* alpha = "011" */
+ fxt1_decode_1MIXED, /* mixed = "1??" */
+ fxt1_decode_1MIXED, /* mixed = "1??" */
+ fxt1_decode_1MIXED, /* mixed = "1??" */
+ fxt1_decode_1MIXED /* mixed = "1??" */
+ };
+
+ const byte *code = (const byte *)texture +
+ ((j / 4) * (stride / 8) + (i / 8)) * 16;
+ int mode = CC_SEL(code, 125);
+ int t = i & 7;
+
+ if (t & 4) {
+ t += 12;
+ }
+ t += (j & 3) * 4;
+
+ decode_1[mode](code, t, rgba);
+
+#if VERBOSE
+ {
+ extern int cc_chroma;
+ extern int cc_alpha;
+ extern int cc_high;
+ extern int cc_mixed;
+ static int *cctype[] = {
+ &cc_high,
+ &cc_high,
+ &cc_chroma,
+ &cc_alpha,
+ &cc_mixed,
+ &cc_mixed,
+ &cc_mixed,
+ &cc_mixed
+ };
+ (*cctype[mode])++;
+ }
+#endif
+}
--- /dev/null
+/*
+ * FXT1 codec
+ * Version: 1.1
+ *
+ * Copyright (C) 2004 Daniel Borca 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
+ * DANIEL BORCA 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.
+ */
+
+
+#ifndef FXT1_H_included
+#define FXT1_H_included
+
+TAPI int TAPIENTRY
+fxt1_encode (int width, int height, int comps,
+ const void *source, int srcRowStride,
+ void *dest, int destRowStride);
+
+TAPI void TAPIENTRY
+fxt1_decode_1 (const void *texture, int stride /* in pixels */,
+ int i, int j, byte *rgba);
+
+#endif
--- /dev/null
+/*
+ * Texture compression
+ * Version: 1.0
+ *
+ * Copyright (C) 2004 Daniel Borca All Rights Reserved.
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#ifndef INTERNAL_H_included
+#define INTERNAL_H_included
+
+/*****************************************************************************\
+ * DLL stuff
+\*****************************************************************************/
+
+#ifdef __WIN32__
+#define TAPI __declspec(dllexport)
+#define TAPIENTRY /*__stdcall*/
+#else
+#define TAPI
+#define TAPIENTRY
+#endif
+
+
+/*****************************************************************************\
+ * 64bit types on 32bit machine
+\*****************************************************************************/
+
+#if defined(__GNUC__) && !defined(__cplusplus)
+
+typedef unsigned long long qword;
+
+#define Q_MOV32(a, b) a = b
+#define Q_OR32(a, b) a |= b
+#define Q_SHL(a, c) a <<= c
+
+#else /* !__GNUC__ */
+
+typedef struct {
+ dword lo, hi;
+} qword;
+
+#define Q_MOV32(a, b) a.lo = b
+#define Q_OR32(a, b) a.lo |= b
+#define Q_SHL(a, c) \
+ do { \
+ if ((c) >= 32) { \
+ a.hi = a.lo << ((c) - 32); \
+ a.lo = 0; \
+ } else { \
+ a.hi = (a.hi << (c)) | (a.lo >> (32 - (c)));\
+ a.lo <<= c; \
+ } \
+ } while (0)
+
+#endif /* !__GNUC__ */
+
+
+/*****************************************************************************\
+ * Config
+\*****************************************************************************/
+
+#define RCOMP 0
+#define GCOMP 1
+#define BCOMP 2
+#define ACOMP 3
+
+
+/*****************************************************************************\
+ * Metric
+\*****************************************************************************/
+
+#define F(i) (float)1 /* can be used to obtain an oblong metric: 0.30 / 0.59 / 0.11 */
+#define SAFECDOT 1 /* for paranoids */
+
+#define MAKEIVEC(NV, NC, IV, B, V0, V1) \
+ do { \
+ /* compute interpolation vector */\
+ float d2 = 0.0F; \
+ float rd2; \
+ \
+ for (i = 0; i < NC; i++) { \
+ IV[i] = (V1[i] - V0[i]) * F(i);\
+ d2 += IV[i] * IV[i]; \
+ } \
+ rd2 = (float)NV / d2; \
+ B = 0; \
+ for (i = 0; i < NC; i++) { \
+ IV[i] *= F(i); \
+ B -= IV[i] * V0[i]; \
+ IV[i] *= rd2; \
+ } \
+ B = B * rd2 + 0.5F; \
+ } while (0)
+
+#define CALCCDOT(TEXEL, NV, NC, IV, B, V)\
+ do { \
+ float dot = 0.0F; \
+ for (i = 0; i < NC; i++) { \
+ dot += V[i] * IV[i]; \
+ } \
+ TEXEL = (int)(dot + B); \
+ if (SAFECDOT) { \
+ if (TEXEL < 0) { \
+ TEXEL = 0; \
+ } else if (TEXEL > NV) { \
+ TEXEL = NV; \
+ } \
+ } \
+ } while (0)
+
+
+/*****************************************************************************\
+ * Utility functions
+\*****************************************************************************/
+
+void
+_mesa_upscale_teximage2d (unsigned int inWidth, unsigned int inHeight,
+ unsigned int outWidth, unsigned int outHeight,
+ unsigned int comps,
+ const byte *src, int srcRowStride,
+ unsigned char *dest);
+
+#endif
--- /dev/null
+# Texture compression
+# Version: 1.1
+#
+# Copyright (C) 2004 Daniel Borca All Rights Reserved.
+#
+# this is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# this 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Make; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+#
+# Available options:
+#
+# Environment variables:
+#
+# Targets:
+# all: build codec
+# clean: remove object files
+# realclean: remove all generated files
+#
+
+
+.PHONY: all clean realclean
+
+EXENAME = codec
+
+CC = gcc
+CFLAGS = -Wall -W -pedantic -ansi
+CFLAGS += -O2 -ffast-math -funroll-loops
+#CFLAGS += -fomit-frame-pointer -fexpensive-optimizations
+CFLAGS += -DVERBOSE=1
+
+LD = gcc
+LDFLAGS = -s
+LDLIBS =
+
+SOURCES = \
+ main.c \
+ tga.c \
+ util.c
+
+SOURCES += \
+ ../fxt1.c \
+ ../dxtn.c \
+ ../wrapper.c \
+ ../texstore.c
+
+OBJECTS = $(SOURCES:.c=.o)
+
+.c.o:
+ $(CC) -o $@ $(CFLAGS) -c $<
+
+all: $(EXENAME)
+
+$(EXENAME): $(OBJECTS)
+ $(LD) -o $@ $(LDFLAGS) $^
+
+clean:
+ -$(RM) $(OBJECTS)
+
+realclean: clean
+ -$(RM) $(EXENAME)
--- /dev/null
+/*
+ * Texture compression
+ * Version: 1.1
+ *
+ * Copyright (C) 2004 Daniel Borca All Rights Reserved.
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <GL/gl.h>
+
+#include "tga.h"
+#include "util.h"
+#include "../types.h"
+#include "../internal.h"
+#include "../fxt1.h"
+#include "../dxtn.h"
+
+
+#if VERBOSE
+int cc_chroma = 0;
+int cc_alpha = 0;
+int cc_high = 0;
+int cc_mixed = 0;
+#endif
+
+
+typedef int (*encoder) (int width, int height, int comps,
+ const void *source, int srcRowStride,
+ void *dest, int destRowStride);
+typedef void (*decoder) (const void *texture, int stride,
+ int i, int j, unsigned char *rgba);
+
+
+static struct {
+ const char *name;
+ int type;
+ encoder enc;
+ decoder dec;
+ int wround, hround;
+} *q = NULL, tc[] = {
+ { "fxt1rgba", GL_COMPRESSED_RGBA_FXT1_3DFX, fxt1_encode, fxt1_decode_1, 7, 3 },
+ { "fxt1rgb", GL_COMPRESSED_RGB_FXT1_3DFX, fxt1_encode, fxt1_decode_1, 7, 3 },
+ { "dxt1rgb", GL_COMPRESSED_RGB_S3TC_DXT1_EXT, dxt1_rgb_encode, dxt1_rgb_decode_1, 3, 3 },
+ { "dxt1rgba", GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, dxt1_rgba_encode, dxt1_rgba_decode_1, 3, 3 },
+ { "dxt3", GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, dxt3_rgba_encode, dxt3_rgba_decode_1, 3, 3 },
+ { "dxt5", GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, dxt5_rgba_encode, dxt5_rgba_decode_1, 3, 3 },
+ { NULL, -1, NULL, NULL, 0, 0 }
+};
+
+
+int
+main (int argc, char **argv)
+{
+ const char *myself = argv[0];
+ const char *inf = NULL, *outf = NULL, *cmpf = NULL, *a0 = NULL, *a1 = NULL;
+
+ int i, j;
+ int width, height;
+ void *input, *output;
+ unsigned char *rgba;
+#if VERBOSE
+ t_type t0;
+#endif
+
+ /* user options */
+ while (--argc) {
+ char *p = *++argv;
+ if (!strcmp(p, "-h") || !strcmp(p, "--help")) {
+ fprintf(stderr, "usage: %s [type] infile [-o outfile] [-k cfile] [-a0 inalpha] [-a1 outalpha]\n", myself);
+ fprintf(stderr, " infile must be a 24/32bpp TGA\n");
+ fprintf(stderr, " outfile will be a 32bpp TGA\n");
+ fprintf(stderr, " cfile will be the compressed file\n");
+ fprintf(stderr, " inalpha will be original alpha 32bpp TGA\n");
+ fprintf(stderr, " outalpha will be output alpha 32bpp TGA\n");
+ fprintf(stderr, " type can be one of the following:\n");
+ for (i = 0; tc[i].name != NULL; i++) {
+ fprintf(stderr, " -%s%s\n", tc[i].name, (i == 0) ? " (default)" : "");
+ }
+ return 0;
+ } /*else*/ if (!strcmp(p, "-o")) {
+ if (argc > 1) {
+ argc--;
+ outf = *++argv;
+ continue;
+ } else {
+ fprintf(stderr, "%s: argument to `%s' is missing\n", myself, p);
+ return -1;
+ }
+ } else if (!strcmp(p, "-k")) {
+ if (argc > 1) {
+ argc--;
+ cmpf = *++argv;
+ continue;
+ } else {
+ fprintf(stderr, "%s: argument to `%s' is missing\n", myself, p);
+ return -1;
+ }
+ } else if (!strcmp(p, "-a0")) {
+ if (argc > 1) {
+ argc--;
+ a0 = *++argv;
+ continue;
+ } else {
+ fprintf(stderr, "%s: argument to `%s' is missing\n", myself, p);
+ return -1;
+ }
+ } else if (!strcmp(p, "-a1")) {
+ if (argc > 1) {
+ argc--;
+ a1 = *++argv;
+ continue;
+ } else {
+ fprintf(stderr, "%s: argument to `%s' is missing\n", myself, p);
+ return -1;
+ }
+ } else if (*p == '-') {
+ for (q = tc; q->name != NULL; q++) {
+ if (!strcmp(p + 1, q->name)) {
+ break;
+ }
+ }
+ if (q->name != NULL) {
+ continue;
+ }
+ fprintf(stderr, "%s: bad option `%s'\n", myself, p);
+ return -1;
+ } else if (inf == NULL) {
+ inf = p;
+ continue;
+ }
+ fprintf(stderr, "%s: too many input files\n", myself);
+ return -1;
+ }
+ if (inf == NULL) {
+ fprintf(stderr, "%s: no input files\n", myself);
+ return -1;
+ }
+ if (outf == NULL) {
+ outf = "aout.tga";
+ }
+ if ((q == NULL) || (q->name == NULL)) {
+ q = tc;
+ }
+
+ /* get input data */
+#if 1
+ if (tga_read_32(inf, &width, &height, &input)) {
+ fprintf(stderr, "%s: cannot read `%s'\n", myself, inf);
+ return -1;
+ }
+#elif 0
+ {
+ static char pattern[8 * 32 + 1] = { "\
+ \
+ MMM EEEE SSS AAA \
+ M M M E S S A A \
+ M M M EEEE SS A A \
+ M M M E SS AAAAA \
+ M M E S S A A \
+ M M EEEE SSS A A \
+ " };
+
+ unsigned char (*texture)[8 * 32][4];
+ width = 32;
+ height = 8;
+ input = malloc(width * height * 4);
+ texture = (unsigned char (*)[8 * 32][4])input;
+ for (i = 0; i < sizeof(pattern) - 1; i++) {
+ switch (pattern[i]) {
+ default:
+ case ' ':
+ (*texture)[i][0] = 255;
+ (*texture)[i][1] = 255;
+ (*texture)[i][2] = 255;
+ (*texture)[i][3] = 64;
+ break;
+ case 'M':
+ (*texture)[i][0] = 255;
+ (*texture)[i][1] = 0;
+ (*texture)[i][2] = 0;
+ (*texture)[i][3] = 255;
+ break;
+ case 'E':
+ (*texture)[i][0] = 0;
+ (*texture)[i][1] = 255;
+ (*texture)[i][2] = 0;
+ (*texture)[i][3] = 255;
+ break;
+ case 'S':
+ (*texture)[i][0] = 0;
+ (*texture)[i][1] = 0;
+ (*texture)[i][2] = 255;
+ (*texture)[i][3] = 255;
+ break;
+ case 'A':
+ (*texture)[i][0] = 255;
+ (*texture)[i][1] = 255;
+ (*texture)[i][2] = 0;
+ (*texture)[i][3] = 255;
+ break;
+ }
+ }
+ }
+#else
+ {
+ unsigned char (*texture)[4 * 8][4];
+ width = 8;
+ height = 4;
+ input = malloc(width * height * 4);
+ texture = (unsigned char (*)[4 * 8][4])input;
+ for (i = 0; i < 4 * 8; i++) {
+ (*texture)[i][0] =
+ (*texture)[i][1] =
+ (*texture)[i][2] = 255 * i / 31;
+ (*texture)[i][3] = 255;
+ }
+ }
+#endif
+
+ /* make alpha tga (input values) */
+ if (a0 != NULL) {
+ unsigned long *alpha0 = malloc(width * height * 4);
+ if (alpha0) {
+ unsigned long *ap = alpha0;
+ for (j = 0; j < height; j++) {
+ for (i = 0; i < width; i++) {
+ unsigned char alp = ((unsigned char *)input)[(j * width + i) * 4 + 3];
+ *ap++ = alp | (alp << 8) | (alp << 16) | (alp << 24);
+ }
+ }
+ if (tga_write(a0, width, height, alpha0, 32) != 0) {
+ fprintf(stderr, "%s: cannot write `%s'\n", myself, a0);
+ }
+ free(alpha0);
+ }
+ }
+
+ /* allocate compressed output storage */
+ output = malloc(tc_size(width, height, q->type));
+ if (output == NULL) {
+ free(input);
+ fprintf(stderr, "%s: out of memory\n", myself);
+ return -1;
+ }
+
+ /* encode */
+#if VERBOSE
+ T_START(t0);
+#endif
+ q->enc(width, height, 4, input, width * 4, output, tc_stride(q->type, width));
+#if VERBOSE
+ T_STOP(t0);
+ fprintf(stderr, "ENC(%s): %lu ticks\n", q->name, T_DELTA(t0));
+#endif
+
+ /* free raw input data, make encoded data as input */
+ free(input);
+ input = output;
+
+ /* allocate uncompressed output storage */
+ width = (width + q->wround) & ~q->wround;
+ height = (height + q->hround) & ~q->hround;
+ output = malloc(width * height * 4);
+ if (output == NULL) {
+ free(input);
+ fprintf(stderr, "%s: out of memory\n", myself);
+ return -1;
+ }
+
+ /* decode */
+ rgba = output;
+#if VERBOSE
+ T_START(t0);
+#endif
+ for (j = 0; j < height; j++) {
+ for (i = 0; i < width; i++) {
+ q->dec(input, width, i, j, rgba);
+ rgba += 4;
+ }
+ }
+#if VERBOSE
+ T_STOP(t0);
+#endif
+
+ /* write encoded block */
+ if (cmpf != NULL) {
+ FILE *eff = fopen(cmpf, "wb");
+ if (eff) {
+ if (!fwrite(input, tc_size(width, height, q->type), 1, eff)) {
+ fprintf(stderr, "%s: cannot write compressed data\n", myself);
+ }
+ fclose(eff);
+ } else {
+ fprintf(stderr, "%s: cannot create `%s'\n", cmpf, myself);
+ }
+ }
+
+ /* free encoded block */
+ free(input);
+
+ /* write decoded block */
+ if (tga_write(outf, width, height, output, 32) != 0) {
+ fprintf(stderr, "%s: cannot write `%s'\n", myself, outf);
+ return -1;
+ }
+
+ /* make alpha tga (output values) */
+ if (a1 != NULL) {
+ unsigned long *alpha1 = malloc(width * height * 4);
+ if (alpha1) {
+ unsigned long *ap = alpha1;
+ for (j = 0; j < height; j++) {
+ for (i = 0; i < width; i++) {
+ unsigned char alp = ((unsigned char *)output)[(j * width + i) * 4 + 3];
+ *ap++ = alp | (alp << 8) | (alp << 16) | (alp << 24);
+ }
+ }
+ if (tga_write(a1, width, height, alpha1, 32) != 0) {
+ fprintf(stderr, "%s: cannot write `%s'\n", myself, a1);
+ }
+ free(alpha1);
+ }
+ }
+
+ /* free decoded block */
+ free(output);
+
+ /* final stats */
+#if VERBOSE
+ fprintf(stderr, "CHROMA = %d\n", cc_chroma);
+ fprintf(stderr, "ALPHA = %d\n", cc_alpha);
+ fprintf(stderr, "HIGH = %d\n", cc_high);
+ fprintf(stderr, "MIXED = %d\n", cc_mixed);
+ fprintf(stderr, "DEC(%s): %lu ticks\n", q->name, T_DELTA(t0));
+#endif
+
+ return 0;
+}
--- /dev/null
+/*
+ * TGA file handling
+ * Version: 1.1
+ *
+ * Copyright (C) 2004 Daniel Borca All Rights Reserved.
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "tga.h"
+
+
+int
+tga_read_32 (const char *filename, int *w, int *h, void **p)
+{
+ FILE *f;
+ void *img;
+ unsigned char header[18];
+ unsigned int skip_cmap_size;
+ unsigned int type, width, height, tga_bpp;
+ unsigned int raw_image_size;
+ unsigned char *raw_image;
+ unsigned int i, j, k;
+
+ if ((f = fopen(filename, "rb")) == NULL) {
+ return TGA_ERR_OPEN;
+ }
+
+ if (!fread(header, 18, 1, f)) {
+ fclose(f);
+ return TGA_ERR_READ;
+ }
+
+ type = header[2];
+ if (type != 2) {
+ fclose(f);
+ return TGA_ERR_FORMAT;
+ }
+ width = ((short *)header)[6];
+ height = ((short *)header)[7];
+ tga_bpp = header[16];
+
+ if (header[1]) {
+ skip_cmap_size = *(short *)&header[5] * header[7] >> 3;
+ } else {
+ skip_cmap_size = 0;
+ }
+ fseek(f, skip_cmap_size + header[0], SEEK_CUR);
+
+ raw_image_size = width * height;
+ switch (tga_bpp) {
+ case 16:
+ raw_image_size *= 2;
+ break;
+ case 24:
+ raw_image_size *= 3;
+ break;
+ case 32:
+ raw_image_size *= 4;
+ break;
+ default:
+ fclose(f);
+ return TGA_ERR_FORMAT;
+ }
+
+ if ((img = malloc(width * height * 4)) == NULL) {
+ fclose(f);
+ return TGA_ERR_MEM;
+ }
+
+ if ((raw_image = malloc(raw_image_size)) == NULL) {
+ free(img);
+ fclose(f);
+ return TGA_ERR_MEM;
+ }
+
+ if (!fread(raw_image, raw_image_size, 1, f)) {
+ free(raw_image);
+ free(img);
+ fclose(f);
+ return TGA_ERR_READ;
+ }
+
+ k = 0;
+ for (i = 0; i < height; i++) {
+ unsigned long decoded;
+ int l = (header[17] & 0x20) ? i : (height - i - 1);
+ unsigned char *bmp_line = (unsigned char *)img + l * width * 4;
+ for (j = 0; j < width; j++) {
+ switch (tga_bpp) {
+ case 16:
+ assert(0);
+ k += 2;
+ break;
+ case 24:
+ decoded = (*(unsigned long *)&raw_image[k]) | 0xff000000UL;
+ k += 3;
+ break;
+ case 32:
+ decoded = *(unsigned long *)&raw_image[k];
+ k += 4;
+ break;
+ default:
+ decoded = 0;
+ }
+ ((unsigned long *)bmp_line)[j] = decoded;
+ }
+ }
+
+ free(raw_image);
+ fclose(f);
+
+ *p = img;
+ *w = width;
+ *h = height;
+ return TGA_OK;
+}
+
+
+int
+tga_write (const char *filename, int width, int height, void *data, int bpp)
+{
+ int len;
+ char header[18];
+ FILE *f = fopen(filename, "wb");
+
+ if (f == NULL) {
+ return TGA_ERR_CREATE;
+ }
+
+ memset(header, 0, sizeof(header));
+ header[2] = 2;
+ ((unsigned short *)header)[6] = width;
+ ((unsigned short *)header)[7] = height;
+ header[16] = bpp;
+ header[17] |= 0x20;
+
+ len = width * height * ((header[16] + 7) / 8);
+
+ if (!fwrite(header, sizeof(header), 1, f) || !fwrite(data, len, 1, f)) {
+ return TGA_ERR_WRITE;
+ }
+
+ fclose(f);
+
+ return TGA_OK;
+}
--- /dev/null
+/*
+ * TGA file handling
+ * Version: 1.1
+ *
+ * Copyright (C) 2004 Daniel Borca All Rights Reserved.
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#ifndef TGA_H_included
+#define TGA_H_included
+
+#define TGA_OK 0
+#define TGA_ERR_MEM -2
+#define TGA_ERR_CREATE -3
+#define TGA_ERR_OPEN -4
+#define TGA_ERR_READ -5
+#define TGA_ERR_WRITE -6
+#define TGA_ERR_FORMAT -7
+
+int tga_read_32 (const char *filename, int *w, int *h, void **p);
+int tga_write (const char *filename, int width, int height, void *data, int bpp);
+
+#endif
--- /dev/null
+/*
+ * Texture compression
+ * Version: 1.1
+ *
+ * Copyright (C) 2004 Daniel Borca All Rights Reserved.
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <GL/gl.h>
+
+#include "util.h"
+
+
+#define GL_RGB_S3TC 0x83A0
+#define GL_RGB4_S3TC 0x83A1
+#define GL_RGBA_S3TC 0x83A2
+#define GL_RGBA4_S3TC 0x83A3
+
+
+int
+tc_stride (int format, unsigned int width)
+{
+ int stride;
+
+ switch (format) {
+ case GL_COMPRESSED_RGB_FXT1_3DFX:
+ case GL_COMPRESSED_RGBA_FXT1_3DFX:
+ stride = ((width + 7) / 8) * 16; /* 16 bytes per 8x4 tile */
+ break;
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ case GL_RGB_S3TC:
+ case GL_RGB4_S3TC:
+ stride = ((width + 3) / 4) * 8; /* 8 bytes per 4x4 tile */
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+ case GL_RGBA_S3TC:
+ case GL_RGBA4_S3TC:
+ stride = ((width + 3) / 4) * 16; /* 16 bytes per 4x4 tile */
+ break;
+ default:
+ return 0;
+ }
+
+ return stride;
+}
+
+
+unsigned int
+tc_size (unsigned int width, unsigned int height, int format)
+{
+ unsigned int size;
+
+ switch (format) {
+ case GL_COMPRESSED_RGB_FXT1_3DFX:
+ case GL_COMPRESSED_RGBA_FXT1_3DFX:
+ /* round up width to next multiple of 8, height to next multiple of 4 */
+ width = (width + 7) & ~7;
+ height = (height + 3) & ~3;
+ /* 16 bytes per 8x4 tile of RGB[A] texels */
+ size = width * height / 2;
+ /* Textures smaller than 8x4 will effectively be made into 8x4 and
+ * take 16 bytes.
+ */
+ if (size < 16)
+ size = 16;
+ return size;
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ case GL_RGB_S3TC:
+ case GL_RGB4_S3TC:
+ /* round up width, height to next multiple of 4 */
+ width = (width + 3) & ~3;
+ height = (height + 3) & ~3;
+ /* 8 bytes per 4x4 tile of RGB[A] texels */
+ size = width * height / 2;
+ /* Textures smaller than 4x4 will effectively be made into 4x4 and
+ * take 8 bytes.
+ */
+ if (size < 8)
+ size = 8;
+ return size;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+ case GL_RGBA_S3TC:
+ case GL_RGBA4_S3TC:
+ /* round up width, height to next multiple of 4 */
+ width = (width + 3) & ~3;
+ height = (height + 3) & ~3;
+ /* 16 bytes per 4x4 tile of RGBA texels */
+ size = width * height; /* simple! */
+ /* Textures smaller than 4x4 will effectively be made into 4x4 and
+ * take 16 bytes.
+ */
+ if (size < 16)
+ size = 16;
+ return size;
+ default:
+ return 0;
+ }
+}
+
+
+void *
+txs_read_fxt1 (const char *filename, int *width, int *height)
+{
+ FILE *f;
+ void *data;
+
+ char cookie[5];
+ float version;
+ int format;
+ int levels;
+ unsigned int offset;
+
+ int rv;
+
+ f = fopen(filename, "rb");
+ if (f == NULL) {
+ fprintf(stderr, "txs_read_fxt1: cannot open `%s'\n", filename);
+ return NULL;
+ }
+
+ if ((fscanf(f, "%4s %f %d %d %d %d %8x", cookie, &version,
+ &format, width, height, &levels,
+ &offset) != 7) ||
+ strcmp(cookie, "TXSF") ||
+ (version != 1.0) ||
+ (format != 17) ||
+ (*width & 7) ||
+ (*height & 4) ||
+ (levels != 1)) {
+ fclose(f);
+ fprintf(stderr, "txs_read_fxt1: bad TXS file %s\n", filename);
+ return NULL;
+ }
+
+ rv = tc_size(*width, *height, GL_COMPRESSED_RGBA_FXT1_3DFX);
+ data = malloc(rv);
+ if (data == NULL) {
+ fclose(f);
+ fprintf(stderr, "txs_read_fxt1: out of memory\n");
+ return NULL;
+ }
+
+ fseek(f, offset, SEEK_SET);
+ rv = fread(data, rv, 1, f);
+ fclose(f);
+
+ if (!rv) {
+ free(data);
+ data = NULL;
+ }
+
+ return data;
+}
--- /dev/null
+/*
+ * Texture compression
+ * Version: 1.1
+ *
+ * Copyright (C) 2004 Daniel Borca All Rights Reserved.
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#ifndef UTIL_H_included
+
+
+/*
+ * timer stuff
+ */
+#ifdef __DJGPP__
+
+typedef unsigned long long t_type;
+extern unsigned long long _rdtsc(void);
+#define T_START(t) do { t = _rdtsc(); } while (0)
+#define T_STOP(t) do { t = _rdtsc() - t; } while (0)
+#define T_DELTA(t) (unsigned long)(t & 0xffffffff)
+
+#elif defined(__linux__)
+
+#include <time.h>
+
+typedef clock_t t_type;
+#define T_START(t) do { t = clock(); } while (0)
+#define T_STOP(t) do { t = clock() - t; } while (0)
+#define T_DELTA(t) t
+
+#else /* !__linux__ */
+
+typedef int t_type;
+#define T_START(t) do { t = 0; } while (0)
+#define T_STOP(t) do { t = 0 - t; } while (0)
+#define T_DELTA(t) t
+
+#endif /* !__linux__ */
+
+
+/*
+ * compressed texture stuff
+ */
+int tc_stride (int format, unsigned int width);
+unsigned int tc_size (unsigned int width, unsigned int height, int format);
+
+
+/*
+ * specific stuff
+ */
+void *txs_read_fxt1 (const char *filename, int *width, int *height);
+
+
+#endif /* UTIL_H_included */
--- /dev/null
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.3
+ *
+ * Copyright (C) 1999-2004 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.
+ */
+
+
+#include <assert.h>
+
+#include "types.h"
+#include "internal.h"
+
+
+void
+_mesa_upscale_teximage2d (unsigned int inWidth, unsigned int inHeight,
+ unsigned int outWidth, unsigned int outHeight,
+ unsigned int comps,
+ const byte *src, int srcRowStride,
+ byte *dest)
+{
+ unsigned int i, j, k;
+
+ assert(outWidth >= inWidth);
+ assert(outHeight >= inHeight);
+
+ for (i = 0; i < outHeight; i++) {
+ const int ii = i % inHeight;
+ for (j = 0; j < outWidth; j++) {
+ const int jj = j % inWidth;
+ for (k = 0; k < comps; k++) {
+ dest[(i * outWidth + j) * comps + k]
+ = src[ii * srcRowStride + jj * comps + k];
+ }
+ }
+ }
+}
--- /dev/null
+#ifndef TYPES_H_included
+#define TYPES_H_included
+
+/*****************************************************************************\
+ * 32bit types
+\*****************************************************************************/
+typedef unsigned char byte; /* 8-bit */
+typedef unsigned short word; /* 16-bit */
+typedef unsigned int dword; /* 32-bit */
+
+#endif
--- /dev/null
+/*
+ * Texture compression
+ * Version: 1.0
+ *
+ * Copyright (C) 2004 Daniel Borca All Rights Reserved.
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include <assert.h>
+
+#include "types.h"
+#include "internal.h"
+#include "dxtn.h"
+
+
+#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
+#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
+
+
+TAPI void TAPIENTRY
+fetch_2d_texel_rgb_dxt1 (int texImage_RowStride,
+ const byte *texImage_Data,
+ int i, int j,
+ byte *texel)
+{
+ dxt1_rgb_decode_1(texImage_Data, texImage_RowStride, i, j, texel);
+}
+
+
+TAPI void TAPIENTRY
+fetch_2d_texel_rgba_dxt1 (int texImage_RowStride,
+ const byte *texImage_Data,
+ int i, int j,
+ byte *texel)
+{
+ dxt1_rgba_decode_1(texImage_Data, texImage_RowStride, i, j, texel);
+}
+
+
+TAPI void TAPIENTRY
+fetch_2d_texel_rgba_dxt3 (int texImage_RowStride,
+ const byte *texImage_Data,
+ int i, int j,
+ byte *texel)
+{
+ dxt3_rgba_decode_1(texImage_Data, texImage_RowStride, i, j, texel);
+}
+
+
+TAPI void TAPIENTRY
+fetch_2d_texel_rgba_dxt5 (int texImage_RowStride,
+ const byte *texImage_Data,
+ int i, int j,
+ byte *texel)
+{
+ dxt5_rgba_decode_1(texImage_Data, texImage_RowStride, i, j, texel);
+}
+
+
+TAPI void TAPIENTRY
+tx_compress_dxtn (int srccomps, int width, int height,
+ const byte *source, int destformat, byte *dest,
+ int destRowStride)
+{
+ int srcRowStride = width * srccomps;
+ int rv;
+
+ switch (destformat) {
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ rv = dxt1_rgb_encode(width, height, srccomps,
+ source, srcRowStride,
+ dest, destRowStride);
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ rv = dxt1_rgba_encode(width, height, srccomps,
+ source, srcRowStride,
+ dest, destRowStride);
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+ rv = dxt3_rgba_encode(width, height, srccomps,
+ source, srcRowStride,
+ dest, destRowStride);
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+ rv = dxt5_rgba_encode(width, height, srccomps,
+ source, srcRowStride,
+ dest, destRowStride);
+ break;
+ default:
+ assert(0);
+ }
+
+ /*return rv;*/
+}