1 /**************************************************************************
3 * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
31 #include "intel_context.h"
32 #include "intel_mipmap_tree.h"
33 #include "intel_tex.h"
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.
41 static void intel_calculate_first_last_level( struct intel_texture_object
*intelObj
)
43 struct gl_texture_object
*tObj
= &intelObj
->base
;
44 const struct gl_texture_image
* const baseImage
=
45 tObj
->Image
[0][tObj
->BaseLevel
];
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
54 /* Yes, this looks overly complicated, but it's all needed.
56 switch (tObj
->Target
) {
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.
64 firstLevel
= lastLevel
= tObj
->BaseLevel
;
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:
73 firstLevel
= tObj
->BaseLevel
;
74 lastLevel
= MIN2(tObj
->BaseLevel
+ baseImage
->MaxLog2
,
76 lastLevel
= MAX2(firstLevel
, lastLevel
); /* need at least one level */
79 case GL_TEXTURE_RECTANGLE_NV
:
80 case GL_TEXTURE_4D_SGIS
:
81 firstLevel
= lastLevel
= 0;
87 /* save these values */
88 intelObj
->firstLevel
= firstLevel
;
89 intelObj
->lastLevel
= lastLevel
;
92 static GLboolean
copy_image_data_to_tree( struct intel_context
*intel
,
93 struct intel_texture_object
*intelObj
,
94 struct gl_texture_image
*texImage
,
98 return intel_miptree_image_data(intel
,
104 (texImage
->RowStride
*
106 texImage
->TexFormat
->TexelBytes
));
109 static void intel_texture_invalidate( struct intel_texture_object
*intelObj
)
111 GLint nr_faces
, face
;
112 intelObj
->dirty
= ~0;
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;
119 static void intel_texture_invalidate_cb( struct intel_context
*intel
,
122 intel_texture_invalidate( (struct intel_texture_object
*) ptr
);
125 #include "texformat.h"
126 static GLuint
intel_compressed_num_bytes(GLenum mesaFormat
)
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
:
138 case MESA_FORMAT_RGBA_DXT3
:
139 case MESA_FORMAT_RGBA_DXT5
:
151 GLuint
intel_finalize_mipmap_tree( struct intel_context
*intel
,
152 struct gl_texture_object
*tObj
)
154 struct intel_texture_object
*intelObj
= intel_texture_object(tObj
);
157 struct gl_texture_image
*firstImage
;
160 if( tObj
== intel
->frame_buffer_texobj
)
163 /* We know/require this is true by now:
165 assert(intelObj
->base
._Complete
);
167 /* What levels must the tree include at a minimum?
169 if (intelObj
->dirty
) {
170 intel_calculate_first_last_level( intelObj
);
171 /* intel_miptree_destroy(intel, intelObj->mt); */
172 /* intelObj->mt = NULL; */
175 firstImage
= intelObj
->base
.Image
[0][intelObj
->firstLevel
];
179 if (firstImage
->Border
) {
181 intel_miptree_destroy(intel
, intelObj
->mt
);
183 /* Set all images dirty:
185 intel_texture_invalidate(intelObj
);
192 if (firstImage
->IsCompressed
) {
193 cpp
= intel_compressed_num_bytes(firstImage
->TexFormat
->MesaFormat
);
195 cpp
= firstImage
->TexFormat
->TexelBytes
;
198 /* Check tree can hold all active levels. Check tree matches
199 * target, imageFormat, etc.
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
))
212 intel_miptree_destroy(intel
, intelObj
->mt
);
215 /* Set all images dirty:
217 intel_texture_invalidate(intelObj
);
221 /* May need to create a new tree:
224 intelObj
->mt
= intel_miptree_create(intel
,
225 intelObj
->base
.Target
,
226 firstImage
->InternalFormat
,
227 intelObj
->firstLevel
,
233 firstImage
->IsCompressed
);
235 /* Tell the buffer manager that we will manage the backing
236 * store, but we still want it to do fencing for us.
238 bmBufferSetInvalidateCB(intel
,
239 intelObj
->mt
->region
->buffer
,
240 intel_texture_invalidate_cb
,
245 /* Pull in any images not in the object's tree:
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
];
254 /* Need to import images in main memory or held in other trees.
256 if (intelObj
->dirty_images
[face
] & (1<<i
) &&
259 if (INTEL_DEBUG
& DEBUG_TEXTURE
)
260 _mesa_printf("copy data from image %d (%p) into object miptree\n",
264 if (!copy_image_data_to_tree(intel
,
276 /* Only clear the dirty flags if everything went ok:
278 for (face
= 0; face
< nr_faces
; face
++) {
279 intelObj
->dirty_images
[face
] = 0;