Merge branch 'mesa_7_6_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 (!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 */
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 =
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
236 void
237 intel_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
263 void
264 intel_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
282 void
283 intel_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
294 void
295 intel_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 }