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