intel_tex.c revision c50ffc4cb89b67ae59208eb72cdb664c846ba987
1#include "swrast/swrast.h" 2#include "texobj.h" 3#include "teximage.h" 4#include "mipmap.h" 5#include "intel_context.h" 6#include "intel_mipmap_tree.h" 7#include "intel_tex.h" 8 9#define FILE_DEBUG_FLAG DEBUG_TEXTURE 10 11static GLboolean 12intelIsTextureResident(GLcontext * ctx, struct gl_texture_object *texObj) 13{ 14#if 0 15 struct intel_context *intel = intel_context(ctx); 16 struct intel_texture_object *intelObj = intel_texture_object(texObj); 17 18 return 19 intelObj->mt && 20 intelObj->mt->region && 21 intel_is_region_resident(intel, intelObj->mt->region); 22#endif 23 return 1; 24} 25 26 27 28static struct gl_texture_image * 29intelNewTextureImage(GLcontext * ctx) 30{ 31 DBG("%s\n", __FUNCTION__); 32 (void) ctx; 33 return (struct gl_texture_image *) CALLOC_STRUCT(intel_texture_image); 34} 35 36 37static struct gl_texture_object * 38intelNewTextureObject(GLcontext * ctx, GLuint name, GLenum target) 39{ 40 struct intel_texture_object *obj = CALLOC_STRUCT(intel_texture_object); 41 42 DBG("%s\n", __FUNCTION__); 43 _mesa_initialize_texture_object(&obj->base, name, target); 44 45 return &obj->base; 46} 47 48static void 49intelDeleteTextureObject(GLcontext *ctx, 50 struct gl_texture_object *texObj) 51{ 52 struct intel_context *intel = intel_context(ctx); 53 struct intel_texture_object *intelObj = intel_texture_object(texObj); 54 55 if (intelObj->mt) 56 intel_miptree_release(intel, &intelObj->mt); 57 58 _mesa_delete_texture_object(ctx, texObj); 59} 60 61 62static void 63intelFreeTextureImageData(GLcontext * ctx, struct gl_texture_image *texImage) 64{ 65 struct intel_context *intel = intel_context(ctx); 66 struct intel_texture_image *intelImage = intel_texture_image(texImage); 67 68 DBG("%s\n", __FUNCTION__); 69 70 if (intelImage->mt) { 71 intel_miptree_release(intel, &intelImage->mt); 72 } 73 74 if (texImage->Data) { 75 _mesa_free_texmemory(texImage->Data); 76 texImage->Data = NULL; 77 } 78} 79 80 81/* The system memcpy (at least on ubuntu 5.10) has problems copying 82 * to agp (writecombined) memory from a source which isn't 64-byte 83 * aligned - there is a 4x performance falloff. 84 * 85 * The x86 __memcpy is immune to this but is slightly slower 86 * (10%-ish) than the system memcpy. 87 * 88 * The sse_memcpy seems to have a slight cliff at 64/32 bytes, but 89 * isn't much faster than x86_memcpy for agp copies. 90 * 91 * TODO: switch dynamically. 92 */ 93static void * 94do_memcpy(void *dest, const void *src, size_t n) 95{ 96 if ((((unsigned) src) & 63) || (((unsigned) dest) & 63)) { 97 return __memcpy(dest, src, n); 98 } 99 else 100 return memcpy(dest, src, n); 101} 102 103 104#if DO_DEBUG && !defined(__ia64__) 105 106#ifndef __x86_64__ 107static unsigned 108fastrdtsc(void) 109{ 110 unsigned eax; 111 __asm__ volatile ("\t" 112 "pushl %%ebx\n\t" 113 "cpuid\n\t" ".byte 0x0f, 0x31\n\t" 114 "popl %%ebx\n":"=a" (eax) 115 :"0"(0) 116 :"ecx", "edx", "cc"); 117 118 return eax; 119} 120#else 121static unsigned 122fastrdtsc(void) 123{ 124 unsigned eax; 125 __asm__ volatile ("\t" "cpuid\n\t" ".byte 0x0f, 0x31\n\t":"=a" (eax) 126 :"0"(0) 127 :"ecx", "edx", "ebx", "cc"); 128 129 return eax; 130} 131#endif 132 133static unsigned 134time_diff(unsigned t, unsigned t2) 135{ 136 return ((t < t2) ? t2 - t : 0xFFFFFFFFU - (t - t2 - 1)); 137} 138 139 140static void * 141timed_memcpy(void *dest, const void *src, size_t n) 142{ 143 void *ret; 144 unsigned t1, t2; 145 double rate; 146 147 if ((((unsigned) src) & 63) || (((unsigned) dest) & 63)) 148 _mesa_printf("Warning - non-aligned texture copy!\n"); 149 150 t1 = fastrdtsc(); 151 ret = do_memcpy(dest, src, n); 152 t2 = fastrdtsc(); 153 154 rate = time_diff(t1, t2); 155 rate /= (double) n; 156 _mesa_printf("timed_memcpy: %u %u --> %f clocks/byte\n", t1, t2, rate); 157 return ret; 158} 159#endif /* DO_DEBUG */ 160 161/** 162 * Generate new mipmap data from BASE+1 to BASE+p (the minimally-sized mipmap 163 * level). 164 * 165 * The texture object's miptree must be mapped. 166 * 167 * It would be really nice if this was just called by Mesa whenever mipmaps 168 * needed to be regenerated, rather than us having to remember to do so in 169 * each texture image modification path. 170 * 171 * This function should also include an accelerated path. 172 */ 173void 174intel_generate_mipmap(GLcontext *ctx, GLenum target, 175 const struct gl_texture_unit *texUnit, 176 struct gl_texture_object *texObj) 177{ 178 struct intel_texture_object *intelObj = intel_texture_object(texObj); 179 GLuint nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; 180 int face, i; 181 182 _mesa_generate_mipmap(ctx, target, texUnit, texObj); 183 184 /* Update the level information in our private data in the new images, since 185 * it didn't get set as part of a normal TexImage path. 186 */ 187 for (face = 0; face < nr_faces; face++) { 188 for (i = texObj->BaseLevel + 1; i < texObj->MaxLevel; i++) { 189 struct intel_texture_image *intelImage; 190 191 intelImage = intel_texture_image(texObj->Image[face][i]); 192 if (intelImage == NULL) 193 break; 194 195 intelImage->level = i; 196 intelImage->face = face; 197 } 198 } 199} 200 201void intelMapTexture(GLcontext *ctx, struct gl_texture_object *texObj) 202{ 203 struct intel_texture_object *intelObj = intel_texture_object(texObj); 204 struct intel_context *intel = intel_context(ctx); 205 206 intel_tex_map_images(intel, intelObj); 207} 208 209void intelUnmapTexture(GLcontext *ctx, struct gl_texture_object *texObj) 210{ 211 struct intel_texture_object *intelObj = intel_texture_object(texObj); 212 struct intel_context *intel = intel_context(ctx); 213 214 intel_tex_unmap_images(intel, intelObj); 215} 216 217void 218intelInitTextureFuncs(struct dd_function_table *functions) 219{ 220 functions->ChooseTextureFormat = intelChooseTextureFormat; 221 functions->TexImage1D = intelTexImage1D; 222 functions->TexImage2D = intelTexImage2D; 223 functions->TexImage3D = intelTexImage3D; 224 functions->TexSubImage1D = intelTexSubImage1D; 225 functions->TexSubImage2D = intelTexSubImage2D; 226 functions->TexSubImage3D = intelTexSubImage3D; 227#ifdef I915 228 functions->CopyTexImage1D = intelCopyTexImage1D; 229 functions->CopyTexImage2D = intelCopyTexImage2D; 230 functions->CopyTexSubImage1D = intelCopyTexSubImage1D; 231 functions->CopyTexSubImage2D = intelCopyTexSubImage2D; 232#else 233 functions->CopyTexImage1D = _swrast_copy_teximage1d; 234 functions->CopyTexImage2D = _swrast_copy_teximage2d; 235 functions->CopyTexSubImage1D = _swrast_copy_texsubimage1d; 236 functions->CopyTexSubImage2D = _swrast_copy_texsubimage2d; 237#endif 238 functions->GetTexImage = intelGetTexImage; 239 240 /* compressed texture functions */ 241 functions->CompressedTexImage2D = intelCompressedTexImage2D; 242 functions->GetCompressedTexImage = intelGetCompressedTexImage; 243 244 functions->NewTextureObject = intelNewTextureObject; 245 functions->NewTextureImage = intelNewTextureImage; 246 functions->DeleteTexture = intelDeleteTextureObject; 247 functions->FreeTexImageData = intelFreeTextureImageData; 248 functions->UpdateTexturePalette = 0; 249 functions->IsTextureResident = intelIsTextureResident; 250 251 functions->MapTexture = intelMapTexture; 252 functions->UnmapTexture = intelUnmapTexture; 253 254#if DO_DEBUG && !defined(__ia64__) 255 if (INTEL_DEBUG & DEBUG_BUFMGR) 256 functions->TextureMemCpy = timed_memcpy; 257 else 258#endif 259 functions->TextureMemCpy = do_memcpy; 260} 261