Merge branch 'mesa_7_6_branch' into mesa_7_7_branch
[mesa.git] / src / mesa / drivers / dri / intel / intel_tex_validate.c
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 */
17 static void
18 intel_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 (intel->gen == 2) {
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 */
85 static void
86 copy_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 */
123 GLuint
124 intel_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 = intel_texture_image(tObj->Image[0][intelObj->firstLevel]);
142
143 /* Fallback case:
144 */
145 if (firstImage->base.Border) {
146 if (intelObj->mt) {
147 intel_miptree_release(intel, &intelObj->mt);
148 }
149 return GL_FALSE;
150 }
151
152
153 /* If both firstImage and intelObj have a tree which can contain
154 * all active images, favour firstImage. Note that because of the
155 * completeness requirement, we know that the image dimensions
156 * will match.
157 */
158 if (firstImage->mt &&
159 firstImage->mt != intelObj->mt &&
160 firstImage->mt->first_level <= intelObj->firstLevel &&
161 firstImage->mt->last_level >= intelObj->lastLevel) {
162
163 if (intelObj->mt)
164 intel_miptree_release(intel, &intelObj->mt);
165
166 intel_miptree_reference(&intelObj->mt, firstImage->mt);
167 }
168
169 if (_mesa_is_format_compressed(firstImage->base.TexFormat)) {
170 comp_byte = intel_compressed_num_bytes(firstImage->base.TexFormat);
171 cpp = comp_byte;
172 }
173 else
174 cpp = _mesa_get_format_bytes(firstImage->base.TexFormat);
175
176 /* Check tree can hold all active levels. Check tree matches
177 * target, imageFormat, etc.
178 *
179 * XXX: For some layouts (eg i945?), the test might have to be
180 * first_level == firstLevel, as the tree isn't valid except at the
181 * original start level. Hope to get around this by
182 * programming minLod, maxLod, baseLevel into the hardware and
183 * leaving the tree alone.
184 */
185 if (intelObj->mt &&
186 (intelObj->mt->target != intelObj->base.Target ||
187 intelObj->mt->internal_format != firstImage->base.InternalFormat ||
188 intelObj->mt->first_level != intelObj->firstLevel ||
189 intelObj->mt->last_level != intelObj->lastLevel ||
190 intelObj->mt->width0 != firstImage->base.Width ||
191 intelObj->mt->height0 != firstImage->base.Height ||
192 intelObj->mt->depth0 != firstImage->base.Depth ||
193 intelObj->mt->cpp != cpp ||
194 intelObj->mt->compressed != _mesa_is_format_compressed(firstImage->base.TexFormat))) {
195 intel_miptree_release(intel, &intelObj->mt);
196 }
197
198
199 /* May need to create a new tree:
200 */
201 if (!intelObj->mt) {
202 intelObj->mt = intel_miptree_create(intel,
203 intelObj->base.Target,
204 firstImage->base._BaseFormat,
205 firstImage->base.InternalFormat,
206 intelObj->firstLevel,
207 intelObj->lastLevel,
208 firstImage->base.Width,
209 firstImage->base.Height,
210 firstImage->base.Depth,
211 cpp,
212 comp_byte,
213 GL_TRUE);
214 }
215
216 /* Pull in any images not in the object's tree:
217 */
218 nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
219 for (face = 0; face < nr_faces; face++) {
220 for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++) {
221 struct intel_texture_image *intelImage =
222 intel_texture_image(intelObj->base.Image[face][i]);
223
224 /* Need to import images in main memory or held in other trees.
225 * If it's a render target, then its data isn't needed to be in
226 * the object tree (otherwise we'd be FBO incomplete), and we need
227 * to keep track of the image's MT as needing to be pulled in still,
228 * or we'll lose the rendering that's done to it.
229 */
230 if (intelObj->mt != intelImage->mt &&
231 !intelImage->used_as_render_target) {
232 copy_image_data_to_tree(intel, intelObj, intelImage);
233 }
234 }
235 }
236
237 return GL_TRUE;
238 }
239
240 void
241 intel_tex_map_level_images(struct intel_context *intel,
242 struct intel_texture_object *intelObj,
243 int level)
244 {
245 GLuint nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
246 GLuint face;
247
248 for (face = 0; face < nr_faces; face++) {
249 struct intel_texture_image *intelImage =
250 intel_texture_image(intelObj->base.Image[face][level]);
251
252 if (intelImage && intelImage->mt) {
253 intelImage->base.Data =
254 intel_miptree_image_map(intel,
255 intelImage->mt,
256 intelImage->face,
257 intelImage->level,
258 &intelImage->base.RowStride,
259 intelImage->base.ImageOffsets);
260 /* convert stride to texels, not bytes */
261 intelImage->base.RowStride /= intelImage->mt->cpp;
262 /* intelImage->base.ImageStride /= intelImage->mt->cpp; */
263 }
264 }
265 }
266
267 void
268 intel_tex_unmap_level_images(struct intel_context *intel,
269 struct intel_texture_object *intelObj,
270 int level)
271 {
272 GLuint nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
273 GLuint face;
274
275 for (face = 0; face < nr_faces; face++) {
276 struct intel_texture_image *intelImage =
277 intel_texture_image(intelObj->base.Image[face][level]);
278
279 if (intelImage && intelImage->mt) {
280 intel_miptree_image_unmap(intel, intelImage->mt);
281 intelImage->base.Data = NULL;
282 }
283 }
284 }
285
286 void
287 intel_tex_map_images(struct intel_context *intel,
288 struct intel_texture_object *intelObj)
289 {
290 int i;
291
292 DBG("%s\n", __FUNCTION__);
293
294 for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++)
295 intel_tex_map_level_images(intel, intelObj, i);
296 }
297
298 void
299 intel_tex_unmap_images(struct intel_context *intel,
300 struct intel_texture_object *intelObj)
301 {
302 int i;
303
304 for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++)
305 intel_tex_unmap_level_images(intel, intelObj, i);
306 }