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