small fixes wrt texture handling
[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 if (ctx->Driver.CompressedTextureSize) {
100 return ctx->Driver.CompressedTextureSize(ctx, width, height, depth, format);
101 }
102
103 switch (format) {
104 case GL_COMPRESSED_RGB_FXT1_3DFX:
105 case GL_COMPRESSED_RGBA_FXT1_3DFX:
106 /* round up to multiples of 8, 4 */
107 size = ((width + 7) / 8) * ((height + 3) / 4) * 16;
108 /* Textures smaller than 8x4 will effectively be made into 8x4 and
109 * take 16 bytes.
110 */
111 if (size < 16)
112 size = 16;
113 return size;
114 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
115 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
116 /* round up width, height to next multiple of 4 */
117 width = (width + 3) & ~3;
118 height = (height + 3) & ~3;
119 ASSERT(depth == 1);
120 /* 8 bytes per 4x4 tile of RGB[A] texels */
121 size = (width * height * 8) / 16;
122 /* Textures smaller than 4x4 will effectively be made into 4x4 and
123 * take 8 bytes.
124 */
125 if (size < 8)
126 size = 8;
127 return size;
128 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
129 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
130 /* round up width, height to next multiple of 4 */
131 width = (width + 3) & ~3;
132 height = (height + 3) & ~3;
133 ASSERT(depth == 1);
134 /* 16 bytes per 4x4 tile of RGBA texels */
135 size = width * height; /* simple! */
136 /* Textures smaller than 4x4 will effectively be made into 4x4 and
137 * take 16 bytes.
138 */
139 if (size < 16)
140 size = 16;
141 return size;
142 default:
143 _mesa_problem(ctx, "bad texformat in compressed_texture_size");
144 return 0;
145 }
146 }
147
148
149 /**
150 * Compute the bytes per row in a compressed texture image.
151 * We use this for computing the destination address for sub-texture updates.
152 * \param format one of the specific texture compression formats
153 * \param width image width in pixels
154 * \return stride, in bytes, between rows for compressed image
155 */
156 GLint
157 _mesa_compressed_row_stride(GLenum format, GLsizei width)
158 {
159 GLint bytesPerTile, stride;
160
161 switch (format) {
162 case GL_COMPRESSED_RGB_FXT1_3DFX:
163 case GL_COMPRESSED_RGBA_FXT1_3DFX:
164 bytesPerTile = 16;
165 break;
166 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
167 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
168 bytesPerTile = 8;
169 break;
170 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
171 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
172 bytesPerTile = 16;
173 break;
174 default:
175 return 0;
176 }
177
178 stride = ((width + 3) / 4) * bytesPerTile;
179 return stride;
180 }
181
182
183 /**
184 * Return the address of the pixel at (col, row, img) in a
185 * compressed texture image.
186 *
187 * \param col image position.
188 * \param row image position.
189 * \param img image position.
190 * \param format compressed image format.
191 * \param width image width.
192 * \param image the image address.
193 *
194 * \return address of pixel at (row, col).
195 */
196 GLubyte *
197 _mesa_compressed_image_address(GLint col, GLint row, GLint img,
198 GLenum format,
199 GLsizei width, const GLubyte *image)
200 {
201 GLint bytesPerTile, stride;
202 GLubyte *addr;
203
204 ASSERT((row & 3) == 0);
205 ASSERT((col & 3) == 0);
206 (void) img;
207
208 switch (format) {
209 case GL_COMPRESSED_RGB_FXT1_3DFX:
210 case GL_COMPRESSED_RGBA_FXT1_3DFX:
211 bytesPerTile = 16;
212 break;
213 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
214 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
215 bytesPerTile = 8;
216 break;
217 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
218 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
219 bytesPerTile = 16;
220 break;
221 default:
222 return 0;
223 }
224
225 stride = ((width + 3) / 4) * bytesPerTile;
226
227 addr = (GLubyte *) image + (row / 4) * stride + (col / 4) * bytesPerTile;
228 return addr;
229 }
230
231
232 /**
233 * \param srcRowStride source stride, in pixels
234 */
235 void
236 _mesa_compress_teximage( GLcontext *ctx, GLsizei width, GLsizei height,
237 GLenum srcFormat, const GLchan *source,
238 GLint srcRowStride,
239 const struct gl_texture_format *dstFormat,
240 GLubyte *dest, GLint dstRowStride )
241 {
242 switch (dstFormat->MesaFormat) {
243 default:
244 _mesa_problem(ctx, "Bad dstFormat in _mesa_compress_teximage()");
245 return;
246 }
247 }