r600: Convert to shared debug code and add a few new debug messages.
[mesa.git] / src / mesa / drivers / dri / r600 / r600_tex.c
1 /*
2 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
3
4 The Weather Channel (TM) funded Tungsten Graphics to develop the
5 initial release of the Radeon 8500 driver under the XFree86 license.
6 This notice must be preserved.
7
8 Permission is hereby granted, free of charge, to any person obtaining
9 a copy of this software and associated documentation files (the
10 "Software"), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sublicense, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
15
16 The above copyright notice and this permission notice (including the
17 next paragraph) shall be included in all copies or substantial
18 portions of the Software.
19
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
24 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 */
28
29 /**
30 * \file
31 *
32 * \author Keith Whitwell <keith@tungstengraphics.com>
33 */
34
35 #include "main/glheader.h"
36 #include "main/imports.h"
37 #include "main/colormac.h"
38 #include "main/context.h"
39 #include "main/enums.h"
40 #include "main/image.h"
41 #include "main/mipmap.h"
42 #include "main/simple_list.h"
43 #include "main/texformat.h"
44 #include "main/texstore.h"
45 #include "main/teximage.h"
46 #include "main/texobj.h"
47
48 #include "texmem.h"
49
50 #include "r600_context.h"
51 #include "r700_state.h"
52 #include "radeon_mipmap_tree.h"
53 #include "r600_tex.h"
54
55 #include "xmlpool.h"
56
57
58 static unsigned int translate_wrap_mode(GLenum wrapmode)
59 {
60 switch(wrapmode) {
61 case GL_REPEAT: return SQ_TEX_WRAP;
62 case GL_CLAMP: return SQ_TEX_CLAMP_HALF_BORDER;
63 case GL_CLAMP_TO_EDGE: return SQ_TEX_CLAMP_LAST_TEXEL;
64 case GL_CLAMP_TO_BORDER: return SQ_TEX_CLAMP_BORDER;
65 case GL_MIRRORED_REPEAT: return SQ_TEX_MIRROR;
66 case GL_MIRROR_CLAMP_EXT: return SQ_TEX_MIRROR_ONCE_HALF_BORDER;
67 case GL_MIRROR_CLAMP_TO_EDGE_EXT: return SQ_TEX_MIRROR_ONCE_LAST_TEXEL;
68 case GL_MIRROR_CLAMP_TO_BORDER_EXT: return SQ_TEX_MIRROR_ONCE_BORDER;
69 default:
70 radeon_error("bad wrap mode in %s", __FUNCTION__);
71 return 0;
72 }
73 }
74
75
76 /**
77 * Update the cached hardware registers based on the current texture wrap modes.
78 *
79 * \param t Texture object whose wrap modes are to be set
80 */
81 static void r600UpdateTexWrap(radeonTexObjPtr t)
82 {
83 struct gl_texture_object *tObj = &t->base;
84
85 SETfield(t->SQ_TEX_SAMPLER0, translate_wrap_mode(tObj->WrapS),
86 SQ_TEX_SAMPLER_WORD0_0__CLAMP_X_shift, SQ_TEX_SAMPLER_WORD0_0__CLAMP_X_mask);
87
88 if (tObj->Target != GL_TEXTURE_1D) {
89 SETfield(t->SQ_TEX_SAMPLER0, translate_wrap_mode(tObj->WrapT),
90 CLAMP_Y_shift, CLAMP_Y_mask);
91
92 if (tObj->Target == GL_TEXTURE_3D)
93 SETfield(t->SQ_TEX_SAMPLER0, translate_wrap_mode(tObj->WrapR),
94 CLAMP_Z_shift, CLAMP_Z_mask);
95 }
96 }
97
98 static void r600SetTexDefaultState(radeonTexObjPtr t)
99 {
100 /* Init text object to default states. */
101 t->SQ_TEX_RESOURCE0 = 0;
102 SETfield(t->SQ_TEX_RESOURCE0, SQ_TEX_DIM_2D, DIM_shift, DIM_mask);
103 SETfield(t->SQ_TEX_RESOURCE0, ARRAY_LINEAR_GENERAL,
104 SQ_TEX_RESOURCE_WORD0_0__TILE_MODE_shift, SQ_TEX_RESOURCE_WORD0_0__TILE_MODE_mask);
105 CLEARbit(t->SQ_TEX_RESOURCE0, TILE_TYPE_bit);
106
107 t->SQ_TEX_RESOURCE1 = 0;
108 SETfield(t->SQ_TEX_RESOURCE1, FMT_8_8_8_8,
109 SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
110
111 t->SQ_TEX_RESOURCE2 = 0;
112 t->SQ_TEX_RESOURCE3 = 0;
113
114 t->SQ_TEX_RESOURCE4 = 0;
115 SETfield(t->SQ_TEX_RESOURCE4, SQ_FORMAT_COMP_UNSIGNED,
116 FORMAT_COMP_X_shift, FORMAT_COMP_X_mask);
117 SETfield(t->SQ_TEX_RESOURCE4, SQ_FORMAT_COMP_UNSIGNED,
118 FORMAT_COMP_Y_shift, FORMAT_COMP_Y_mask);
119 SETfield(t->SQ_TEX_RESOURCE4, SQ_FORMAT_COMP_UNSIGNED,
120 FORMAT_COMP_Z_shift, FORMAT_COMP_Z_mask);
121 SETfield(t->SQ_TEX_RESOURCE4, SQ_FORMAT_COMP_UNSIGNED,
122 FORMAT_COMP_W_shift, FORMAT_COMP_W_mask);
123 SETfield(t->SQ_TEX_RESOURCE4, SQ_NUM_FORMAT_NORM,
124 SQ_TEX_RESOURCE_WORD4_0__NUM_FORMAT_ALL_shift, SQ_TEX_RESOURCE_WORD4_0__NUM_FORMAT_ALL_mask);
125 CLEARbit(t->SQ_TEX_RESOURCE4, SQ_TEX_RESOURCE_WORD4_0__SRF_MODE_ALL_bit);
126 CLEARbit(t->SQ_TEX_RESOURCE4, SQ_TEX_RESOURCE_WORD4_0__FORCE_DEGAMMA_bit);
127 SETfield(t->SQ_TEX_RESOURCE4, SQ_ENDIAN_NONE,
128 SQ_TEX_RESOURCE_WORD4_0__ENDIAN_SWAP_shift, SQ_TEX_RESOURCE_WORD4_0__ENDIAN_SWAP_mask);
129 SETfield(t->SQ_TEX_RESOURCE4, 1, REQUEST_SIZE_shift, REQUEST_SIZE_mask);
130 SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
131 SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift,
132 SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
133 SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
134 SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift,
135 SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
136 SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
137 SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift,
138 SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
139 SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_W,
140 SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift,
141 SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
142 SETfield(t->SQ_TEX_RESOURCE4, 0, BASE_LEVEL_shift, BASE_LEVEL_mask); /* mip-maps */
143
144 t->SQ_TEX_RESOURCE5 = 0;
145 t->SQ_TEX_RESOURCE6 = 0;
146
147 SETfield(t->SQ_TEX_RESOURCE6, SQ_TEX_VTX_VALID_TEXTURE,
148 SQ_TEX_RESOURCE_WORD6_0__TYPE_shift, SQ_TEX_RESOURCE_WORD6_0__TYPE_mask);
149
150 /* Initialize sampler registers */
151 t->SQ_TEX_SAMPLER0 = 0;
152 SETfield(t->SQ_TEX_SAMPLER0, SQ_TEX_WRAP, SQ_TEX_SAMPLER_WORD0_0__CLAMP_X_shift,
153 SQ_TEX_SAMPLER_WORD0_0__CLAMP_X_mask);
154 SETfield(t->SQ_TEX_SAMPLER0, SQ_TEX_WRAP, CLAMP_Y_shift, CLAMP_Y_mask);
155 SETfield(t->SQ_TEX_SAMPLER0, SQ_TEX_WRAP, CLAMP_Z_shift, CLAMP_Z_mask);
156 SETfield(t->SQ_TEX_SAMPLER0, SQ_TEX_XY_FILTER_POINT, XY_MAG_FILTER_shift, XY_MAG_FILTER_mask);
157 SETfield(t->SQ_TEX_SAMPLER0, SQ_TEX_XY_FILTER_POINT, XY_MIN_FILTER_shift, XY_MIN_FILTER_mask);
158 SETfield(t->SQ_TEX_SAMPLER0, SQ_TEX_Z_FILTER_NONE, Z_FILTER_shift, Z_FILTER_mask);
159 SETfield(t->SQ_TEX_SAMPLER0, SQ_TEX_Z_FILTER_NONE, MIP_FILTER_shift, MIP_FILTER_mask);
160 SETfield(t->SQ_TEX_SAMPLER0, SQ_TEX_BORDER_COLOR_TRANS_BLACK, BORDER_COLOR_TYPE_shift, BORDER_COLOR_TYPE_mask);
161
162 t->SQ_TEX_SAMPLER1 = 0;
163 SETfield(t->SQ_TEX_SAMPLER1, 0x3ff, MAX_LOD_shift, MAX_LOD_mask);
164
165 t->SQ_TEX_SAMPLER2 = 0;
166 SETbit(t->SQ_TEX_SAMPLER2, SQ_TEX_SAMPLER_WORD2_0__TYPE_bit);
167 }
168
169
170 #if 0
171 static GLuint aniso_filter(GLfloat anisotropy)
172 {
173 if (anisotropy >= 16.0) {
174 return R300_TX_MAX_ANISO_16_TO_1;
175 } else if (anisotropy >= 8.0) {
176 return R300_TX_MAX_ANISO_8_TO_1;
177 } else if (anisotropy >= 4.0) {
178 return R300_TX_MAX_ANISO_4_TO_1;
179 } else if (anisotropy >= 2.0) {
180 return R300_TX_MAX_ANISO_2_TO_1;
181 } else {
182 return R300_TX_MAX_ANISO_1_TO_1;
183 }
184 return 0;
185 }
186 #endif
187
188 /**
189 * Set the texture magnification and minification modes.
190 *
191 * \param t Texture whose filter modes are to be set
192 * \param minf Texture minification mode
193 * \param magf Texture magnification mode
194 * \param anisotropy Maximum anisotropy level
195 */
196 static void r600SetTexFilter(radeonTexObjPtr t, GLenum minf, GLenum magf, GLfloat anisotropy)
197 {
198 /* Force revalidation to account for switches from/to mipmapping. */
199 t->validated = GL_FALSE;
200
201 /* Note that EXT_texture_filter_anisotropic is extremely vague about
202 * how anisotropic filtering interacts with the "normal" filter modes.
203 * When anisotropic filtering is enabled, we override min and mag
204 * filter settings completely. This includes driconf's settings.
205 */
206 if (anisotropy >= 2.0 && (minf != GL_NEAREST) && (magf != GL_NEAREST)) {
207 /*t->pp_txfilter |= R300_TX_MAG_FILTER_ANISO
208 | R300_TX_MIN_FILTER_ANISO
209 | R300_TX_MIN_FILTER_MIP_LINEAR
210 | aniso_filter(anisotropy);*/
211 radeon_print(RADEON_TEXTURE, RADEON_NORMAL, "Using maximum anisotropy of %f\n", anisotropy);
212 return;
213 }
214
215 switch (minf) {
216 case GL_NEAREST:
217 SETfield(t->SQ_TEX_SAMPLER0, TEX_XYFilter_Point,
218 XY_MIN_FILTER_shift, XY_MIN_FILTER_mask);
219 SETfield(t->SQ_TEX_SAMPLER0, TEX_MipFilter_None,
220 MIP_FILTER_shift, MIP_FILTER_mask);
221 break;
222 case GL_LINEAR:
223 SETfield(t->SQ_TEX_SAMPLER0, TEX_XYFilter_Linear,
224 XY_MIN_FILTER_shift, XY_MIN_FILTER_mask);
225 SETfield(t->SQ_TEX_SAMPLER0, TEX_MipFilter_None,
226 MIP_FILTER_shift, MIP_FILTER_mask);
227 break;
228 case GL_NEAREST_MIPMAP_NEAREST:
229 SETfield(t->SQ_TEX_SAMPLER0, TEX_XYFilter_Point,
230 XY_MIN_FILTER_shift, XY_MIN_FILTER_mask);
231 SETfield(t->SQ_TEX_SAMPLER0, TEX_MipFilter_Point,
232 MIP_FILTER_shift, MIP_FILTER_mask);
233 break;
234 case GL_NEAREST_MIPMAP_LINEAR:
235 SETfield(t->SQ_TEX_SAMPLER0, TEX_XYFilter_Point,
236 XY_MIN_FILTER_shift, XY_MIN_FILTER_mask);
237 SETfield(t->SQ_TEX_SAMPLER0, TEX_MipFilter_Linear,
238 MIP_FILTER_shift, MIP_FILTER_mask);
239 break;
240 case GL_LINEAR_MIPMAP_NEAREST:
241 SETfield(t->SQ_TEX_SAMPLER0, TEX_XYFilter_Linear,
242 XY_MIN_FILTER_shift, XY_MIN_FILTER_mask);
243 SETfield(t->SQ_TEX_SAMPLER0, TEX_MipFilter_Point,
244 MIP_FILTER_shift, MIP_FILTER_mask);
245 break;
246 case GL_LINEAR_MIPMAP_LINEAR:
247 SETfield(t->SQ_TEX_SAMPLER0, TEX_XYFilter_Linear,
248 XY_MIN_FILTER_shift, XY_MIN_FILTER_mask);
249 SETfield(t->SQ_TEX_SAMPLER0, TEX_MipFilter_Linear,
250 MIP_FILTER_shift, MIP_FILTER_mask);
251 break;
252 }
253
254 /* Note we don't have 3D mipmaps so only use the mag filter setting
255 * to set the 3D texture filter mode.
256 */
257 switch (magf) {
258 case GL_NEAREST:
259 SETfield(t->SQ_TEX_SAMPLER0, TEX_XYFilter_Point,
260 XY_MAG_FILTER_shift, XY_MAG_FILTER_mask);
261 break;
262 case GL_LINEAR:
263 SETfield(t->SQ_TEX_SAMPLER0, TEX_XYFilter_Linear,
264 XY_MAG_FILTER_shift, XY_MAG_FILTER_mask);
265 break;
266 }
267 }
268
269 static void r600SetTexBorderColor(radeonTexObjPtr t, const GLfloat color[4])
270 {
271 t->TD_PS_SAMPLER0_BORDER_ALPHA = *((uint32_t*)&(color[3]));
272 t->TD_PS_SAMPLER0_BORDER_RED = *((uint32_t*)&(color[2]));
273 t->TD_PS_SAMPLER0_BORDER_GREEN = *((uint32_t*)&(color[1]));
274 t->TD_PS_SAMPLER0_BORDER_BLUE = *((uint32_t*)&(color[0]));
275 SETfield(t->SQ_TEX_SAMPLER0, SQ_TEX_BORDER_COLOR_REGISTER,
276 BORDER_COLOR_TYPE_shift, BORDER_COLOR_TYPE_mask);
277 }
278
279 /**
280 * Changes variables and flags for a state update, which will happen at the
281 * next UpdateTextureState
282 */
283
284 static void r600TexParameter(GLcontext * ctx, GLenum target,
285 struct gl_texture_object *texObj,
286 GLenum pname, const GLfloat * params)
287 {
288 radeonTexObj* t = radeon_tex_obj(texObj);
289
290 radeon_print(RADEON_STATE | RADEON_TEXTURE, RADEON_VERBOSE,
291 "%s( %s )\n", __FUNCTION__,
292 _mesa_lookup_enum_by_nr(pname));
293
294 switch (pname) {
295 case GL_TEXTURE_MIN_FILTER:
296 case GL_TEXTURE_MAG_FILTER:
297 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
298 r600SetTexFilter(t, texObj->MinFilter, texObj->MagFilter, texObj->MaxAnisotropy);
299 break;
300
301 case GL_TEXTURE_WRAP_S:
302 case GL_TEXTURE_WRAP_T:
303 case GL_TEXTURE_WRAP_R:
304 r600UpdateTexWrap(t);
305 break;
306
307 case GL_TEXTURE_BORDER_COLOR:
308 r600SetTexBorderColor(t, texObj->BorderColor);
309 break;
310
311 case GL_TEXTURE_BASE_LEVEL:
312 case GL_TEXTURE_MAX_LEVEL:
313 case GL_TEXTURE_MIN_LOD:
314 case GL_TEXTURE_MAX_LOD:
315 /* This isn't the most efficient solution but there doesn't appear to
316 * be a nice alternative. Since there's no LOD clamping,
317 * we just have to rely on loading the right subset of mipmap levels
318 * to simulate a clamped LOD.
319 */
320 if (t->mt) {
321 radeon_miptree_unreference(t->mt);
322 t->mt = 0;
323 t->validated = GL_FALSE;
324 }
325 break;
326
327 case GL_DEPTH_TEXTURE_MODE:
328 if (!texObj->Image[0][texObj->BaseLevel])
329 return;
330 if (texObj->Image[0][texObj->BaseLevel]->TexFormat->BaseFormat
331 == GL_DEPTH_COMPONENT) {
332 r600SetDepthTexMode(texObj);
333 break;
334 } else {
335 /* If the texture isn't a depth texture, changing this
336 * state won't cause any changes to the hardware.
337 * Don't force a flush of texture state.
338 */
339 return;
340 }
341
342 default:
343 return;
344 }
345 }
346
347 static void r600DeleteTexture(GLcontext * ctx, struct gl_texture_object *texObj)
348 {
349 context_t* rmesa = R700_CONTEXT(ctx);
350 radeonTexObj* t = radeon_tex_obj(texObj);
351
352 radeon_print(RADEON_STATE | RADEON_TEXTURE, RADEON_NORMAL,
353 "%s( %p (target = %s) )\n", __FUNCTION__,
354 (void *)texObj,
355 _mesa_lookup_enum_by_nr(texObj->Target));
356
357 if (rmesa) {
358 int i;
359 radeon_firevertices(&rmesa->radeon);
360
361 for(i = 0; i < R700_MAX_TEXTURE_UNITS; ++i)
362 if (rmesa->hw.textures[i] == t)
363 rmesa->hw.textures[i] = 0;
364 }
365
366 if (t->bo) {
367 radeon_bo_unref(t->bo);
368 t->bo = NULL;
369 }
370
371 if (t->mt) {
372 radeon_miptree_unreference(t->mt);
373 t->mt = 0;
374 }
375 _mesa_delete_texture_object(ctx, texObj);
376 }
377
378 /**
379 * Allocate a new texture object.
380 * Called via ctx->Driver.NewTextureObject.
381 * Note: this function will be called during context creation to
382 * allocate the default texture objects.
383 * Fixup MaxAnisotropy according to user preference.
384 */
385 static struct gl_texture_object *r600NewTextureObject(GLcontext * ctx,
386 GLuint name,
387 GLenum target)
388 {
389 context_t* rmesa = R700_CONTEXT(ctx);
390 radeonTexObj* t = CALLOC_STRUCT(radeon_tex_obj);
391
392
393 radeon_print(RADEON_STATE | RADEON_TEXTURE, RADEON_NORMAL,
394 "%s( %p (target = %s) )\n", __FUNCTION__,
395 t, _mesa_lookup_enum_by_nr(target));
396
397 _mesa_initialize_texture_object(&t->base, name, target);
398 t->base.MaxAnisotropy = rmesa->radeon.initialMaxAnisotropy;
399
400 /* Initialize hardware state */
401 r600SetTexDefaultState(t);
402 r600UpdateTexWrap(t);
403 r600SetTexFilter(t, t->base.MinFilter, t->base.MagFilter, t->base.MaxAnisotropy);
404 r600SetTexBorderColor(t, t->base.BorderColor);
405
406 return &t->base;
407 }
408
409 void r600InitTextureFuncs(struct dd_function_table *functions)
410 {
411 /* Note: we only plug in the functions we implement in the driver
412 * since _mesa_init_driver_functions() was already called.
413 */
414 functions->NewTextureImage = radeonNewTextureImage;
415 functions->FreeTexImageData = radeonFreeTexImageData;
416 functions->MapTexture = radeonMapTexture;
417 functions->UnmapTexture = radeonUnmapTexture;
418
419 functions->ChooseTextureFormat = radeonChooseTextureFormat_mesa;
420 functions->TexImage1D = radeonTexImage1D;
421 functions->TexImage2D = radeonTexImage2D;
422 functions->TexImage3D = radeonTexImage3D;
423 functions->TexSubImage1D = radeonTexSubImage1D;
424 functions->TexSubImage2D = radeonTexSubImage2D;
425 functions->TexSubImage3D = radeonTexSubImage3D;
426 functions->GetTexImage = radeonGetTexImage;
427 functions->GetCompressedTexImage = radeonGetCompressedTexImage;
428 functions->NewTextureObject = r600NewTextureObject;
429 functions->DeleteTexture = r600DeleteTexture;
430 functions->IsTextureResident = driIsTextureResident;
431
432 functions->TexParameter = r600TexParameter;
433
434 functions->CompressedTexImage2D = radeonCompressedTexImage2D;
435 functions->CompressedTexSubImage2D = radeonCompressedTexSubImage2D;
436
437 functions->GenerateMipmap = radeonGenerateMipmap;
438
439 driInitTextureFormats();
440 }