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