Use SecondaryColorPtr, not ColorPtr[1] (the latter is NULL).
[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 #include "texobj.h"
42
43 #define ALIGN(value, align) (GLubyte *)((long)(value + align - 1) & ~(align - 1))
44
45 #define TEXTURE_HW_ALIGNMENT 4
46 #define TEXTURE_HW_PLUS (4 + 4)
47
48 static sisTexObjPtr
49 sisAllocTexObj( struct gl_texture_object *texObj )
50 {
51 sisTexObjPtr t;
52
53 t = (sisTexObjPtr) CALLOC_STRUCT( sis_tex_obj );
54 texObj->DriverData = t;
55 return t;
56 }
57
58 static void
59 sisAllocTexImage( sisContextPtr smesa, sisTexObjPtr t, int level,
60 const struct gl_texture_image *image )
61 {
62 char *addr;
63 int size, texel_size;
64
65 if (t->format == 0) {
66 t->format = image->Format;
67 switch (t->format)
68 {
69 case GL_RGBA:
70 t->hwformat = TEXEL_ARGB_8888_32;
71 break;
72 case GL_INTENSITY:
73 t->hwformat = TEXEL_I8;
74 break;
75 case GL_ALPHA:
76 t->hwformat = TEXEL_A8;
77 break;
78 case GL_LUMINANCE:
79 t->hwformat = TEXEL_L8;
80 break;
81 case GL_LUMINANCE_ALPHA:
82 t->hwformat = TEXEL_AL88;
83 break;
84 case GL_RGB:
85 t->hwformat = TEXEL_ARGB_0888_32;
86 break;
87 default:
88 sis_fatal_error("Bad texture format.\n");
89 }
90 }
91 assert(t->format == image->Format);
92
93 texel_size = image->TexFormat->TexelBytes;
94 size = image->Width * image->Height * texel_size + TEXTURE_HW_PLUS;
95
96 addr = sisAllocFB( smesa, size, &t->image[level].handle );
97 if (addr == NULL) {
98 addr = sisAllocAGP( smesa, size, &t->image[level].handle );
99 if (addr == NULL)
100 sis_fatal_error("Failure to allocate texture memory.\n");
101 t->image[level].memType = AGP_TYPE;
102 }
103 else
104 t->image[level].memType = VIDEO_TYPE;
105
106 t->image[level].Data = ALIGN(addr, TEXTURE_HW_ALIGNMENT);
107 t->image[level].pitch = image->Width * texel_size;
108 t->image[level].size = image->Width * image->Height * texel_size;
109 t->numImages++;
110 }
111
112 static void
113 sisFreeTexImage( sisContextPtr smesa, sisTexObjPtr t, int level )
114 {
115 if (t->image[level].Data == NULL)
116 return;
117
118 switch (t->image[level].memType)
119 {
120 case VIDEO_TYPE:
121 sisFreeFB( smesa, t->image[level].handle );
122 break;
123 case AGP_TYPE:
124 sisFreeAGP( smesa, t->image[level].handle );
125 break;
126 }
127 t->image[level].Data = NULL;
128 t->image[level].handle = NULL;
129 /* If there are no textures loaded any more, reset the hw format so the
130 * object can be reused for new formats
131 */
132 t->numImages--;
133 if (t->numImages == 0) {
134 t->format = 0;
135 t->hwformat = 0;
136 }
137 }
138
139 static void
140 sisTexEnv( GLcontext *ctx, GLenum target, GLenum pname, const GLfloat *param )
141 {
142 sisContextPtr smesa = SIS_CONTEXT(ctx);
143
144 smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURE_ENV;
145 }
146
147 static void
148 sisTexParameter( GLcontext *ctx, GLenum target,
149 struct gl_texture_object *texObj, GLenum pname,
150 const GLfloat *params )
151 {
152 sisContextPtr smesa = SIS_CONTEXT(ctx);
153
154 smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURING;
155 }
156
157 static void
158 sisBindTexture( GLcontext *ctx, GLenum target,
159 struct gl_texture_object *texObj )
160 {
161 sisContextPtr smesa = SIS_CONTEXT(ctx);
162 sisTexObjPtr t;
163
164 if ( target == GL_TEXTURE_2D || target == GL_TEXTURE_1D ) {
165 if ( texObj->DriverData == NULL ) {
166 sisAllocTexObj( texObj );
167 }
168 }
169
170 t = texObj->DriverData;
171 if (!t)
172 return;
173
174 if (smesa->PrevTexFormat[ctx->Texture.CurrentUnit] != t->format) {
175 smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURE_ENV;
176 smesa->PrevTexFormat[ctx->Texture.CurrentUnit] = t->format;
177 }
178 smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURING;
179 }
180
181 static void
182 sisDeleteTexture( GLcontext * ctx, struct gl_texture_object *texObj )
183 {
184 sisContextPtr smesa = SIS_CONTEXT(ctx);
185 sisTexObjPtr t;
186 int i;
187
188 smesa->clearTexCache = GL_TRUE;
189
190 t = texObj->DriverData;
191 if (t == NULL) {
192 /*
193 * this shows the texture is default object and never be a
194 * argument of sisTexImage*
195 */
196 return;
197 }
198 for (i = 0; i < MAX_TEXTURE_LEVELS; i++) {
199 sisFreeTexImage( smesa, t, i );
200 }
201
202 FREE(t);
203 texObj->DriverData = NULL;
204 /* Free mipmap images and the texture object itself */
205 _mesa_delete_texture_object(ctx, texObj);
206 }
207
208 static GLboolean sisIsTextureResident( GLcontext * ctx,
209 struct gl_texture_object *texObj )
210 {
211 return (texObj->DriverData != NULL);
212 }
213
214 static const struct gl_texture_format *
215 sisChooseTextureFormat( 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 sisTexImage1D( 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 sisChooseTextureFormat */
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 sisTexSubImage1D( 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 const char *src;
327 GLubyte *dst;
328
329 if ( texObj->DriverData == NULL )
330 sisAllocTexObj( texObj );
331 t = texObj->DriverData;
332
333 _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
334 format, type, pixels, packing, texObj,
335 texImage);
336
337 /* Allocate offscreen space for the texture */
338 sisFreeTexImage(smesa, t, level);
339 sisAllocTexImage(smesa, t, level, texImage);
340
341 /* Upload the texture */
342 texelBytes = texImage->TexFormat->TexelBytes;
343
344 copySize = width * texelBytes;
345 src = (char *)texImage->Data + xoffset * texelBytes;
346 dst = t->image[level].Data + xoffset * texelBytes;
347
348 memcpy( dst, src, copySize );
349
350 smesa->clearTexCache = GL_TRUE;
351
352 if (smesa->PrevTexFormat[ctx->Texture.CurrentUnit] != t->format)
353 {
354 smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURE_ENV;
355 smesa->PrevTexFormat[ctx->Texture.CurrentUnit] = t->format;
356 }
357 smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURING;
358 }
359
360 static void sisTexImage2D( GLcontext *ctx, GLenum target, GLint level,
361 GLint internalFormat,
362 GLint width, GLint height, GLint border,
363 GLenum format, GLenum type, const GLvoid *pixels,
364 const struct gl_pixelstore_attrib *packing,
365 struct gl_texture_object *texObj,
366 struct gl_texture_image *texImage )
367 {
368 sisContextPtr smesa = SIS_CONTEXT(ctx);
369 sisTexObjPtr t;
370
371 if ( texObj->DriverData == NULL )
372 sisAllocTexObj( texObj );
373 t = texObj->DriverData;
374
375 /* Note, this will call sisChooseTextureFormat */
376 _mesa_store_teximage2d(ctx, target, level, internalFormat,
377 width, height, border, format, type, pixels,
378 &ctx->Unpack, texObj, texImage);
379
380 /* Allocate offscreen space for the texture */
381 sisFreeTexImage(smesa, t, level);
382 sisAllocTexImage(smesa, t, level, texImage);
383
384 /* Upload the texture */
385 memcpy(t->image[level].Data, texImage->Data, t->image[level].size);
386
387 if (smesa->PrevTexFormat[ctx->Texture.CurrentUnit] != t->format)
388 {
389 smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURE_ENV;
390 smesa->PrevTexFormat[ctx->Texture.CurrentUnit] = t->format;
391 }
392 smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURING;
393 }
394
395 static void sisTexSubImage2D( GLcontext *ctx,
396 GLenum target,
397 GLint level,
398 GLint xoffset, GLint yoffset,
399 GLsizei width, GLsizei height,
400 GLenum format, GLenum type,
401 const GLvoid *pixels,
402 const struct gl_pixelstore_attrib *packing,
403 struct gl_texture_object *texObj,
404 struct gl_texture_image *texImage )
405 {
406 sisContextPtr smesa = SIS_CONTEXT(ctx);
407 sisTexObjPtr t;
408 GLuint copySize;
409 GLint texelBytes;
410 const char *src;
411 GLubyte *dst;
412 int j;
413 GLuint soffset;
414
415 if ( texObj->DriverData == NULL )
416 sisAllocTexObj( texObj );
417 t = texObj->DriverData;
418
419 _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
420 height, format, type, pixels, packing, texObj,
421 texImage);
422
423 /* Allocate offscreen space for the texture */
424 sisFreeTexImage(smesa, t, level);
425 sisAllocTexImage(smesa, t, level, texImage);
426
427 /* Upload the texture */
428 texelBytes = texImage->TexFormat->TexelBytes;
429
430 copySize = width * texelBytes;
431 src = (char *)texImage->Data + (xoffset + yoffset * texImage->Width) *
432 texelBytes;
433 dst = t->image[level].Data + (xoffset + yoffset * texImage->Width) *
434 texelBytes;
435 soffset = texImage->Width * texelBytes;
436
437 for (j = yoffset; j < yoffset + height; j++) {
438 memcpy( dst, src, copySize );
439 src += soffset;
440 dst += soffset;
441 }
442
443 smesa->clearTexCache = GL_TRUE;
444
445 if (smesa->PrevTexFormat[ctx->Texture.CurrentUnit] != t->format)
446 {
447 smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURE_ENV;
448 smesa->PrevTexFormat[ctx->Texture.CurrentUnit] = t->format;
449 }
450 smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURING;
451 }
452
453
454 /**
455 * Allocate a new texture object.
456 * Called via ctx->Driver.NewTextureObject.
457 * Note: this function will be called during context creation to
458 * allocate the default texture objects.
459 * Note: we could use containment here to 'derive' the driver-specific
460 * texture object from the core mesa gl_texture_object. Not done at this time.
461 */
462 static struct gl_texture_object *
463 sisNewTextureObject( GLcontext *ctx, GLuint name, GLenum target )
464 {
465 struct gl_texture_object *obj;
466 obj = _mesa_new_texture_object(ctx, name, target);
467 return obj;
468 }
469
470
471 void sisInitTextureFuncs( struct dd_function_table *functions )
472 {
473 functions->TexEnv = sisTexEnv;
474 functions->ChooseTextureFormat = sisChooseTextureFormat;
475 functions->TexImage1D = sisTexImage1D;
476 functions->TexSubImage1D = sisTexSubImage1D;
477 functions->TexImage2D = sisTexImage2D;
478 functions->TexSubImage2D = sisTexSubImage2D;
479 functions->TexParameter = sisTexParameter;
480 functions->BindTexture = sisBindTexture;
481 functions->NewTextureObject = sisNewTextureObject;
482 functions->DeleteTexture = sisDeleteTexture;
483 functions->IsTextureResident = sisIsTextureResident;
484 }