Merge remote branch 'origin/gallium-0.2' into gallium-0.2
[mesa.git] / src / mesa / drivers / dri / s3v / s3v_tex.c
1 /*
2 * Author: Max Lingua <sunmax@libero.it>
3 */
4
5 #include <stdlib.h>
6 #include <stdio.h>
7
8 #include "main/glheader.h"
9 #include "main/mtypes.h"
10 #include "main/simple_list.h"
11 #include "main/enums.h"
12 #include "main/mm.h"
13 #include "main/texstore.h"
14 #include "main/texformat.h"
15 #include "main/teximage.h"
16 #include "swrast/swrast.h"
17
18 #include "s3v_context.h"
19 #include "s3v_tex.h"
20
21
22 extern void s3vSwapOutTexObj(s3vContextPtr vmesa, s3vTextureObjectPtr t);
23 extern void s3vDestroyTexObj(s3vContextPtr vmesa, s3vTextureObjectPtr t);
24
25 /*
26 static GLuint s3vComputeLodBias(GLfloat bias)
27 {
28 #if TEX_DEBUG_ON
29 DEBUG_TEX(("*** s3vComputeLodBias ***\n"));
30 #endif
31 return bias;
32 }
33 */
34
35 static void s3vSetTexWrapping(s3vContextPtr vmesa,
36 s3vTextureObjectPtr t,
37 GLenum wraps, GLenum wrapt)
38 {
39 GLuint t0 = t->TextureCMD;
40 GLuint cmd = vmesa->CMD;
41 #if TEX_DEBUG_ON
42 static unsigned int times=0;
43 DEBUG_TEX(("*** s3vSetTexWrapping: #%i ***\n", ++times));
44 #endif
45
46
47 t0 &= ~TEX_WRAP_MASK;
48 cmd &= ~TEX_WRAP_MASK;
49
50 if ((wraps != GL_CLAMP) || (wrapt != GL_CLAMP)) {
51 DEBUG(("TEX_WRAP_ON\n"));
52 t0 |= TEX_WRAP_ON;
53 cmd |= TEX_WRAP_ON;
54 }
55
56 cmd |= TEX_WRAP_ON; /* FIXME: broken if off */
57 t->TextureCMD = t0;
58 vmesa->CMD = cmd;
59 }
60
61
62 static void s3vSetTexFilter(s3vContextPtr vmesa,
63 s3vTextureObjectPtr t,
64 GLenum minf, GLenum magf)
65 {
66 GLuint t0 = t->TextureCMD;
67 GLuint cmd = vmesa->CMD;
68 #if TEX_DEBUG_ON
69 static unsigned int times=0;
70 DEBUG_TEX(("*** s3vSetTexFilter: #%i ***\n", ++times));
71 #endif
72
73 t0 &= ~TEX_FILTER_MASK;
74 cmd &= ~TEX_FILTER_MASK;
75
76 switch (minf) {
77 case GL_NEAREST:
78 DEBUG(("GL_NEAREST\n"));
79 t0 |= NEAREST;
80 cmd |= NEAREST;
81 break;
82 case GL_LINEAR:
83 DEBUG(("GL_LINEAR\n"));
84 t0 |= LINEAR;
85 cmd |= LINEAR;
86 break;
87 case GL_NEAREST_MIPMAP_NEAREST:
88 DEBUG(("GL_MIPMAP_NEAREST\n"));
89 t0 |= MIP_NEAREST;
90 cmd |= MIP_NEAREST;
91 break;
92 case GL_LINEAR_MIPMAP_NEAREST:
93 DEBUG(("GL_LINEAR_MIPMAP_NEAREST\n"));
94 t0 |= LINEAR_MIP_NEAREST;
95 cmd |= LINEAR_MIP_NEAREST;
96 break;
97 case GL_NEAREST_MIPMAP_LINEAR:
98 DEBUG(("GL_NEAREST_MIPMAP_LINEAR\n"));
99 t0 |= MIP_LINEAR;
100 cmd |= MIP_LINEAR;
101 break;
102 case GL_LINEAR_MIPMAP_LINEAR:
103 DEBUG(("GL_LINEAR_MIPMAP_LINEAR\n"));
104 t0 |= LINEAR_MIP_LINEAR;
105 cmd |= LINEAR_MIP_LINEAR;
106 break;
107 default:
108 break;
109 }
110 /* FIXME: bilinear? */
111
112 #if 0
113 switch (magf) {
114 case GL_NEAREST:
115 break;
116 case GL_LINEAR:
117 break;
118 default:
119 break;
120 }
121 #endif
122
123 t->TextureCMD = t0;
124
125 DEBUG(("CMD was = 0x%x\n", vmesa->CMD));
126 DEBUG(("CMD is = 0x%x\n", cmd));
127
128 vmesa->CMD = cmd;
129 /* CMDCHANGE(); */
130 }
131
132
133 static void s3vSetTexBorderColor(s3vContextPtr vmesa,
134 s3vTextureObjectPtr t,
135 GLubyte color[4])
136 {
137 #if TEX_DEBUG_ON
138 static unsigned int times=0;
139 DEBUG_TEX(("*** s3vSetTexBorderColor: #%i ***\n", ++times));
140 #endif
141
142 /*FIXME: it should depend on tex col format */
143 /* switch(t0 ... t->TextureColorMode) */
144
145 /* case TEX_COL_ARGB1555: */
146 t->TextureBorderColor =
147 S3VIRGEPACKCOLOR555(color[0], color[1], color[2], color[3]);
148
149 DEBUG(("TextureBorderColor = 0x%x\n", t->TextureBorderColor));
150
151 vmesa->TextureBorderColor = t->TextureBorderColor;
152 }
153
154 static void s3vTexParameter( GLcontext *ctx, GLenum target,
155 struct gl_texture_object *tObj,
156 GLenum pname, const GLfloat *params )
157 {
158 s3vContextPtr vmesa = S3V_CONTEXT(ctx);
159 s3vTextureObjectPtr t = (s3vTextureObjectPtr) tObj->DriverData;
160 #if TEX_DEBUG_ON
161 static unsigned int times=0;
162 DEBUG_TEX(("*** s3vTexParameter: #%i ***\n", ++times));
163 #endif
164
165 if (!t) return;
166
167 /* Can't do the update now as we don't know whether to flush
168 * vertices or not. Setting vmesa->new_state means that
169 * s3vUpdateTextureState() will be called before any triangles are
170 * rendered. If a statechange has occurred, it will be detected at
171 * that point, and buffered vertices flushed.
172 */
173 switch (pname) {
174 case GL_TEXTURE_MIN_FILTER:
175 case GL_TEXTURE_MAG_FILTER:
176 s3vSetTexFilter( vmesa, t, tObj->MinFilter, tObj->MagFilter );
177 break;
178
179 case GL_TEXTURE_WRAP_S:
180 case GL_TEXTURE_WRAP_T:
181 s3vSetTexWrapping( vmesa, t, tObj->WrapS, tObj->WrapT );
182 break;
183
184 case GL_TEXTURE_BORDER_COLOR:
185 s3vSetTexBorderColor( vmesa, t, tObj->_BorderChan );
186 break;
187
188 case GL_TEXTURE_BASE_LEVEL:
189 case GL_TEXTURE_MAX_LEVEL:
190 case GL_TEXTURE_MIN_LOD:
191 case GL_TEXTURE_MAX_LOD:
192 /* This isn't the most efficient solution but there doesn't appear to
193 * be a nice alternative for Virge. Since there's no LOD clamping,
194 * we just have to rely on loading the right subset of mipmap levels
195 * to simulate a clamped LOD.
196 */
197 s3vSwapOutTexObj( vmesa, t );
198 break;
199
200 default:
201 return;
202 }
203
204 if (t == vmesa->CurrentTexObj[0])
205 vmesa->dirty |= S3V_UPLOAD_TEX0;
206
207 #if 0
208 if (t == vmesa->CurrentTexObj[1]) {
209 vmesa->dirty |= S3V_UPLOAD_TEX1;
210 }
211 #endif
212 }
213
214
215 static void s3vTexEnv( GLcontext *ctx, GLenum target,
216 GLenum pname, const GLfloat *param )
217 {
218 s3vContextPtr vmesa = S3V_CONTEXT( ctx );
219 GLuint unit = ctx->Texture.CurrentUnit;
220 #if TEX_DEBUG_ON
221 static unsigned int times=0;
222 DEBUG_TEX(("*** s3vTexEnv: #%i ***\n", ++times));
223 #endif
224
225 /* Only one env color. Need a fallback if env colors are different
226 * and texture setup references env color in both units.
227 */
228 switch (pname) {
229 case GL_TEXTURE_ENV_COLOR: {
230 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
231 GLfloat *fc = texUnit->EnvColor;
232 GLuint r, g, b, a, col;
233 CLAMPED_FLOAT_TO_UBYTE(r, fc[0]);
234 CLAMPED_FLOAT_TO_UBYTE(g, fc[1]);
235 CLAMPED_FLOAT_TO_UBYTE(b, fc[2]);
236 CLAMPED_FLOAT_TO_UBYTE(a, fc[3]);
237
238 col = ((a << 24) |
239 (r << 16) |
240 (g << 8) |
241 (b << 0));
242
243 break;
244 }
245 case GL_TEXTURE_ENV_MODE:
246 vmesa->TexEnvImageFmt[unit] = 0; /* force recalc of env state */
247 break;
248 case GL_TEXTURE_LOD_BIAS_EXT: {
249 /*
250 struct gl_texture_object *tObj =
251 ctx->Texture.Unit[unit]._Current;
252
253 s3vTextureObjectPtr t = (s3vTextureObjectPtr) tObj->DriverData;
254 */
255 break;
256 }
257 default:
258 break;
259 }
260 }
261
262 static void s3vTexImage1D( GLcontext *ctx, GLenum target, GLint level,
263 GLint internalFormat,
264 GLint width, GLint border,
265 GLenum format, GLenum type,
266 const GLvoid *pixels,
267 const struct gl_pixelstore_attrib *pack,
268 struct gl_texture_object *texObj,
269 struct gl_texture_image *texImage )
270 {
271 s3vContextPtr vmesa = S3V_CONTEXT( ctx );
272 s3vTextureObjectPtr t = (s3vTextureObjectPtr) texObj->DriverData;
273 #if TEX_DEBUG_ON
274 static unsigned int times=0;
275 DEBUG_TEX(("*** s3vTexImage1D: #%i ***\n", ++times));
276 #endif
277
278 #if 1
279 if (t) {
280 #if _TEXFLUSH
281 DMAFLUSH();
282 #endif
283 s3vSwapOutTexObj( vmesa, t );
284 /*
285 s3vDestroyTexObj( vmesa, t );
286 texObj->DriverData = 0;
287 */
288 }
289 #endif
290 _mesa_store_teximage1d( ctx, target, level, internalFormat,
291 width, border, format, type,
292 pixels, pack, texObj, texImage );
293 }
294
295 static void s3vTexSubImage1D( GLcontext *ctx,
296 GLenum target,
297 GLint level,
298 GLint xoffset,
299 GLsizei width,
300 GLenum format, GLenum type,
301 const GLvoid *pixels,
302 const struct gl_pixelstore_attrib *pack,
303 struct gl_texture_object *texObj,
304 struct gl_texture_image *texImage )
305 {
306 s3vContextPtr vmesa = S3V_CONTEXT( ctx );
307 s3vTextureObjectPtr t = (s3vTextureObjectPtr) texObj->DriverData;
308 #if TEX_DEBUG_ON
309 static unsigned int times=0;
310 DEBUG_TEX(("*** s3vTexSubImage1D: #%i ***\n", ++times));
311 #endif
312
313 #if 1
314 if (t) {
315 #if _TEXFLUSH
316 DMAFLUSH();
317 #endif
318 s3vSwapOutTexObj( vmesa, t );
319 /*
320 s3vDestroyTexObj( vmesa, t );
321 texObj->DriverData = 0;
322 */
323 }
324 #endif
325 _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
326 format, type, pixels, pack, texObj,
327 texImage);
328 }
329
330 static void s3vTexImage2D( GLcontext *ctx, GLenum target, GLint level,
331 GLint internalFormat,
332 GLint width, GLint height, GLint border,
333 GLenum format, GLenum type, const GLvoid *pixels,
334 const struct gl_pixelstore_attrib *packing,
335 struct gl_texture_object *texObj,
336 struct gl_texture_image *texImage )
337 {
338 s3vContextPtr vmesa = S3V_CONTEXT( ctx );
339 s3vTextureObjectPtr t = (s3vTextureObjectPtr) texObj->DriverData;
340
341 #if TEX_DEBUG_ON
342 static unsigned int times=0;
343 DEBUG_TEX(("*** s3vTexImage2D: #%i ***\n", ++times));
344 #endif
345
346 #if 1
347 if (t) {
348 #if _TEXFLUSH
349 DMAFLUSH();
350 #endif
351 s3vSwapOutTexObj( vmesa, t );
352 /*
353 s3vDestroyTexObj( vmesa, t );
354 texObj->DriverData = 0;
355 */
356 }
357 #endif
358 _mesa_store_teximage2d( ctx, target, level, internalFormat,
359 width, height, border, format, type,
360 pixels, packing, texObj, texImage );
361 }
362
363 static void s3vTexSubImage2D( GLcontext *ctx,
364 GLenum target,
365 GLint level,
366 GLint xoffset, GLint yoffset,
367 GLsizei width, GLsizei height,
368 GLenum format, GLenum type,
369 const GLvoid *pixels,
370 const struct gl_pixelstore_attrib *packing,
371 struct gl_texture_object *texObj,
372 struct gl_texture_image *texImage )
373 {
374 s3vContextPtr vmesa = S3V_CONTEXT( ctx );
375 s3vTextureObjectPtr t = (s3vTextureObjectPtr) texObj->DriverData;
376 #if TEX_DEBUG_ON
377 static unsigned int times=0;
378 DEBUG_TEX(("*** s3vTexSubImage2D: #%i ***\n", ++times));
379 #endif
380
381 #if 1
382 if (t) {
383 #if _TEXFLUSH
384 DMAFLUSH();
385 #endif
386 s3vSwapOutTexObj( vmesa, t );
387 /*
388 s3vDestroyTexObj( vmesa, t );
389 texObj->DriverData = 0;
390 */
391 }
392 #endif
393 _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
394 height, format, type, pixels, packing, texObj,
395 texImage);
396 }
397
398
399 static void s3vBindTexture( GLcontext *ctx, GLenum target,
400 struct gl_texture_object *tObj )
401 {
402 s3vContextPtr vmesa = S3V_CONTEXT( ctx );
403 s3vTextureObjectPtr t = (s3vTextureObjectPtr) tObj->DriverData;
404 GLuint cmd = vmesa->CMD;
405 #if TEX_DEBUG_ON
406 static unsigned int times=0;
407 DEBUG_TEX(("*** s3vBindTexture: #%i ***\n", ++times));
408 #endif
409
410 if (!t) {
411 /*
412 GLfloat bias = ctx->Texture.Unit[ctx->Texture.CurrentUnit].LodBias;
413 */
414 t = CALLOC_STRUCT(s3v_texture_object_t);
415
416 /* Initialize non-image-dependent parts of the state:
417 */
418 t->globj = tObj;
419 #if 0
420 if (target == GL_TEXTURE_2D) {
421 } else
422 if (target == GL_TEXTURE_1D) {
423 }
424
425 #if X_BYTE_ORDER == X_LITTLE_ENDIAN
426 t->TextureFormat = (TF_LittleEndian |
427 #else
428 t->TextureFormat = (TF_BigEndian |
429 #endif
430 #endif
431 t->dirty_images = ~0;
432
433 tObj->DriverData = t;
434 make_empty_list( t );
435 #if 0
436 s3vSetTexWrapping( vmesa, t, tObj->WrapS, tObj->WrapT );
437 s3vSetTexFilter( vmesa, t, tObj->MinFilter, tObj->MagFilter );
438 s3vSetTexBorderColor( vmesa, t, tObj->BorderColor );
439 #endif
440 }
441
442 cmd = vmesa->CMD & ~MIP_MASK;
443 vmesa->dirty |= S3V_UPLOAD_TEX0;
444 vmesa->TexOffset = t->TextureBaseAddr[tObj->BaseLevel];
445 vmesa->TexStride = t->Pitch;
446 cmd |= MIPMAP_LEVEL(t->WidthLog2);
447 vmesa->CMD = cmd;
448 vmesa->restore_primitive = -1;
449 #if 0
450 printf("t->TextureBaseAddr[0] = 0x%x\n", t->TextureBaseAddr[0]);
451 printf("t->TextureBaseAddr[1] = 0x%x\n", t->TextureBaseAddr[1]);
452 printf("t->TextureBaseAddr[2] = 0x%x\n", t->TextureBaseAddr[2]);
453 #endif
454 }
455
456
457 static void s3vDeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj )
458 {
459 s3vTextureObjectPtr t = (s3vTextureObjectPtr)tObj->DriverData;
460 #if TEX_DEBUG_ON
461 static unsigned int times=0;
462 DEBUG_TEX(("*** s3vDeleteTexture: #%i ***\n", ++times));
463 #endif
464
465 if (t) {
466 s3vContextPtr vmesa = S3V_CONTEXT( ctx );
467
468 #if _TEXFLUSH
469 if (vmesa) {
470 DMAFLUSH();
471 }
472 #endif
473
474 s3vDestroyTexObj( vmesa, t );
475 tObj->DriverData = 0;
476
477 }
478 }
479
480 static GLboolean s3vIsTextureResident( GLcontext *ctx,
481 struct gl_texture_object *tObj )
482 {
483 s3vTextureObjectPtr t = (s3vTextureObjectPtr)tObj->DriverData;
484 #if TEX_DEBUG_ON
485 static unsigned int times=0;
486 DEBUG_TEX(("*** s3vIsTextureResident: #%i ***\n", ++times));
487 #endif
488
489 return (t && t->MemBlock);
490 }
491
492 static void s3vInitTextureObjects( GLcontext *ctx )
493 {
494 /* s3vContextPtr vmesa = S3V_CONTEXT(ctx); */
495 struct gl_texture_object *texObj;
496 GLuint tmp = ctx->Texture.CurrentUnit;
497 #if TEX_DEBUG_ON
498 static unsigned int times=0;
499 DEBUG_TEX(("*** s3vInitTextureObjects: #%i ***\n", ++times));
500 #endif
501
502 #if 1
503 ctx->Texture.CurrentUnit = 0;
504
505 texObj = ctx->Texture.Unit[0].Current1D;
506 s3vBindTexture( ctx, GL_TEXTURE_1D, texObj );
507
508 texObj = ctx->Texture.Unit[0].Current2D;
509 s3vBindTexture( ctx, GL_TEXTURE_2D, texObj );
510 #endif
511
512 #if 0
513 ctx->Texture.CurrentUnit = 1;
514
515 texObj = ctx->Texture.Unit[1].Current1D;
516 s3vBindTexture( ctx, GL_TEXTURE_1D, texObj );
517
518 texObj = ctx->Texture.Unit[1].Current2D;
519 s3vBindTexture( ctx, GL_TEXTURE_2D, texObj );
520 #endif
521
522 ctx->Texture.CurrentUnit = tmp;
523 }
524
525
526 void s3vInitTextureFuncs( GLcontext *ctx )
527 {
528 #if TEX_DEBUG_ON
529 static unsigned int times=0;
530 DEBUG_TEX(("*** s3vInitTextureFuncs: #%i ***\n", ++times));
531 #endif
532
533 ctx->Driver.TexEnv = s3vTexEnv;
534 ctx->Driver.ChooseTextureFormat = _mesa_choose_tex_format;
535 ctx->Driver.TexImage1D = _mesa_store_teximage1d;
536 ctx->Driver.TexImage2D = s3vTexImage2D;
537 ctx->Driver.TexImage3D = _mesa_store_teximage3d;
538 ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d;
539 ctx->Driver.TexSubImage2D = s3vTexSubImage2D;
540 ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
541 ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d;
542 ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d;
543 ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d;
544 ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d;
545 ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d;
546 ctx->Driver.BindTexture = s3vBindTexture;
547 ctx->Driver.DeleteTexture = s3vDeleteTexture;
548 ctx->Driver.TexParameter = s3vTexParameter;
549 ctx->Driver.UpdateTexturePalette = 0;
550 ctx->Driver.IsTextureResident = s3vIsTextureResident;
551 ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage;
552
553 s3vInitTextureObjects( ctx );
554 }