i965: set mt->cpp differently with compressed texture
[mesa.git] / src / mesa / drivers / dri / i965 / intel_tex_validate.c
1 /**************************************************************************
2 *
3 * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #include "mtypes.h"
29 #include "macros.h"
30
31 #include "intel_context.h"
32 #include "intel_mipmap_tree.h"
33 #include "intel_tex.h"
34 #include "bufmgr.h"
35
36 /**
37 * Compute which mipmap levels that really need to be sent to the hardware.
38 * This depends on the base image size, GL_TEXTURE_MIN_LOD,
39 * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
40 */
41 static void intel_calculate_first_last_level( struct intel_texture_object *intelObj )
42 {
43 struct gl_texture_object *tObj = &intelObj->base;
44 const struct gl_texture_image * const baseImage =
45 tObj->Image[0][tObj->BaseLevel];
46
47 /* These must be signed values. MinLod and MaxLod can be negative numbers,
48 * and having firstLevel and lastLevel as signed prevents the need for
49 * extra sign checks.
50 */
51 int firstLevel;
52 int lastLevel;
53
54 /* Yes, this looks overly complicated, but it's all needed.
55 */
56 switch (tObj->Target) {
57 case GL_TEXTURE_1D:
58 case GL_TEXTURE_2D:
59 case GL_TEXTURE_3D:
60 case GL_TEXTURE_CUBE_MAP:
61 if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) {
62 /* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL.
63 */
64 firstLevel = lastLevel = tObj->BaseLevel;
65 }
66 else {
67 /* Currently not taking min/max lod into account here, those
68 * values are programmed as sampler state elsewhere and we
69 * upload the same mipmap levels regardless. Not sure if
70 * this makes sense as it means it isn't possible for the app
71 * to use min/max lod to reduce texture memory pressure:
72 */
73 firstLevel = tObj->BaseLevel;
74 lastLevel = MIN2(tObj->BaseLevel + baseImage->MaxLog2,
75 tObj->MaxLevel);
76 lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */
77 }
78 break;
79 case GL_TEXTURE_RECTANGLE_NV:
80 case GL_TEXTURE_4D_SGIS:
81 firstLevel = lastLevel = 0;
82 break;
83 default:
84 return;
85 }
86
87 /* save these values */
88 intelObj->firstLevel = firstLevel;
89 intelObj->lastLevel = lastLevel;
90 }
91
92 static GLboolean copy_image_data_to_tree( struct intel_context *intel,
93 struct intel_texture_object *intelObj,
94 struct gl_texture_image *texImage,
95 GLuint face,
96 GLuint level)
97 {
98 return intel_miptree_image_data(intel,
99 intelObj->mt,
100 face,
101 level,
102 texImage->Data,
103 texImage->RowStride,
104 (texImage->RowStride *
105 texImage->Height *
106 texImage->TexFormat->TexelBytes));
107 }
108
109 static void intel_texture_invalidate( struct intel_texture_object *intelObj )
110 {
111 GLint nr_faces, face;
112 intelObj->dirty = ~0;
113
114 nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
115 for (face = 0; face < nr_faces; face++)
116 intelObj->dirty_images[face] = ~0;
117 }
118
119 static void intel_texture_invalidate_cb( struct intel_context *intel,
120 void *ptr )
121 {
122 intel_texture_invalidate( (struct intel_texture_object *) ptr );
123 }
124
125 #include "texformat.h"
126 static GLuint intel_compressed_num_bytes(GLenum mesaFormat)
127 {
128 GLuint bytes = 0;
129
130 switch (mesaFormat) {
131 case MESA_FORMAT_RGB_FXT1:
132 case MESA_FORMAT_RGBA_FXT1:
133 case MESA_FORMAT_RGB_DXT1:
134 case MESA_FORMAT_RGBA_DXT1:
135 bytes = 2;
136 break;
137
138 case MESA_FORMAT_RGBA_DXT3:
139 case MESA_FORMAT_RGBA_DXT5:
140 bytes = 4;
141
142 default:
143 break;
144 }
145
146 return bytes;
147 }
148
149 /*
150 */
151 GLuint intel_finalize_mipmap_tree( struct intel_context *intel,
152 struct gl_texture_object *tObj )
153 {
154 struct intel_texture_object *intelObj = intel_texture_object(tObj);
155 GLuint face, i;
156 GLuint nr_faces = 0;
157 struct gl_texture_image *firstImage;
158 GLuint cpp = 0;
159
160 if( tObj == intel->frame_buffer_texobj )
161 return GL_FALSE;
162
163 /* We know/require this is true by now:
164 */
165 assert(intelObj->base._Complete);
166
167 /* What levels must the tree include at a minimum?
168 */
169 if (intelObj->dirty) {
170 intel_calculate_first_last_level( intelObj );
171 /* intel_miptree_destroy(intel, intelObj->mt); */
172 /* intelObj->mt = NULL; */
173 }
174
175 firstImage = intelObj->base.Image[0][intelObj->firstLevel];
176
177 /* Fallback case:
178 */
179 if (firstImage->Border) {
180 if (intelObj->mt) {
181 intel_miptree_destroy(intel, intelObj->mt);
182 intelObj->mt = NULL;
183 /* Set all images dirty:
184 */
185 intel_texture_invalidate(intelObj);
186 }
187 return GL_FALSE;
188 }
189
190
191
192 if (firstImage->IsCompressed) {
193 cpp = intel_compressed_num_bytes(firstImage->TexFormat->MesaFormat);
194 } else {
195 cpp = firstImage->TexFormat->TexelBytes;
196 }
197
198 /* Check tree can hold all active levels. Check tree matches
199 * target, imageFormat, etc.
200 */
201 if (intelObj->mt &&
202 (intelObj->mt->target != intelObj->base.Target ||
203 intelObj->mt->internal_format != firstImage->InternalFormat ||
204 intelObj->mt->first_level != intelObj->firstLevel ||
205 intelObj->mt->last_level != intelObj->lastLevel ||
206 intelObj->mt->width0 != firstImage->Width ||
207 intelObj->mt->height0 != firstImage->Height ||
208 intelObj->mt->depth0 != firstImage->Depth ||
209 intelObj->mt->cpp != cpp ||
210 intelObj->mt->compressed != firstImage->IsCompressed))
211 {
212 intel_miptree_destroy(intel, intelObj->mt);
213 intelObj->mt = NULL;
214
215 /* Set all images dirty:
216 */
217 intel_texture_invalidate(intelObj);
218 }
219
220
221 /* May need to create a new tree:
222 */
223 if (!intelObj->mt) {
224 intelObj->mt = intel_miptree_create(intel,
225 intelObj->base.Target,
226 firstImage->InternalFormat,
227 intelObj->firstLevel,
228 intelObj->lastLevel,
229 firstImage->Width,
230 firstImage->Height,
231 firstImage->Depth,
232 cpp,
233 firstImage->IsCompressed);
234
235 /* Tell the buffer manager that we will manage the backing
236 * store, but we still want it to do fencing for us.
237 */
238 bmBufferSetInvalidateCB(intel,
239 intelObj->mt->region->buffer,
240 intel_texture_invalidate_cb,
241 intelObj,
242 GL_FALSE);
243 }
244
245 /* Pull in any images not in the object's tree:
246 */
247 if (intelObj->dirty) {
248 nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
249 for (face = 0; face < nr_faces; face++) {
250 if (intelObj->dirty_images[face]) {
251 for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++) {
252 struct gl_texture_image *texImage = intelObj->base.Image[face][i];
253
254 /* Need to import images in main memory or held in other trees.
255 */
256 if (intelObj->dirty_images[face] & (1<<i) &&
257 texImage) {
258
259 if (INTEL_DEBUG & DEBUG_TEXTURE)
260 _mesa_printf("copy data from image %d (%p) into object miptree\n",
261 i,
262 texImage->Data);
263
264 if (!copy_image_data_to_tree(intel,
265 intelObj,
266 texImage,
267 face,
268 i))
269 return GL_FALSE;
270
271 }
272 }
273 }
274 }
275
276 /* Only clear the dirty flags if everything went ok:
277 */
278 for (face = 0; face < nr_faces; face++) {
279 intelObj->dirty_images[face] = 0;
280 }
281
282 intelObj->dirty = 0;
283 }
284
285 return GL_TRUE;
286 }