intel_tex.c revision 7d4b348c67dbc2eff1d7dd0c043a76bc0eae57ab
1#include "swrast/swrast.h" 2#include "main/texobj.h" 3#include "main/teximage.h" 4#include "main/mipmap.h" 5#include "drivers/common/meta.h" 6#include "intel_context.h" 7#include "intel_mipmap_tree.h" 8#include "intel_tex.h" 9 10#define FILE_DEBUG_FLAG DEBUG_TEXTURE 11 12static GLboolean 13intelIsTextureResident(GLcontext * ctx, struct gl_texture_object *texObj) 14{ 15#if 0 16 struct intel_context *intel = intel_context(ctx); 17 struct intel_texture_object *intelObj = intel_texture_object(texObj); 18 19 return 20 intelObj->mt && 21 intelObj->mt->region && 22 intel_is_region_resident(intel, intelObj->mt->region); 23#endif 24 return 1; 25} 26 27 28 29static struct gl_texture_image * 30intelNewTextureImage(GLcontext * ctx) 31{ 32 DBG("%s\n", __FUNCTION__); 33 (void) ctx; 34 return (struct gl_texture_image *) CALLOC_STRUCT(intel_texture_image); 35} 36 37 38static struct gl_texture_object * 39intelNewTextureObject(GLcontext * ctx, GLuint name, GLenum target) 40{ 41 struct intel_texture_object *obj = CALLOC_STRUCT(intel_texture_object); 42 43 DBG("%s\n", __FUNCTION__); 44 _mesa_initialize_texture_object(&obj->base, name, target); 45 46 return &obj->base; 47} 48 49static void 50intelDeleteTextureObject(GLcontext *ctx, 51 struct gl_texture_object *texObj) 52{ 53 struct intel_context *intel = intel_context(ctx); 54 struct intel_texture_object *intelObj = intel_texture_object(texObj); 55 56 if (intelObj->mt) 57 intel_miptree_release(intel, &intelObj->mt); 58 59 _mesa_delete_texture_object(ctx, texObj); 60} 61 62 63static void 64intelFreeTextureImageData(GLcontext * ctx, struct gl_texture_image *texImage) 65{ 66 struct intel_context *intel = intel_context(ctx); 67 struct intel_texture_image *intelImage = intel_texture_image(texImage); 68 69 DBG("%s\n", __FUNCTION__); 70 71 if (intelImage->mt) { 72 intel_miptree_release(intel, &intelImage->mt); 73 } 74 75 if (texImage->Data) { 76 _mesa_free_texmemory(texImage->Data); 77 texImage->Data = NULL; 78 } 79} 80 81 82/* The system memcpy (at least on ubuntu 5.10) has problems copying 83 * to agp (writecombined) memory from a source which isn't 64-byte 84 * aligned - there is a 4x performance falloff. 85 * 86 * The x86 __memcpy is immune to this but is slightly slower 87 * (10%-ish) than the system memcpy. 88 * 89 * The sse_memcpy seems to have a slight cliff at 64/32 bytes, but 90 * isn't much faster than x86_memcpy for agp copies. 91 * 92 * TODO: switch dynamically. 93 */ 94static void * 95do_memcpy(void *dest, const void *src, size_t n) 96{ 97 if ((((unsigned long) src) & 63) || (((unsigned long) dest) & 63)) { 98 return __memcpy(dest, src, n); 99 } 100 else 101 return memcpy(dest, src, n); 102} 103 104 105#if DO_DEBUG && !defined(__ia64__) 106 107#ifndef __x86_64__ 108static unsigned 109fastrdtsc(void) 110{ 111 unsigned eax; 112 __asm__ volatile ("\t" 113 "pushl %%ebx\n\t" 114 "cpuid\n\t" ".byte 0x0f, 0x31\n\t" 115 "popl %%ebx\n":"=a" (eax) 116 :"0"(0) 117 :"ecx", "edx", "cc"); 118 119 return eax; 120} 121#else 122static unsigned 123fastrdtsc(void) 124{ 125 unsigned eax; 126 __asm__ volatile ("\t" "cpuid\n\t" ".byte 0x0f, 0x31\n\t":"=a" (eax) 127 :"0"(0) 128 :"ecx", "edx", "ebx", "cc"); 129 130 return eax; 131} 132#endif 133 134static unsigned 135time_diff(unsigned t, unsigned t2) 136{ 137 return ((t < t2) ? t2 - t : 0xFFFFFFFFU - (t - t2 - 1)); 138} 139 140 141static void * 142timed_memcpy(void *dest, const void *src, size_t n) 143{ 144 void *ret; 145 unsigned t1, t2; 146 double rate; 147 148 if ((((unsigned) src) & 63) || (((unsigned) dest) & 63)) 149 _mesa_printf("Warning - non-aligned texture copy!\n"); 150 151 t1 = fastrdtsc(); 152 ret = do_memcpy(dest, src, n); 153 t2 = fastrdtsc(); 154 155 rate = time_diff(t1, t2); 156 rate /= (double) n; 157 _mesa_printf("timed_memcpy: %u %u --> %f clocks/byte\n", t1, t2, rate); 158 return ret; 159} 160#endif /* DO_DEBUG */ 161 162 163/** 164 * Called via ctx->Driver.GenerateMipmap() 165 * This is basically a wrapper for _mesa_meta_GenerateMipmap() which checks 166 * if we'll be using software mipmap generation. In that case, we need to 167 * map/unmap the base level texture image. 168 */ 169static void 170intelGenerateMipmap(GLcontext *ctx, GLenum target, 171 struct gl_texture_object *texObj) 172{ 173 if (_mesa_meta_check_generate_mipmap_fallback(ctx, target, texObj)) { 174 /* sw path: need to map texture images */ 175 struct intel_context *intel = intel_context(ctx); 176 struct intel_texture_object *intelObj = intel_texture_object(texObj); 177 intel_tex_map_level_images(intel, intelObj, texObj->BaseLevel); 178 _mesa_generate_mipmap(ctx, target, texObj); 179 intel_tex_unmap_level_images(intel, intelObj, texObj->BaseLevel); 180 } 181 else { 182 _mesa_meta_GenerateMipmap(ctx, target, texObj); 183 } 184} 185 186 187void 188intelInitTextureFuncs(struct dd_function_table *functions) 189{ 190 functions->ChooseTextureFormat = intelChooseTextureFormat; 191 functions->GenerateMipmap = intelGenerateMipmap; 192 193 functions->NewTextureObject = intelNewTextureObject; 194 functions->NewTextureImage = intelNewTextureImage; 195 functions->DeleteTexture = intelDeleteTextureObject; 196 functions->FreeTexImageData = intelFreeTextureImageData; 197 functions->UpdateTexturePalette = 0; 198 functions->IsTextureResident = intelIsTextureResident; 199 200#if DO_DEBUG && !defined(__ia64__) 201 if (INTEL_DEBUG & DEBUG_BUFMGR) 202 functions->TextureMemCpy = timed_memcpy; 203 else 204#endif 205 functions->TextureMemCpy = do_memcpy; 206} 207