8383c974c388fb86c6bcc1b5c9e40139e414754a
[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 /* 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 */
57 static void
58 copy_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 */
95 GLuint
96 intel_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
212 void
213 intel_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
239 void
240 intel_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
258 void
259 intel_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
270 void
271 intel_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 }