2 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
3 * Copyright © 2009 Intel Corporation
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
25 * Eric Anholt <eric@anholt.net>
29 #include "main/glheader.h"
30 #include "main/enums.h"
31 #include "main/image.h"
32 #include "main/mtypes.h"
33 #include "main/macros.h"
34 #include "main/bufferobj.h"
35 #include "main/teximage.h"
36 #include "main/texenv.h"
37 #include "main/texobj.h"
38 #include "main/texstate.h"
39 #include "main/texparam.h"
40 #include "main/varray.h"
41 #include "main/attrib.h"
42 #include "main/enable.h"
43 #include "main/buffers.h"
44 #include "main/fbobject.h"
45 #include "main/framebuffer.h"
46 #include "main/renderbuffer.h"
47 #include "main/depth.h"
48 #include "main/hash.h"
49 #include "main/mipmap.h"
50 #include "main/blend.h"
51 #include "glapi/dispatch.h"
52 #include "swrast/swrast.h"
54 #include "intel_screen.h"
55 #include "intel_context.h"
56 #include "intel_batchbuffer.h"
57 #include "intel_pixel.h"
58 #include "intel_tex.h"
59 #include "intel_mipmap_tree.h"
61 static const char *intel_fp_tex2d
=
63 "TEX result.color, fragment.texcoord[0], texture[0], 2D;\n"
67 intel_generate_mipmap_level(GLcontext
*ctx
, GLuint tex_name
,
68 int level
, int width
, int height
)
70 struct intel_context
*intel
= intel_context(ctx
);
71 GLfloat vertices
[4][2];
74 /* Set to source from the previous level */
75 _mesa_TexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_BASE_LEVEL
, level
- 1);
76 _mesa_TexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_MAX_LEVEL
, level
- 1);
78 /* Set to draw into the current level */
79 _mesa_FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT
,
80 GL_COLOR_ATTACHMENT0_EXT
,
84 /* Choose to render to the color attachment. */
85 _mesa_DrawBuffer(GL_COLOR_ATTACHMENT0_EXT
);
87 status
= _mesa_CheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT
);
88 if (status
!= GL_FRAMEBUFFER_COMPLETE_EXT
)
91 meta_set_passthrough_transform(&intel
->meta
);
93 /* XXX: Doing it right would involve setting up the transformation to do
94 * 0-1 mapping or something, and not changing the vertex data.
98 vertices
[1][0] = width
;
100 vertices
[2][0] = width
;
101 vertices
[2][1] = height
;
103 vertices
[3][1] = height
;
105 _mesa_VertexPointer(2, GL_FLOAT
, 2 * sizeof(GLfloat
), &vertices
);
106 _mesa_Enable(GL_VERTEX_ARRAY
);
107 meta_set_default_texrect(&intel
->meta
);
109 _mesa_DrawArrays(GL_TRIANGLE_FAN
, 0, 4);
111 meta_restore_texcoords(&intel
->meta
);
112 meta_restore_transform(&intel
->meta
);
118 intel_generate_mipmap_2d(GLcontext
*ctx
,
120 struct gl_texture_object
*texObj
)
122 struct intel_context
*intel
= intel_context(ctx
);
123 GLint old_active_texture
;
124 int level
, max_levels
, start_level
, end_level
;
126 GLboolean success
= GL_FALSE
;
127 struct gl_framebuffer
*saved_fbo
= NULL
;
128 struct gl_buffer_object
*saved_array_buffer
= NULL
;
129 struct gl_buffer_object
*saved_element_buffer
= NULL
;
131 _mesa_PushAttrib(GL_ENABLE_BIT
| GL_TEXTURE_BIT
|
132 GL_CURRENT_BIT
| GL_COLOR_BUFFER_BIT
|
133 GL_DEPTH_BUFFER_BIT
);
134 _mesa_PushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT
);
135 old_active_texture
= ctx
->Texture
.CurrentUnit
;
136 _mesa_reference_framebuffer(&saved_fbo
, ctx
->DrawBuffer
);
138 /* use default array/index buffers */
139 _mesa_reference_buffer_object(ctx
, &saved_array_buffer
,
140 ctx
->Array
.ArrayBufferObj
);
141 _mesa_reference_buffer_object(ctx
, &ctx
->Array
.ArrayBufferObj
,
142 ctx
->Shared
->NullBufferObj
);
143 _mesa_reference_buffer_object(ctx
, &saved_element_buffer
,
144 ctx
->Array
.ElementArrayBufferObj
);
145 _mesa_reference_buffer_object(ctx
, &ctx
->Array
.ElementArrayBufferObj
,
146 ctx
->Shared
->NullBufferObj
);
148 _mesa_Disable(GL_POLYGON_STIPPLE
);
149 _mesa_Disable(GL_DEPTH_TEST
);
150 _mesa_Disable(GL_STENCIL_TEST
);
151 _mesa_ColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
152 _mesa_DepthMask(GL_FALSE
);
154 /* Bind the given texture to GL_TEXTURE_2D with linear filtering for our
157 _mesa_ActiveTextureARB(GL_TEXTURE0_ARB
);
158 _mesa_Enable(GL_TEXTURE_2D
);
159 _mesa_BindTexture(GL_TEXTURE_2D
, texObj
->Name
);
160 _mesa_TexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
,
161 GL_LINEAR_MIPMAP_NEAREST
);
162 _mesa_TexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
164 /* Bind the new renderbuffer to the color attachment point. */
165 _mesa_GenFramebuffersEXT(1, &fb_name
);
166 _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT
, fb_name
);
168 meta_set_fragment_program(&intel
->meta
, &intel
->meta
.tex2d_fp
,
170 meta_set_passthrough_vertex_program(&intel
->meta
);
172 max_levels
= _mesa_max_texture_levels(ctx
, texObj
->Target
);
173 start_level
= texObj
->BaseLevel
;
174 end_level
= texObj
->MaxLevel
;
176 /* Loop generating level+1 from level. */
177 for (level
= start_level
; level
< end_level
&& level
< max_levels
- 1; level
++) {
178 const struct gl_texture_image
*srcImage
;
181 srcImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
182 if (srcImage
->Border
!= 0)
185 width
= srcImage
->Width
/ 2;
188 height
= srcImage
->Height
/ 2;
192 if (width
== srcImage
->Width
&&
193 height
== srcImage
->Height
) {
194 /* Neither _mesa_max_texture_levels nor texObj->MaxLevel are the
195 * maximum texture level for the object, so break out when we've gone
201 /* Make sure that there's space allocated for the target level.
202 * We could skip this if there's already space allocated and save some
205 _mesa_TexImage2D(GL_TEXTURE_2D
, level
+ 1, srcImage
->InternalFormat
,
207 GL_RGBA
, GL_UNSIGNED_INT
, NULL
);
209 if (!intel_generate_mipmap_level(ctx
, texObj
->Name
, level
+ 1,
217 meta_restore_fragment_program(&intel
->meta
);
218 meta_restore_vertex_program(&intel
->meta
);
220 /* restore array/index buffers */
221 _mesa_reference_buffer_object(ctx
, &ctx
->Array
.ArrayBufferObj
,
223 _mesa_reference_buffer_object(ctx
, &saved_array_buffer
, NULL
);
224 _mesa_reference_buffer_object(ctx
, &ctx
->Array
.ElementArrayBufferObj
,
225 saved_element_buffer
);
226 _mesa_reference_buffer_object(ctx
, &saved_element_buffer
, NULL
);
229 _mesa_DeleteFramebuffersEXT(1, &fb_name
);
230 _mesa_ActiveTextureARB(GL_TEXTURE0_ARB
+ old_active_texture
);
232 _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT
, saved_fbo
->Name
);
233 _mesa_reference_framebuffer(&saved_fbo
, NULL
);
234 _mesa_PopClientAttrib();
242 * Generate new mipmap data from BASE+1 to BASE+p (the minimally-sized mipmap
245 * The texture object's miptree must be mapped.
247 * This function should also include an accelerated path.
250 intel_generate_mipmap(GLcontext
*ctx
, GLenum target
,
251 struct gl_texture_object
*texObj
)
253 struct intel_context
*intel
= intel_context(ctx
);
254 struct intel_texture_object
*intelObj
= intel_texture_object(texObj
);
255 GLuint nr_faces
= (intelObj
->base
.Target
== GL_TEXTURE_CUBE_MAP
) ? 6 : 1;
259 if (target
== GL_TEXTURE_2D
&&
260 ctx
->Extensions
.EXT_framebuffer_object
&&
261 ctx
->Extensions
.ARB_fragment_program
&&
262 ctx
->Extensions
.ARB_vertex_program
) {
265 /* We'll be accessing this texture using GL entrypoints, which should
266 * be resilient against other access to this texture.
268 _mesa_unlock_texture(ctx
, texObj
);
269 success
= intel_generate_mipmap_2d(ctx
, target
, texObj
);
270 _mesa_lock_texture(ctx
, texObj
);
277 intel_tex_map_level_images(intel
, intelObj
, texObj
->BaseLevel
);
278 _mesa_generate_mipmap(ctx
, target
, texObj
);
279 intel_tex_unmap_level_images(intel
, intelObj
, texObj
->BaseLevel
);
281 /* Update the level information in our private data in the new images, since
282 * it didn't get set as part of a normal TexImage path.
284 for (face
= 0; face
< nr_faces
; face
++) {
285 for (i
= texObj
->BaseLevel
+ 1; i
< texObj
->MaxLevel
; i
++) {
286 struct intel_texture_image
*intelImage
;
288 intelImage
= intel_texture_image(texObj
->Image
[face
][i
]);
289 if (intelImage
== NULL
)
292 intelImage
->level
= i
;
293 intelImage
->face
= face
;
294 /* Unreference the miptree to signal that the new Data is a bare
297 intel_miptree_release(intel
, &intelImage
->mt
);