Merge Jose's documentation and core Mesa changes from embedded branch
[mesa.git] / src / mesa / main / texcompress.c
1 /**
2 * \file texcompress.c
3 * Compressed textures functions.
4 */
5
6 /*
7 * Mesa 3-D graphics library
8 * Version: 5.1
9 *
10 * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
11 *
12 * Permission is hereby granted, free of charge, to any person obtaining a
13 * copy of this software and associated documentation files (the "Software"),
14 * to deal in the Software without restriction, including without limitation
15 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 * and/or sell copies of the Software, and to permit persons to whom the
17 * Software is furnished to do so, subject to the following conditions:
18 *
19 * The above copyright notice and this permission notice shall be included
20 * in all copies or substantial portions of the Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
27 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 */
29
30
31 #include "glheader.h"
32 #include "imports.h"
33 #include "context.h"
34 #include "image.h"
35 #include "texcompress.h"
36 #include "texformat.h"
37
38
39 /**
40 * Get the list of supported internal compression formats.
41 *
42 * \param ctx GL context.
43 * \param formats the resulting format list (may be NULL).
44 *
45 * \return number of formats.
46 */
47 GLuint
48 _mesa_get_compressed_formats( GLcontext *ctx, GLint *formats )
49 {
50 GLuint n = 0;
51 if (ctx->Extensions.ARB_texture_compression) {
52 if (ctx->Extensions.TDFX_texture_compression_FXT1) {
53 if (formats) {
54 formats[n++] = GL_COMPRESSED_RGB_FXT1_3DFX;
55 formats[n++] = GL_COMPRESSED_RGBA_FXT1_3DFX;
56 }
57 else {
58 n += 2;
59 }
60 }
61 if (ctx->Extensions.EXT_texture_compression_s3tc) {
62 if (formats) {
63 formats[n++] = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
64 /* Skip this one because it has a restriction (all transparent
65 * pixels become black). See the texture compressions spec for
66 * a detailed explanation. This is what NVIDIA does.
67 formats[n++] = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
68 */
69 formats[n++] = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
70 formats[n++] = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
71 }
72 else {
73 n += 3;
74 }
75 }
76 }
77 return n;
78 }
79
80
81 /**
82 * Return bytes of storage needed for the given texture size and
83 * compressed format.
84 *
85 * \param width texture width in texels.
86 * \param height texture height in texels.
87 * \param depth texture depth in texels.
88 * \param texFormat one of the compressed format enums
89 *
90 * \return size in bytes, or zero if bad \p texFormat.
91 */
92 GLuint
93 _mesa_compressed_texture_size( GLcontext *ctx,
94 GLsizei width, GLsizei height, GLsizei depth,
95 GLenum format )
96 {
97 GLuint size;
98
99 switch (format) {
100 case GL_COMPRESSED_RGB_FXT1_3DFX:
101 case GL_COMPRESSED_RGBA_FXT1_3DFX:
102 /* round up to multiple of 4 */
103 size = ((width + 7) / 8) * ((height + 3) / 4) * 16;
104 return size;
105 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
106 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
107 /* round up width, height to next multiple of 4 */
108 width = (width + 3) & ~3;
109 height = (height + 3) & ~3;
110 ASSERT(depth == 1);
111 /* 8 bytes per 4x4 tile of RGB[A] texels */
112 size = (width * height * 8) / 16;
113 /* Textures smaller than 4x4 will effectively be made into 4x4 and
114 * take 8 bytes.
115 */
116 if (size < 8)
117 size = 8;
118 return size;
119 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
120 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
121 /* round up width, height to next multiple of 4 */
122 width = (width + 3) & ~3;
123 height = (height + 3) & ~3;
124 ASSERT(depth == 1);
125 /* 16 bytes per 4x4 tile of RGBA texels */
126 size = width * height; /* simple! */
127 /* Textures smaller than 4x4 will effectively be made into 4x4 and
128 * take 16 bytes.
129 */
130 if (size < 16)
131 size = 16;
132 return size;
133 default:
134 _mesa_problem(ctx, "bad texformat in compressed_texture_size");
135 return 0;
136 }
137 }
138
139
140 /**
141 * Compute the bytes per row in a compressed texture image.
142 * We use this for computing the destination address for sub-texture updates.
143 * \param format one of the specific texture compression formats
144 * \param width image width in pixels
145 * \return stride, in bytes, between rows for compressed image
146 */
147 GLint
148 _mesa_compressed_row_stride(GLenum format, GLsizei width)
149 {
150 GLint bytesPerTile, stride;
151
152 switch (format) {
153 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
154 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
155 bytesPerTile = 8;
156 break;
157 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
158 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
159 bytesPerTile = 16;
160 break;
161 default:
162 return 0;
163 }
164
165 stride = ((width + 3) / 4) * bytesPerTile;
166 return stride;
167 }
168
169
170 /**
171 * Return the address of the pixel at (col, row, img) in a
172 * compressed texture image.
173 *
174 * \param col image position.
175 * \param row image position.
176 * \param img image position.
177 * \param format compressed image format.
178 * \param width image width.
179 * \param image the image address.
180 *
181 * \return address of pixel at (row, col).
182 */
183 GLubyte *
184 _mesa_compressed_image_address(GLint col, GLint row, GLint img,
185 GLenum format,
186 GLsizei width, const GLubyte *image)
187 {
188 GLint bytesPerTile, stride;
189 GLubyte *addr;
190
191 ASSERT((row & 3) == 0);
192 ASSERT((col & 3) == 0);
193 (void) img;
194
195 switch (format) {
196 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
197 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
198 bytesPerTile = 8;
199 break;
200 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
201 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
202 bytesPerTile = 16;
203 break;
204 default:
205 return 0;
206 }
207
208 stride = ((width + 3) / 4) * bytesPerTile;
209
210 addr = (GLubyte *) image + (row / 4) * stride + (col / 4) * bytesPerTile;
211 return addr;
212 }
213
214
215 /**
216 * \param srcRowStride source stride, in pixels
217 */
218 void
219 _mesa_compress_teximage( GLcontext *ctx, GLsizei width, GLsizei height,
220 GLenum srcFormat, const GLchan *source,
221 GLint srcRowStride,
222 const struct gl_texture_format *dstFormat,
223 GLubyte *dest, GLint dstRowStride )
224 {
225 switch (dstFormat->MesaFormat) {
226 default:
227 _mesa_problem(ctx, "Bad dstFormat in _mesa_compress_teximage()");
228 return;
229 }
230 }