075d6d1357b0ad3becab10350a73093aa42d0271
[mesa.git] / src / mesa / drivers / dri / gamma / gamma_tex.c
1 /* $XFree86: xc/lib/GL/mesa/src/drv/gamma/gamma_tex.c,v 1.4 2002/11/05 17:46:07 tsi Exp $ */
2
3 #include <stdlib.h>
4 #include <stdio.h>
5
6 #include "glheader.h"
7 #include "mtypes.h"
8 #include "imports.h"
9 #include "simple_list.h"
10 #include "enums.h"
11 #include "texstore.h"
12 #include "teximage.h"
13 #include "texformat.h"
14 #include "texobj.h"
15 #include "swrast/swrast.h"
16
17 #include "mm.h"
18 #include "gamma_context.h"
19 #include "colormac.h"
20
21
22 /*
23 * Compute the 'S2.4' lod bias factor from the floating point OpenGL bias.
24 */
25 #if 0
26 static GLuint gammaComputeLodBias(GLfloat bias)
27 {
28 return bias;
29 }
30 #endif
31
32 static void gammaSetTexWrapping(gammaTextureObjectPtr t,
33 GLenum wraps, GLenum wrapt)
34 {
35 uint32_t t1 = t->TextureAddressMode;
36 uint32_t t2 = t->TextureReadMode;
37
38 t1 &= ~(TAM_SWrap_Mask | TAM_TWrap_Mask);
39 t2 &= ~(TRM_UWrap_Mask | TRM_VWrap_Mask);
40
41 if (wraps != GL_CLAMP) {
42 t1 |= TAM_SWrap_Repeat;
43 t2 |= TRM_UWrap_Repeat;
44 }
45
46 if (wrapt != GL_CLAMP) {
47 t1 |= TAM_TWrap_Repeat;
48 t2 |= TRM_VWrap_Repeat;
49 }
50
51 t->TextureAddressMode = t1;
52 t->TextureReadMode = t2;
53 }
54
55
56 static void gammaSetTexFilter(gammaContextPtr gmesa,
57 gammaTextureObjectPtr t,
58 GLenum minf, GLenum magf,
59 GLfloat bias)
60 {
61 uint32_t t1 = t->TextureAddressMode;
62 uint32_t t2 = t->TextureReadMode;
63
64 t2 &= ~(TRM_Mag_Mask | TRM_Min_Mask);
65
66 switch (minf) {
67 case GL_NEAREST:
68 t1 &= ~TAM_LODEnable;
69 t2 &= ~TRM_MipMapEnable;
70 t2 |= TRM_Min_Nearest;
71 break;
72 case GL_LINEAR:
73 t1 &= ~TAM_LODEnable;
74 t2 &= ~TRM_MipMapEnable;
75 t2 |= TRM_Min_Linear;
76 break;
77 case GL_NEAREST_MIPMAP_NEAREST:
78 t2 |= TRM_Min_NearestMMNearest;
79 break;
80 case GL_LINEAR_MIPMAP_NEAREST:
81 t2 |= TRM_Min_LinearMMNearest;
82 break;
83 case GL_NEAREST_MIPMAP_LINEAR:
84 t2 |= TRM_Min_NearestMMLinear;
85 break;
86 case GL_LINEAR_MIPMAP_LINEAR:
87 t2 |= TRM_Min_LinearMMLinear;
88 break;
89 default:
90 break;
91 }
92
93 switch (magf) {
94 case GL_NEAREST:
95 t2 |= TRM_Mag_Nearest;
96 break;
97 case GL_LINEAR:
98 t2 |= TRM_Mag_Linear;
99 break;
100 default:
101 break;
102 }
103
104 t->TextureAddressMode = t1;
105 t->TextureReadMode = t2;
106 }
107
108
109 static void gammaSetTexBorderColor(gammaContextPtr gmesa,
110 gammaTextureObjectPtr t,
111 GLubyte color[4])
112 {
113 t->TextureBorderColor = PACK_COLOR_8888(color[0], color[1], color[2], color[3]);
114 }
115
116
117 static void gammaTexParameter( GLcontext *ctx, GLenum target,
118 struct gl_texture_object *tObj,
119 GLenum pname, const GLfloat *params )
120 {
121 gammaContextPtr gmesa = GAMMA_CONTEXT(ctx);
122 gammaTextureObjectPtr t = (gammaTextureObjectPtr) tObj->DriverData;
123 if (!t)
124 return;
125
126 /* Can't do the update now as we don't know whether to flush
127 * vertices or not. Setting gmesa->new_state means that
128 * gammaUpdateTextureState() will be called before any triangles are
129 * rendered. If a statechange has occurred, it will be detected at
130 * that point, and buffered vertices flushed.
131 */
132 switch (pname) {
133 case GL_TEXTURE_MIN_FILTER:
134 case GL_TEXTURE_MAG_FILTER:
135 {
136 GLfloat bias = ctx->Texture.Unit[ctx->Texture.CurrentUnit].LodBias;
137 gammaSetTexFilter( gmesa, t, tObj->MinFilter, tObj->MagFilter, bias );
138 }
139 break;
140
141 case GL_TEXTURE_WRAP_S:
142 case GL_TEXTURE_WRAP_T:
143 gammaSetTexWrapping( t, tObj->WrapS, tObj->WrapT );
144 break;
145
146 case GL_TEXTURE_BORDER_COLOR:
147 gammaSetTexBorderColor( gmesa, t, tObj->_BorderChan );
148 break;
149
150 case GL_TEXTURE_BASE_LEVEL:
151 case GL_TEXTURE_MAX_LEVEL:
152 case GL_TEXTURE_MIN_LOD:
153 case GL_TEXTURE_MAX_LOD:
154 /* This isn't the most efficient solution but there doesn't appear to
155 * be a nice alternative for Radeon. Since there's no LOD clamping,
156 * we just have to rely on loading the right subset of mipmap levels
157 * to simulate a clamped LOD.
158 */
159 gammaSwapOutTexObj( gmesa, t );
160 break;
161
162 default:
163 return;
164 }
165
166 if (t == gmesa->CurrentTexObj[0])
167 gmesa->dirty |= GAMMA_UPLOAD_TEX0;
168
169 #if 0
170 if (t == gmesa->CurrentTexObj[1]) {
171 gmesa->dirty |= GAMMA_UPLOAD_TEX1;
172 }
173 #endif
174 }
175
176
177 static void gammaTexEnv( GLcontext *ctx, GLenum target,
178 GLenum pname, const GLfloat *param )
179 {
180 gammaContextPtr gmesa = GAMMA_CONTEXT( ctx );
181 GLuint unit = ctx->Texture.CurrentUnit;
182
183 /* Only one env color. Need a fallback if env colors are different
184 * and texture setup references env color in both units.
185 */
186 switch (pname) {
187 case GL_TEXTURE_ENV_COLOR: {
188 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
189 GLfloat *fc = texUnit->EnvColor;
190 GLuint r, g, b, a, col;
191 CLAMPED_FLOAT_TO_UBYTE(r, fc[0]);
192 CLAMPED_FLOAT_TO_UBYTE(g, fc[1]);
193 CLAMPED_FLOAT_TO_UBYTE(b, fc[2]);
194 CLAMPED_FLOAT_TO_UBYTE(a, fc[3]);
195
196 col = ((a << 24) |
197 (r << 16) |
198 (g << 8) |
199 (b << 0));
200
201 break;
202 }
203 case GL_TEXTURE_ENV_MODE:
204 gmesa->TexEnvImageFmt[unit] = 0; /* force recalc of env state */
205 break;
206
207 case GL_TEXTURE_LOD_BIAS_EXT:
208 #if 0 /* ?!?!?! */
209 {
210 struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current;
211 gammaTextureObjectPtr t = (gammaTextureObjectPtr) tObj->DriverData;
212 (void) t;
213 /* XXX Looks like there's something missing here */
214 }
215 #endif
216 break;
217
218 default:
219 break;
220 }
221 }
222
223 #if 0
224 static void gammaTexImage1D( GLcontext *ctx, GLenum target, GLint level,
225 GLint internalFormat,
226 GLint width, GLint border,
227 GLenum format, GLenum type,
228 const GLvoid *pixels,
229 const struct gl_pixelstore_attrib *pack,
230 struct gl_texture_object *texObj,
231 struct gl_texture_image *texImage )
232 {
233 gammaTextureObjectPtr t = (gammaTextureObjectPtr) texObj->DriverData;
234 if (t) {
235 gammaSwapOutTexObj( GAMMA_CONTEXT(ctx), t );
236 }
237 _mesa_store_teximage1d( ctx, target, level, internalFormat,
238 width, border, format, type,
239 pixels, pack, texObj, texImage );
240 }
241 #endif
242
243 #if 0
244 static void gammaTexSubImage1D( GLcontext *ctx,
245 GLenum target,
246 GLint level,
247 GLint xoffset,
248 GLsizei width,
249 GLenum format, GLenum type,
250 const GLvoid *pixels,
251 const struct gl_pixelstore_attrib *pack,
252 struct gl_texture_object *texObj,
253 struct gl_texture_image *texImage )
254 {
255 gammaTextureObjectPtr t = (gammaTextureObjectPtr) texObj->DriverData;
256 if (t) {
257 gammaSwapOutTexObj( GAMMA_CONTEXT(ctx), t );
258 }
259 _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
260 format, type, pixels, pack, texObj,
261 texImage);
262 }
263 #endif
264
265 static void gammaTexImage2D( GLcontext *ctx, GLenum target, GLint level,
266 GLint internalFormat,
267 GLint width, GLint height, GLint border,
268 GLenum format, GLenum type, const GLvoid *pixels,
269 const struct gl_pixelstore_attrib *packing,
270 struct gl_texture_object *texObj,
271 struct gl_texture_image *texImage )
272 {
273 gammaTextureObjectPtr t = (gammaTextureObjectPtr) texObj->DriverData;
274 if (t) {
275 gammaSwapOutTexObj( GAMMA_CONTEXT(ctx), t );
276 }
277 _mesa_store_teximage2d( ctx, target, level, internalFormat,
278 width, height, border, format, type,
279 pixels, packing, texObj, texImage );
280 }
281
282 static void gammaTexSubImage2D( GLcontext *ctx,
283 GLenum target,
284 GLint level,
285 GLint xoffset, GLint yoffset,
286 GLsizei width, GLsizei height,
287 GLenum format, GLenum type,
288 const GLvoid *pixels,
289 const struct gl_pixelstore_attrib *packing,
290 struct gl_texture_object *texObj,
291 struct gl_texture_image *texImage )
292 {
293 gammaTextureObjectPtr t = (gammaTextureObjectPtr) texObj->DriverData;
294 if (t) {
295 gammaSwapOutTexObj( GAMMA_CONTEXT(ctx), t );
296 }
297 _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
298 height, format, type, pixels, packing, texObj,
299 texImage);
300 }
301
302 static void gammaBindTexture( GLcontext *ctx, GLenum target,
303 struct gl_texture_object *tObj )
304 {
305 gammaContextPtr gmesa = GAMMA_CONTEXT( ctx );
306 gammaTextureObjectPtr t = (gammaTextureObjectPtr) tObj->DriverData;
307
308 if (!t) {
309 GLfloat bias = ctx->Texture.Unit[ctx->Texture.CurrentUnit].LodBias;
310 t = CALLOC_STRUCT(gamma_texture_object_t);
311
312 /* Initialize non-image-dependent parts of the state:
313 */
314 t->globj = tObj;
315
316 t->TextureAddressMode = TextureAddressModeEnable | TAM_Operation_3D |
317 TAM_DY_Enable | TAM_LODEnable;
318 t->TextureReadMode = TextureReadModeEnable | TRM_PrimaryCacheEnable |
319 TRM_MipMapEnable | TRM_BorderClamp | TRM_Border;
320 t->TextureColorMode = TextureColorModeEnable;
321 t->TextureFilterMode = TextureFilterModeEnable;
322
323 if (target == GL_TEXTURE_2D) {
324 t->TextureAddressMode |= TAM_TexMapType_2D;
325 t->TextureReadMode |= TRM_TexMapType_2D;
326 }
327 else if (target == GL_TEXTURE_1D) {
328 t->TextureAddressMode |= TAM_TexMapType_1D;
329 t->TextureReadMode |= TRM_TexMapType_1D;
330 }
331
332 t->TextureColorMode = TextureColorModeEnable;
333
334 t->TextureFilterMode = TextureFilterModeEnable;
335
336 #ifdef MESA_LITTLE_ENDIAN
337 t->TextureFormat = (TF_LittleEndian |
338 #else
339 t->TextureFormat = (TF_BigEndian |
340 #endif
341 TF_ColorOrder_RGB |
342 TF_OutputFmt_Texel);
343
344 t->dirty_images = ~0;
345
346 tObj->DriverData = t;
347 make_empty_list( t );
348
349 gammaSetTexWrapping( t, tObj->WrapS, tObj->WrapT );
350 gammaSetTexFilter( gmesa, t, tObj->MinFilter, tObj->MagFilter, bias );
351 gammaSetTexBorderColor( gmesa, t, tObj->_BorderChan );
352 }
353 }
354
355 static void gammaDeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj )
356 {
357 gammaTextureObjectPtr t = (gammaTextureObjectPtr)tObj->DriverData;
358
359 if (t) {
360 gammaContextPtr gmesa = GAMMA_CONTEXT( ctx );
361 #if 0
362 if (gmesa)
363 GAMMA_FIREVERTICES( gmesa );
364 #endif
365 gammaDestroyTexObj( gmesa, t );
366 tObj->DriverData = 0;
367 }
368 /* Free mipmap images and the texture object itself */
369 _mesa_delete_texture_object(ctx, tObj);
370 }
371
372 static GLboolean gammaIsTextureResident( GLcontext *ctx,
373 struct gl_texture_object *tObj )
374 {
375 gammaTextureObjectPtr t = (gammaTextureObjectPtr)tObj->DriverData;
376 return t && t->MemBlock;
377 }
378
379 /**
380 * Allocate a new texture object.
381 * Called via ctx->Driver.NewTextureObject.
382 * Note: this function will be called during context creation to
383 * allocate the default texture objects.
384 * Note: we could use containment here to 'derive' the driver-specific
385 * texture object from the core mesa gl_texture_object. Not done at this time.
386 */
387 static struct gl_texture_object *
388 gammaNewTextureObject( GLcontext *ctx, GLuint name, GLenum target )
389 {
390 struct gl_texture_object *obj;
391 obj = _mesa_new_texture_object(ctx, name, target);
392 return obj;
393 }
394
395 void gammaInitTextureObjects( GLcontext *ctx )
396 {
397 struct gl_texture_object *texObj;
398 GLuint tmp = ctx->Texture.CurrentUnit;
399
400 ctx->Texture.CurrentUnit = 0;
401
402 texObj = ctx->Texture.Unit[0].Current1D;
403 gammaBindTexture( ctx, GL_TEXTURE_1D, texObj );
404
405 texObj = ctx->Texture.Unit[0].Current2D;
406 gammaBindTexture( ctx, GL_TEXTURE_2D, texObj );
407
408 #if 0
409 ctx->Texture.CurrentUnit = 1;
410
411 texObj = ctx->Texture.Unit[1].Current1D;
412 gammaBindTexture( ctx, GL_TEXTURE_1D, texObj );
413
414 texObj = ctx->Texture.Unit[1].Current2D;
415 gammaBindTexture( ctx, GL_TEXTURE_2D, texObj );
416 #endif
417
418 ctx->Texture.CurrentUnit = tmp;
419 }
420
421
422 void gammaDDInitTextureFuncs( struct dd_function_table *functions )
423 {
424 functions->TexEnv = gammaTexEnv;
425 functions->TexImage2D = gammaTexImage2D;
426 functions->TexSubImage2D = gammaTexSubImage2D;
427 functions->BindTexture = gammaBindTexture;
428 functions->DeleteTexture = gammaDeleteTexture;
429 functions->TexParameter = gammaTexParameter;
430 functions->IsTextureResident = gammaIsTextureResident;
431 }