intel_tex.c revision 36daee1c7bec44b9d3641f056c84b3b2f39fabd9
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 long) src) & 63) || (((unsigned long) 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