applied Felix's patch for configuration system
[mesa.git] / src / mesa / drivers / dri / sis / sis_tex.c
1 /**************************************************************************
2
3 Copyright 2003 Eric Anholt
4 All Rights Reserved.
5
6 Permission is hereby granted, free of charge, to any person obtaining a
7 copy of this software and associated documentation files (the "Software"),
8 to deal in the Software without restriction, including without limitation
9 on the rights to use, copy, modify, merge, publish, distribute, sub
10 license, and/or sell copies of the Software, and to permit persons to whom
11 the Software is furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice (including the next
14 paragraph) shall be included in all copies or substantial portions of the
15 Software.
16
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
20 ERIC ANHOLT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
24 **************************************************************************/
25 /* $XFree86$ */
26
27 /*
28 * Authors:
29 * Eric Anholt <anholt@FreeBSD.org>
30 */
31
32 #include "sis_context.h"
33 #include "sis_alloc.h"
34 #include "sis_tex.h"
35
36 #include "swrast/swrast.h"
37 #include "imports.h"
38 #include "texformat.h"
39 #include "texstore.h"
40 #include "teximage.h"
41
42 #define ALIGN(value, align) (char *)((long)(value + align - 1) & ~(align - 1))
43
44 #define TEXTURE_HW_ALIGNMENT 4
45 #define TEXTURE_HW_PLUS (4 + 4)
46
47 static sisTexObjPtr
48 sisAllocTexObj( struct gl_texture_object *texObj )
49 {
50 sisTexObjPtr t;
51
52 t = (sisTexObjPtr) CALLOC_STRUCT( sis_tex_obj );
53 texObj->DriverData = t;
54 return t;
55 }
56
57 static void
58 sisAllocTexImage( sisContextPtr smesa, sisTexObjPtr t, int level,
59 const struct gl_texture_image *image )
60 {
61 char *addr;
62 int size, texel_size;
63
64 if (t->format == 0) {
65 t->format = image->Format;
66 switch (t->format)
67 {
68 case GL_RGBA:
69 t->hwformat = TEXEL_ARGB_8888_32;
70 break;
71 case GL_INTENSITY:
72 t->hwformat = TEXEL_I8;
73 break;
74 case GL_ALPHA:
75 t->hwformat = TEXEL_A8;
76 break;
77 case GL_LUMINANCE:
78 t->hwformat = TEXEL_L8;
79 break;
80 case GL_LUMINANCE_ALPHA:
81 t->hwformat = TEXEL_AL88;
82 break;
83 case GL_RGB:
84 t->hwformat = TEXEL_ARGB_0888_32;
85 break;
86 default:
87 assert(0);
88 }
89 }
90 assert(t->format == image->Format);
91
92 texel_size = image->TexFormat->TexelBytes;
93 size = image->Width * image->Height * texel_size + TEXTURE_HW_PLUS;
94
95 addr = sisAllocFB( smesa, size, &t->image[level].handle );
96 if (addr == NULL) {
97 addr = sisAllocAGP( smesa, size, &t->image[level].handle );
98 if (addr == NULL) {
99 fprintf (stderr, "SIS driver : out of video/agp memory\n");
100 sis_fatal_error();
101 }
102 t->image[level].memType = AGP_TYPE;
103 }
104 else
105 t->image[level].memType = VIDEO_TYPE;
106
107 t->image[level].Data = ALIGN(addr, TEXTURE_HW_ALIGNMENT);
108 t->image[level].pitch = image->Width * texel_size;
109 t->image[level].size = image->Width * image->Height * texel_size;
110 t->numImages++;
111 }
112
113 static void
114 sisFreeTexImage( sisContextPtr smesa, sisTexObjPtr t, int level )
115 {
116 if (t->image[level].Data == NULL)
117 return;
118
119 switch (t->image[level].memType)
120 {
121 case VIDEO_TYPE:
122 sisFreeFB( smesa, t->image[level].handle );
123 break;
124 case AGP_TYPE:
125 sisFreeAGP( smesa, t->image[level].handle );
126 break;
127 }
128 t->image[level].Data = NULL;
129 t->image[level].handle = NULL;
130 /* If there are no textures loaded any more, reset the hw format so the
131 * object can be reused for new formats
132 */
133 t->numImages--;
134 if (t->numImages == 0) {
135 t->format = 0;
136 t->hwformat = 0;
137 }
138 }
139
140 static void
141 sisDDTexEnv( GLcontext *ctx, GLenum target, GLenum pname, const GLfloat *param )
142 {
143 sisContextPtr smesa = SIS_CONTEXT(ctx);
144
145 smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURE_ENV;
146 }
147
148 static void
149 sisDDTexParameter( GLcontext *ctx, GLenum target,
150 struct gl_texture_object *texObj, GLenum pname,
151 const GLfloat *params )
152 {
153 sisContextPtr smesa = SIS_CONTEXT(ctx);
154
155 smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURING;
156 }
157
158 static void
159 sisDDBindTexture( GLcontext *ctx, GLenum target,
160 struct gl_texture_object *texObj )
161 {
162 sisContextPtr smesa = SIS_CONTEXT(ctx);
163 sisTexObjPtr t;
164
165 if ( target == GL_TEXTURE_2D || target == GL_TEXTURE_1D ) {
166 if ( texObj->DriverData == NULL ) {
167 sisAllocTexObj( texObj );
168 }
169 }
170
171 t = texObj->DriverData;
172
173 if (t == NULL)
174 return;
175
176 if (smesa->PrevTexFormat[ctx->Texture.CurrentUnit] != t->format) {
177 smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURE_ENV;
178 smesa->PrevTexFormat[ctx->Texture.CurrentUnit] = t->format;
179 }
180 smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURING;
181 }
182
183 static void
184 sisDDDeleteTexture( GLcontext * ctx, struct gl_texture_object *texObj )
185 {
186 sisContextPtr smesa = SIS_CONTEXT(ctx);
187 sisTexObjPtr t;
188 int i;
189
190 smesa->clearTexCache = GL_TRUE;
191
192 t = texObj->DriverData;
193 if (t == NULL) {
194 /*
195 * this shows the texture is default object and never be a
196 * argument of sisDDTexImage*
197 */
198 return;
199 }
200 for (i = 0; i < MAX_TEXTURE_LEVELS; i++) {
201 sisFreeTexImage( smesa, t, i );
202 }
203
204 FREE(t);
205 texObj->DriverData = NULL;
206 }
207
208 static GLboolean sisDDIsTextureResident( GLcontext * ctx,
209 struct gl_texture_object *texObj )
210 {
211 return (texObj->DriverData != NULL);
212 }
213
214 static const struct gl_texture_format *
215 sisDDChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
216 GLenum format, GLenum type )
217 {
218 /* XXX 16-bit internal texture formats? */
219 switch ( internalFormat ) {
220 case GL_ALPHA:
221 case GL_ALPHA4:
222 case GL_ALPHA8:
223 case GL_ALPHA12:
224 case GL_ALPHA16:
225 return &_mesa_texformat_a8;
226 case 1:
227 case GL_LUMINANCE:
228 case GL_LUMINANCE4:
229 case GL_LUMINANCE8:
230 case GL_LUMINANCE12:
231 case GL_LUMINANCE16:
232 return &_mesa_texformat_l8;
233 case 2:
234 case GL_LUMINANCE_ALPHA:
235 case GL_LUMINANCE4_ALPHA4:
236 case GL_LUMINANCE6_ALPHA2:
237 case GL_LUMINANCE8_ALPHA8:
238 case GL_LUMINANCE12_ALPHA4:
239 case GL_LUMINANCE12_ALPHA12:
240 case GL_LUMINANCE16_ALPHA16:
241 return &_mesa_texformat_al88;
242 case GL_INTENSITY:
243 case GL_INTENSITY4:
244 case GL_INTENSITY8:
245 case GL_INTENSITY12:
246 case GL_INTENSITY16:
247 return &_mesa_texformat_i8;
248 case GL_R3_G3_B2:
249 case GL_RGB4:
250 case GL_RGB5:
251 case 3:
252 case GL_RGB:
253 case GL_RGB8:
254 case GL_RGB10:
255 case GL_RGB12:
256 case GL_RGB16:
257 return &_mesa_texformat_argb8888 /*_mesa_texformat_rgb888*/; /* XXX */
258 case GL_RGBA2:
259 case GL_RGBA4:
260 case GL_RGB5_A1:
261 case 4:
262 case GL_RGBA:
263 case GL_RGBA8:
264 case GL_RGB10_A2:
265 case GL_RGBA12:
266 case GL_RGBA16:
267 return &_mesa_texformat_argb8888;
268 default:
269 _mesa_problem(ctx, "unexpected format in tdfxDDChooseTextureFormat: %d",
270 internalFormat);
271 return NULL;
272 }
273 }
274
275 static void sisDDTexImage1D( GLcontext *ctx, GLenum target, GLint level,
276 GLint internalFormat,
277 GLint width, GLint border,
278 GLenum format, GLenum type, const GLvoid *pixels,
279 const struct gl_pixelstore_attrib *packing,
280 struct gl_texture_object *texObj,
281 struct gl_texture_image *texImage )
282 {
283 sisContextPtr smesa = SIS_CONTEXT(ctx);
284 sisTexObjPtr t;
285
286 if ( texObj->DriverData == NULL )
287 sisAllocTexObj( texObj );
288 t = texObj->DriverData;
289
290 /* Note, this will call sisDDChooseTextureFormat */
291 _mesa_store_teximage1d( ctx, target, level, internalFormat,
292 width, border, format, type,
293 pixels, packing, texObj, texImage );
294
295 /* Allocate offscreen space for the texture */
296 sisFreeTexImage(smesa, t, level);
297 sisAllocTexImage(smesa, t, level, texImage);
298
299 /* Upload the texture */
300 memcpy(t->image[level].Data, texImage->Data, t->image[level].size);
301
302 if (smesa->PrevTexFormat[ctx->Texture.CurrentUnit] != t->format)
303 {
304 smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURE_ENV;
305 smesa->PrevTexFormat[ctx->Texture.CurrentUnit] = t->format;
306 }
307 smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURING;
308 }
309
310
311 static void sisDDTexSubImage1D( GLcontext *ctx,
312 GLenum target,
313 GLint level,
314 GLint xoffset,
315 GLsizei width,
316 GLenum format, GLenum type,
317 const GLvoid *pixels,
318 const struct gl_pixelstore_attrib *packing,
319 struct gl_texture_object *texObj,
320 struct gl_texture_image *texImage )
321 {
322 sisContextPtr smesa = SIS_CONTEXT(ctx);
323 sisTexObjPtr t;
324 GLuint copySize;
325 GLint texelBytes;
326 char *src, *dst;
327
328 if ( texObj->DriverData == NULL )
329 sisAllocTexObj( texObj );
330 t = texObj->DriverData;
331
332 _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
333 format, type, pixels, packing, texObj,
334 texImage);
335
336 /* Allocate offscreen space for the texture */
337 sisFreeTexImage(smesa, t, level);
338 sisAllocTexImage(smesa, t, level, texImage);
339
340 /* Upload the texture */
341 texelBytes = texImage->TexFormat->TexelBytes;
342
343 copySize = width * texelBytes;
344 src = (char *)texImage->Data + xoffset * texelBytes;
345 dst = t->image[level].Data + xoffset * texelBytes;
346
347 memcpy( dst, src, copySize );
348
349 smesa->clearTexCache = GL_TRUE;
350
351 if (smesa->PrevTexFormat[ctx->Texture.CurrentUnit] != t->format)
352 {
353 smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURE_ENV;
354 smesa->PrevTexFormat[ctx->Texture.CurrentUnit] = t->format;
355 }
356 smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURING;
357 }
358
359 static void sisDDTexImage2D( GLcontext *ctx, GLenum target, GLint level,
360 GLint internalFormat,
361 GLint width, GLint height, GLint border,
362 GLenum format, GLenum type, const GLvoid *pixels,
363 const struct gl_pixelstore_attrib *packing,
364 struct gl_texture_object *texObj,
365 struct gl_texture_image *texImage )
366 {
367 sisContextPtr smesa = SIS_CONTEXT(ctx);
368 sisTexObjPtr t;
369
370 if ( texObj->DriverData == NULL )
371 sisAllocTexObj( texObj );
372 t = texObj->DriverData;
373
374 /* Note, this will call sisDDChooseTextureFormat */
375 _mesa_store_teximage2d(ctx, target, level, internalFormat,
376 width, height, border, format, type, pixels,
377 &ctx->Unpack, texObj, texImage);
378
379 /* Allocate offscreen space for the texture */
380 sisFreeTexImage(smesa, t, level);
381 sisAllocTexImage(smesa, t, level, texImage);
382
383 /* Upload the texture */
384 memcpy(t->image[level].Data, texImage->Data, t->image[level].size);
385
386 if (smesa->PrevTexFormat[ctx->Texture.CurrentUnit] != t->format)
387 {
388 smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURE_ENV;
389 smesa->PrevTexFormat[ctx->Texture.CurrentUnit] = t->format;
390 }
391 smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURING;
392 }
393
394 static void sisDDTexSubImage2D( GLcontext *ctx,
395 GLenum target,
396 GLint level,
397 GLint xoffset, GLint yoffset,
398 GLsizei width, GLsizei height,
399 GLenum format, GLenum type,
400 const GLvoid *pixels,
401 const struct gl_pixelstore_attrib *packing,
402 struct gl_texture_object *texObj,
403 struct gl_texture_image *texImage )
404 {
405 sisContextPtr smesa = SIS_CONTEXT(ctx);
406 sisTexObjPtr t;
407 GLuint copySize;
408 GLint texelBytes;
409 char *src, *dst;
410 int j;
411 GLuint soffset;
412
413 if ( texObj->DriverData == NULL )
414 sisAllocTexObj( texObj );
415 t = texObj->DriverData;
416
417 _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
418 height, format, type, pixels, packing, texObj,
419 texImage);
420
421 /* Allocate offscreen space for the texture */
422 sisFreeTexImage(smesa, t, level);
423 sisAllocTexImage(smesa, t, level, texImage);
424
425 /* Upload the texture */
426 texelBytes = texImage->TexFormat->TexelBytes;
427
428 copySize = width * texelBytes;
429 src = (char *)texImage->Data + (xoffset + yoffset * texImage->Width) *
430 texelBytes;
431 dst = t->image[level].Data + (xoffset + yoffset * texImage->Width) *
432 texelBytes;
433 soffset = texImage->Width * texelBytes;
434
435 for (j = yoffset; j < yoffset + height; j++) {
436 memcpy( dst, src, copySize );
437 src += soffset;
438 dst += soffset;
439 }
440
441 smesa->clearTexCache = GL_TRUE;
442
443 if (smesa->PrevTexFormat[ctx->Texture.CurrentUnit] != t->format)
444 {
445 smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURE_ENV;
446 smesa->PrevTexFormat[ctx->Texture.CurrentUnit] = t->format;
447 }
448 smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURING;
449
450 }
451
452 void sisDDInitTextureFuncs( GLcontext *ctx )
453 {
454 ctx->Driver.TexEnv = sisDDTexEnv;
455 ctx->Driver.ChooseTextureFormat = sisDDChooseTextureFormat;
456 ctx->Driver.TexImage1D = sisDDTexImage1D;
457 ctx->Driver.TexSubImage1D = sisDDTexSubImage1D;
458 ctx->Driver.TexImage2D = sisDDTexImage2D;
459 ctx->Driver.TexSubImage2D = sisDDTexSubImage2D;
460 ctx->Driver.TexImage3D = _mesa_store_teximage3d;
461 ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
462 ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d;
463 ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d;
464 ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d;
465 ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d;
466 ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d;
467 ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage;
468 ctx->Driver.TexParameter = sisDDTexParameter;
469 ctx->Driver.BindTexture = sisDDBindTexture;
470 ctx->Driver.DeleteTexture = sisDDDeleteTexture;
471 ctx->Driver.IsTextureResident = sisDDIsTextureResident;
472 ctx->Driver.PrioritizeTexture = NULL;
473 }