intel_tex.c revision dc58da3e063d2a4018eea9149b43a3656a93a7ca
1#include "swrast/swrast.h" 2#include "main/texobj.h" 3#include "main/teximage.h" 4#include "main/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 struct gl_texture_object *texObj) 176{ 177 struct intel_context *intel = intel_context(ctx); 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, 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 /* Unreference the miptree to signal that the new Data is a bare 198 * pointer from mesa. 199 */ 200 intel_miptree_release(intel, &intelImage->mt); 201 } 202 } 203} 204 205static void intelGenerateMipmap(GLcontext *ctx, GLenum target, struct gl_texture_object *texObj) 206{ 207 struct intel_context *intel = intel_context(ctx); 208 struct intel_texture_object *intelObj = intel_texture_object(texObj); 209 210 intel_tex_map_level_images(intel, intelObj, texObj->BaseLevel); 211 intel_generate_mipmap(ctx, target, texObj); 212 intel_tex_unmap_level_images(intel, intelObj, texObj->BaseLevel); 213} 214 215void 216intelInitTextureFuncs(struct dd_function_table *functions) 217{ 218 functions->ChooseTextureFormat = intelChooseTextureFormat; 219 functions->TexImage1D = intelTexImage1D; 220 functions->TexImage2D = intelTexImage2D; 221 functions->TexImage3D = intelTexImage3D; 222 functions->TexSubImage1D = intelTexSubImage1D; 223 functions->TexSubImage2D = intelTexSubImage2D; 224 functions->TexSubImage3D = intelTexSubImage3D; 225 functions->CopyTexImage1D = intelCopyTexImage1D; 226 functions->CopyTexImage2D = intelCopyTexImage2D; 227 functions->CopyTexSubImage1D = intelCopyTexSubImage1D; 228 functions->CopyTexSubImage2D = intelCopyTexSubImage2D; 229 functions->GetTexImage = intelGetTexImage; 230 functions->GenerateMipmap = intelGenerateMipmap; 231 232 /* compressed texture functions */ 233 functions->CompressedTexImage2D = intelCompressedTexImage2D; 234 functions->CompressedTexSubImage2D = intelCompressedTexSubImage2D; 235 functions->GetCompressedTexImage = intelGetCompressedTexImage; 236 237 functions->NewTextureObject = intelNewTextureObject; 238 functions->NewTextureImage = intelNewTextureImage; 239 functions->DeleteTexture = intelDeleteTextureObject; 240 functions->FreeTexImageData = intelFreeTextureImageData; 241 functions->UpdateTexturePalette = 0; 242 functions->IsTextureResident = intelIsTextureResident; 243 244#if DO_DEBUG && !defined(__ia64__) 245 if (INTEL_DEBUG & DEBUG_BUFMGR) 246 functions->TextureMemCpy = timed_memcpy; 247 else 248#endif 249 functions->TextureMemCpy = do_memcpy; 250} 251