Minor tweaks to help out at a driver level.
[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 if (ctx->Extensions.S3_s3tc) {
77 if (formats) {
78 formats[n++] = GL_RGB_S3TC;
79 formats[n++] = GL_RGB4_S3TC;
80 formats[n++] = GL_RGBA_S3TC;
81 formats[n++] = GL_RGBA4_S3TC;
82 }
83 else {
84 n += 4;
85 }
86 }
87 }
88 return n;
89 }
90
91
92 /**
93 * Return bytes of storage needed for the given texture size and
94 * compressed format.
95 *
96 * \param width texture width in texels.
97 * \param height texture height in texels.
98 * \param depth texture depth in texels.
99 * \param texFormat one of the compressed format enums
100 *
101 * \return size in bytes, or zero if bad \p texFormat.
102 */
103 GLuint
104 _mesa_compressed_texture_size( GLcontext *ctx,
105 GLsizei width, GLsizei height, GLsizei depth,
106 GLenum format )
107 {
108 GLuint size;
109
110 if (ctx->Driver.CompressedTextureSize) {
111 return ctx->Driver.CompressedTextureSize(ctx, width, height, depth, format);
112 }
113
114 ASSERT(depth == 1);
115
116 switch (format) {
117 case GL_COMPRESSED_RGB_FXT1_3DFX:
118 case GL_COMPRESSED_RGBA_FXT1_3DFX:
119 /* round up width to next multiple of 8, height to next multiple of 4 */
120 width = (width + 7) & ~7;
121 height = (height + 3) & ~3;
122 /* 16 bytes per 8x4 tile of RGB[A] texels */
123 size = width * height / 2;
124 /* Textures smaller than 8x4 will effectively be made into 8x4 and
125 * take 16 bytes.
126 */
127 if (size < 16)
128 size = 16;
129 return size;
130 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
131 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
132 case GL_RGB_S3TC:
133 case GL_RGB4_S3TC:
134 /* round up width, height to next multiple of 4 */
135 width = (width + 3) & ~3;
136 height = (height + 3) & ~3;
137 /* 8 bytes per 4x4 tile of RGB[A] texels */
138 size = width * height / 2;
139 /* Textures smaller than 4x4 will effectively be made into 4x4 and
140 * take 8 bytes.
141 */
142 if (size < 8)
143 size = 8;
144 return size;
145 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
146 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
147 case GL_RGBA_S3TC:
148 case GL_RGBA4_S3TC:
149 /* round up width, height to next multiple of 4 */
150 width = (width + 3) & ~3;
151 height = (height + 3) & ~3;
152 /* 16 bytes per 4x4 tile of RGBA texels */
153 size = width * height; /* simple! */
154 /* Textures smaller than 4x4 will effectively be made into 4x4 and
155 * take 16 bytes.
156 */
157 if (size < 16)
158 size = 16;
159 return size;
160 default:
161 _mesa_problem(ctx, "bad texformat in compressed_texture_size");
162 return 0;
163 }
164 }
165
166
167 /**
168 * Compute the bytes per row in a compressed texture image.
169 * We use this for computing the destination address for sub-texture updates.
170 * \param format one of the specific texture compression formats
171 * \param width image width in pixels
172 * \return stride, in bytes, between rows for compressed image
173 */
174 GLint
175 _mesa_compressed_row_stride(GLenum format, GLsizei width)
176 {
177 GLint stride;
178
179 switch (format) {
180 case GL_COMPRESSED_RGB_FXT1_3DFX:
181 case GL_COMPRESSED_RGBA_FXT1_3DFX:
182 stride = ((width + 7) / 8) * 16; /* 16 bytes per 8x4 tile */
183 break;
184 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
185 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
186 case GL_RGB_S3TC:
187 case GL_RGB4_S3TC:
188 stride = ((width + 3) / 4) * 8; /* 8 bytes per 4x4 tile */
189 break;
190 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
191 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
192 case GL_RGBA_S3TC:
193 case GL_RGBA4_S3TC:
194 stride = ((width + 3) / 4) * 16; /* 16 bytes per 4x4 tile */
195 break;
196 default:
197 return 0;
198 }
199
200 return stride;
201 }
202
203
204 /**
205 * Return the address of the pixel at (col, row, img) in a
206 * compressed texture image.
207 *
208 * \param col image position.
209 * \param row image position.
210 * \param img image position.
211 * \param format compressed image format.
212 * \param width image width.
213 * \param image the image address.
214 *
215 * \return address of pixel at (row, col).
216 */
217 GLubyte *
218 _mesa_compressed_image_address(GLint col, GLint row, GLint img,
219 GLenum format,
220 GLsizei width, const GLubyte *image)
221 {
222 GLubyte *addr;
223
224 (void) img;
225
226 /* We try to spot a "complete" subtexture "above" ROW, COL;
227 * this texture is given by appropriate rounding of WIDTH x ROW.
228 * Then we just add the amount left (usually on the left).
229 *
230 * Example for X*Y microtiles (Z bytes each)
231 * offset = Z * (((width + X - 1) / X) * (row / Y) + col / X);
232 */
233
234 switch (format) {
235 case GL_COMPRESSED_RGB_FXT1_3DFX:
236 case GL_COMPRESSED_RGBA_FXT1_3DFX:
237 addr = (GLubyte *) image + 16 * (((width + 7) / 8) * (row / 4) + col / 8);
238 break;
239 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
240 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
241 case GL_RGB_S3TC:
242 case GL_RGB4_S3TC:
243 addr = (GLubyte *) image + 8 * (((width + 3) / 4) * (row / 4) + col / 4);
244 break;
245 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
246 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
247 case GL_RGBA_S3TC:
248 case GL_RGBA4_S3TC:
249 addr = (GLubyte *) image + 16 * (((width + 3) / 4) * (row / 4) + col / 4);
250 break;
251 default:
252 return 0;
253 }
254
255 return addr;
256 }
257
258
259 /**
260 * \param srcRowStride source stride, in pixels
261 */
262 void
263 _mesa_compress_teximage( GLcontext *ctx, GLsizei width, GLsizei height,
264 GLenum srcFormat, const GLchan *source,
265 GLint srcRowStride,
266 const struct gl_texture_format *dstFormat,
267 GLubyte *dest, GLint dstRowStride )
268 {
269 switch (dstFormat->MesaFormat) {
270 default:
271 _mesa_problem(ctx, "Bad dstFormat in _mesa_compress_teximage()");
272 return;
273 }
274 }