intel_tex_validate.c revision f8f40b53a6a4551630e25bfd7f6e12334bb0f3f8
1#include "main/mtypes.h"
2#include "main/macros.h"
3
4#include "intel_context.h"
5#include "intel_batchbuffer.h"
6#include "intel_mipmap_tree.h"
7#include "intel_tex.h"
8#include "intel_chipset.h"
9
10#define FILE_DEBUG_FLAG DEBUG_TEXTURE
11
12/**
13 * Compute which mipmap levels that really need to be sent to the hardware.
14 * This depends on the base image size, GL_TEXTURE_MIN_LOD,
15 * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
16 */
17static void
18intel_calculate_first_last_level(struct intel_context *intel,
19				 struct intel_texture_object *intelObj)
20{
21   struct gl_texture_object *tObj = &intelObj->base;
22   const struct gl_texture_image *const baseImage =
23      tObj->Image[0][tObj->BaseLevel];
24
25   /* These must be signed values.  MinLod and MaxLod can be negative numbers,
26    * and having firstLevel and lastLevel as signed prevents the need for
27    * extra sign checks.
28    */
29   int firstLevel;
30   int lastLevel;
31
32   /* Yes, this looks overly complicated, but it's all needed.
33    */
34   switch (tObj->Target) {
35   case GL_TEXTURE_1D:
36   case GL_TEXTURE_2D:
37   case GL_TEXTURE_3D:
38   case GL_TEXTURE_CUBE_MAP:
39      if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) {
40         /* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL.
41          */
42         firstLevel = lastLevel = tObj->BaseLevel;
43      }
44      else {
45	 if (!IS_9XX(intel->intelScreen->deviceID)) {
46	    firstLevel = tObj->BaseLevel + (GLint) (tObj->MinLod + 0.5);
47	    firstLevel = MAX2(firstLevel, tObj->BaseLevel);
48	    firstLevel = MIN2(firstLevel, tObj->BaseLevel + baseImage->MaxLog2);
49	    lastLevel = tObj->BaseLevel + (GLint) (tObj->MaxLod + 0.5);
50	    lastLevel = MAX2(lastLevel, tObj->BaseLevel);
51	    lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2);
52	    lastLevel = MIN2(lastLevel, tObj->MaxLevel);
53	    lastLevel = MAX2(firstLevel, lastLevel);       /* need at least one level */
54	 } else {
55	    /* Min/max LOD are taken into account in sampler state.  We don't
56	     * want to re-layout textures just because clamping has been applied
57	     * since it means a bunch of blitting around and probably no memory
58	     * savings (since we have to keep the other levels around anyway).
59	     */
60	    firstLevel = tObj->BaseLevel;
61	    lastLevel = MIN2(tObj->BaseLevel + baseImage->MaxLog2,
62			     tObj->MaxLevel);
63	    /* need at least one level */
64	    lastLevel = MAX2(firstLevel, lastLevel);
65	 }
66      }
67      break;
68   case GL_TEXTURE_RECTANGLE_NV:
69   case GL_TEXTURE_4D_SGIS:
70      firstLevel = lastLevel = 0;
71      break;
72   default:
73      return;
74   }
75
76   /* save these values */
77   intelObj->firstLevel = firstLevel;
78   intelObj->lastLevel = lastLevel;
79}
80
81/**
82 * Copies the image's contents at its level into the object's miptree,
83 * and updates the image to point at the object's miptree.
84 */
85static void
86copy_image_data_to_tree(struct intel_context *intel,
87                        struct intel_texture_object *intelObj,
88                        struct intel_texture_image *intelImage)
89{
90   if (intelImage->mt) {
91      /* Copy potentially with the blitter:
92       */
93      intel_miptree_image_copy(intel,
94                               intelObj->mt,
95                               intelImage->face,
96                               intelImage->level, intelImage->mt);
97
98      intel_miptree_release(intel, &intelImage->mt);
99   }
100   else {
101      assert(intelImage->base.Data != NULL);
102
103      /* More straightforward upload.
104       */
105      intel_miptree_image_data(intel,
106                               intelObj->mt,
107                               intelImage->face,
108                               intelImage->level,
109                               intelImage->base.Data,
110                               intelImage->base.RowStride,
111                               intelImage->base.RowStride *
112                               intelImage->base.Height);
113      _mesa_align_free(intelImage->base.Data);
114      intelImage->base.Data = NULL;
115   }
116
117   intel_miptree_reference(&intelImage->mt, intelObj->mt);
118}
119
120
121/*
122 */
123GLuint
124intel_finalize_mipmap_tree(struct intel_context *intel, GLuint unit)
125{
126   struct gl_texture_object *tObj = intel->ctx.Texture.Unit[unit]._Current;
127   struct intel_texture_object *intelObj = intel_texture_object(tObj);
128   int comp_byte = 0;
129   int cpp;
130   GLuint face, i;
131   GLuint nr_faces = 0;
132   struct intel_texture_image *firstImage;
133
134   /* We know/require this is true by now:
135    */
136   assert(intelObj->base._Complete);
137
138   /* What levels must the tree include at a minimum?
139    */
140   intel_calculate_first_last_level(intel, intelObj);
141   firstImage =
142      intel_texture_image(intelObj->base.Image[0][intelObj->firstLevel]);
143
144   /* Fallback case:
145    */
146   if (firstImage->base.Border) {
147      if (intelObj->mt) {
148         intel_miptree_release(intel, &intelObj->mt);
149      }
150      return GL_FALSE;
151   }
152
153
154   /* If both firstImage and intelObj have a tree which can contain
155    * all active images, favour firstImage.  Note that because of the
156    * completeness requirement, we know that the image dimensions
157    * will match.
158    */
159   if (firstImage->mt &&
160       firstImage->mt != intelObj->mt &&
161       firstImage->mt->first_level <= intelObj->firstLevel &&
162       firstImage->mt->last_level >= intelObj->lastLevel) {
163
164      if (intelObj->mt)
165         intel_miptree_release(intel, &intelObj->mt);
166
167      intel_miptree_reference(&intelObj->mt, firstImage->mt);
168   }
169
170   if (_mesa_is_format_compressed(firstImage->base.TexFormat)) {
171      comp_byte = intel_compressed_num_bytes(firstImage->base.TexFormat);
172      cpp = comp_byte;
173   }
174   else
175      cpp = _mesa_get_format_bytes(firstImage->base.TexFormat);
176
177   /* Check tree can hold all active levels.  Check tree matches
178    * target, imageFormat, etc.
179    *
180    * XXX: For some layouts (eg i945?), the test might have to be
181    * first_level == firstLevel, as the tree isn't valid except at the
182    * original start level.  Hope to get around this by
183    * programming minLod, maxLod, baseLevel into the hardware and
184    * leaving the tree alone.
185    */
186   if (intelObj->mt &&
187       (intelObj->mt->target != intelObj->base.Target ||
188	intelObj->mt->internal_format != firstImage->base.InternalFormat ||
189	intelObj->mt->first_level != intelObj->firstLevel ||
190	intelObj->mt->last_level != intelObj->lastLevel ||
191	intelObj->mt->width0 != firstImage->base.Width ||
192	intelObj->mt->height0 != firstImage->base.Height ||
193	intelObj->mt->depth0 != firstImage->base.Depth ||
194	intelObj->mt->cpp != cpp ||
195	intelObj->mt->compressed != _mesa_is_format_compressed(firstImage->base.TexFormat))) {
196      intel_miptree_release(intel, &intelObj->mt);
197   }
198
199
200   /* May need to create a new tree:
201    */
202   if (!intelObj->mt) {
203      intelObj->mt = intel_miptree_create(intel,
204                                          intelObj->base.Target,
205                                          firstImage->base._BaseFormat,
206                                          firstImage->base.InternalFormat,
207                                          intelObj->firstLevel,
208                                          intelObj->lastLevel,
209                                          firstImage->base.Width,
210                                          firstImage->base.Height,
211                                          firstImage->base.Depth,
212                                          cpp,
213                                          comp_byte,
214					  GL_TRUE);
215   }
216
217   /* Pull in any images not in the object's tree:
218    */
219   nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
220   for (face = 0; face < nr_faces; face++) {
221      for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++) {
222         struct intel_texture_image *intelImage =
223            intel_texture_image(intelObj->base.Image[face][i]);
224
225         /* Need to import images in main memory or held in other trees.
226          */
227         if (intelObj->mt != intelImage->mt) {
228            copy_image_data_to_tree(intel, intelObj, intelImage);
229         }
230      }
231   }
232
233   return GL_TRUE;
234}
235
236void
237intel_tex_map_level_images(struct intel_context *intel,
238			   struct intel_texture_object *intelObj,
239			   int level)
240{
241   GLuint nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
242   GLuint face;
243
244   for (face = 0; face < nr_faces; face++) {
245      struct intel_texture_image *intelImage =
246	 intel_texture_image(intelObj->base.Image[face][level]);
247
248      if (intelImage && intelImage->mt) {
249	 intelImage->base.Data =
250	    intel_miptree_image_map(intel,
251				    intelImage->mt,
252				    intelImage->face,
253				    intelImage->level,
254				    &intelImage->base.RowStride,
255				    intelImage->base.ImageOffsets);
256	 /* convert stride to texels, not bytes */
257	 intelImage->base.RowStride /= intelImage->mt->cpp;
258	 /* intelImage->base.ImageStride /= intelImage->mt->cpp; */
259      }
260   }
261}
262
263void
264intel_tex_unmap_level_images(struct intel_context *intel,
265			     struct intel_texture_object *intelObj,
266			     int level)
267{
268   GLuint nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
269   GLuint face;
270
271   for (face = 0; face < nr_faces; face++) {
272      struct intel_texture_image *intelImage =
273	 intel_texture_image(intelObj->base.Image[face][level]);
274
275      if (intelImage && intelImage->mt) {
276	 intel_miptree_image_unmap(intel, intelImage->mt);
277	 intelImage->base.Data = NULL;
278      }
279   }
280}
281
282void
283intel_tex_map_images(struct intel_context *intel,
284                     struct intel_texture_object *intelObj)
285{
286   int i;
287
288   DBG("%s\n", __FUNCTION__);
289
290   for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++)
291      intel_tex_map_level_images(intel, intelObj, i);
292}
293
294void
295intel_tex_unmap_images(struct intel_context *intel,
296                       struct intel_texture_object *intelObj)
297{
298   int i;
299
300   for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++)
301      intel_tex_unmap_level_images(intel, intelObj, i);
302}
303