Merge commit 'origin/gallium-0.2' into gallium-master-merge
[mesa.git] / src / mesa / drivers / dri / intel / intel_clear.c
1 /**************************************************************************
2 *
3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * Copyright 2009 Intel Corporation.
5 * All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sub license, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial portions
17 * of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
23 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 *
27 **************************************************************************/
28
29 #include "main/glheader.h"
30 #include "main/enums.h"
31 #include "main/image.h"
32 #include "main/mtypes.h"
33 #include "main/attrib.h"
34 #include "main/blend.h"
35 #include "main/bufferobj.h"
36 #include "main/buffers.h"
37 #include "main/depth.h"
38 #include "main/enable.h"
39 #include "main/macros.h"
40 #include "main/matrix.h"
41 #include "main/texstate.h"
42 #include "main/stencil.h"
43 #include "main/varray.h"
44 #include "glapi/dispatch.h"
45 #include "swrast/swrast.h"
46
47 #include "intel_context.h"
48 #include "intel_blit.h"
49 #include "intel_chipset.h"
50 #include "intel_clear.h"
51 #include "intel_fbo.h"
52 #include "intel_pixel.h"
53
54 #define FILE_DEBUG_FLAG DEBUG_BLIT
55
56 /**
57 * Perform glClear where mask contains only color, depth, and/or stencil.
58 *
59 * The implementation is based on calling into Mesa to set GL state and
60 * performing normal triangle rendering. The intent of this path is to
61 * have as generic a path as possible, so that any driver could make use of
62 * it.
63 */
64 void
65 intel_clear_tris(GLcontext *ctx, GLbitfield mask)
66 {
67 struct intel_context *intel = intel_context(ctx);
68 GLfloat vertices[4][3];
69 GLfloat color[4][4];
70 GLfloat dst_z;
71 struct gl_framebuffer *fb = ctx->DrawBuffer;
72 int i;
73 GLboolean saved_fp_enable = GL_FALSE, saved_vp_enable = GL_FALSE;
74 unsigned int saved_active_texture;
75
76 assert((mask & ~(BUFFER_BIT_BACK_LEFT | BUFFER_BIT_FRONT_LEFT |
77 BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL)) == 0);
78
79 _mesa_PushAttrib(GL_COLOR_BUFFER_BIT |
80 GL_CURRENT_BIT |
81 GL_DEPTH_BUFFER_BIT |
82 GL_ENABLE_BIT |
83 GL_STENCIL_BUFFER_BIT |
84 GL_TRANSFORM_BIT |
85 GL_CURRENT_BIT);
86 _mesa_PushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
87 saved_active_texture = ctx->Texture.CurrentUnit;
88
89 /* Disable existing GL state we don't want to apply to a clear. */
90 _mesa_Disable(GL_ALPHA_TEST);
91 _mesa_Disable(GL_BLEND);
92 _mesa_Disable(GL_CULL_FACE);
93 _mesa_Disable(GL_FOG);
94 _mesa_Disable(GL_POLYGON_SMOOTH);
95 _mesa_Disable(GL_POLYGON_STIPPLE);
96 _mesa_Disable(GL_POLYGON_OFFSET_FILL);
97 _mesa_Disable(GL_LIGHTING);
98 _mesa_Disable(GL_CLIP_PLANE0);
99 _mesa_Disable(GL_CLIP_PLANE1);
100 _mesa_Disable(GL_CLIP_PLANE2);
101 _mesa_Disable(GL_CLIP_PLANE3);
102 _mesa_Disable(GL_CLIP_PLANE4);
103 _mesa_Disable(GL_CLIP_PLANE5);
104 if (ctx->Extensions.ARB_fragment_program && ctx->FragmentProgram.Enabled) {
105 saved_fp_enable = GL_TRUE;
106 _mesa_Disable(GL_FRAGMENT_PROGRAM_ARB);
107 }
108 if (ctx->Extensions.ARB_vertex_program && ctx->VertexProgram.Enabled) {
109 saved_vp_enable = GL_TRUE;
110 _mesa_Disable(GL_VERTEX_PROGRAM_ARB);
111 }
112
113 if (ctx->Texture._EnabledUnits != 0) {
114 int i;
115
116 for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
117 _mesa_ActiveTextureARB(GL_TEXTURE0 + i);
118 _mesa_Disable(GL_TEXTURE_1D);
119 _mesa_Disable(GL_TEXTURE_2D);
120 _mesa_Disable(GL_TEXTURE_3D);
121 if (ctx->Extensions.ARB_texture_cube_map)
122 _mesa_Disable(GL_TEXTURE_CUBE_MAP_ARB);
123 if (ctx->Extensions.NV_texture_rectangle)
124 _mesa_Disable(GL_TEXTURE_RECTANGLE_NV);
125 if (ctx->Extensions.MESA_texture_array) {
126 _mesa_Disable(GL_TEXTURE_1D_ARRAY_EXT);
127 _mesa_Disable(GL_TEXTURE_2D_ARRAY_EXT);
128 }
129 }
130 }
131
132 intel_meta_set_passthrough_transform(intel);
133
134 for (i = 0; i < 4; i++) {
135 color[i][0] = ctx->Color.ClearColor[0];
136 color[i][1] = ctx->Color.ClearColor[1];
137 color[i][2] = ctx->Color.ClearColor[2];
138 color[i][3] = ctx->Color.ClearColor[3];
139 }
140
141 /* convert clear Z from [0,1] to NDC coord in [-1,1] */
142 dst_z = -1.0 + 2.0 * ctx->Depth.Clear;
143
144 /* Prepare the vertices, which are the same regardless of which buffer we're
145 * drawing to.
146 */
147 vertices[0][0] = fb->_Xmin;
148 vertices[0][1] = fb->_Ymin;
149 vertices[0][2] = dst_z;
150 vertices[1][0] = fb->_Xmax;
151 vertices[1][1] = fb->_Ymin;
152 vertices[1][2] = dst_z;
153 vertices[2][0] = fb->_Xmax;
154 vertices[2][1] = fb->_Ymax;
155 vertices[2][2] = dst_z;
156 vertices[3][0] = fb->_Xmin;
157 vertices[3][1] = fb->_Ymax;
158 vertices[3][2] = dst_z;
159
160 _mesa_ColorPointer(4, GL_FLOAT, 4 * sizeof(GLfloat), &color);
161 _mesa_VertexPointer(3, GL_FLOAT, 3 * sizeof(GLfloat), &vertices);
162 _mesa_Enable(GL_COLOR_ARRAY);
163 _mesa_Enable(GL_VERTEX_ARRAY);
164
165 while (mask != 0) {
166 GLuint this_mask = 0;
167
168 if (mask & BUFFER_BIT_BACK_LEFT)
169 this_mask = BUFFER_BIT_BACK_LEFT;
170 else if (mask & BUFFER_BIT_FRONT_LEFT)
171 this_mask = BUFFER_BIT_FRONT_LEFT;
172
173 /* Clear depth/stencil in the same pass as color. */
174 this_mask |= (mask & (BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL));
175
176 /* Select the current color buffer and use the color write mask if
177 * we have one, otherwise don't write any color channels.
178 */
179 if (this_mask & BUFFER_BIT_FRONT_LEFT)
180 _mesa_DrawBuffer(GL_FRONT_LEFT);
181 else if (this_mask & BUFFER_BIT_BACK_LEFT)
182 _mesa_DrawBuffer(GL_BACK_LEFT);
183 else
184 _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
185
186 /* Control writing of the depth clear value to depth. */
187 if (this_mask & BUFFER_BIT_DEPTH) {
188 _mesa_DepthFunc(GL_ALWAYS);
189 _mesa_Enable(GL_DEPTH_TEST);
190 } else {
191 _mesa_Disable(GL_DEPTH_TEST);
192 _mesa_DepthMask(GL_FALSE);
193 }
194
195 /* Control writing of the stencil clear value to stencil. */
196 if (this_mask & BUFFER_BIT_STENCIL) {
197 _mesa_Enable(GL_STENCIL_TEST);
198 _mesa_StencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
199 _mesa_StencilFuncSeparate(GL_FRONT, GL_ALWAYS, ctx->Stencil.Clear,
200 ctx->Stencil.WriteMask[0]);
201 } else {
202 _mesa_Disable(GL_STENCIL_TEST);
203 }
204
205 CALL_DrawArrays(ctx->Exec, (GL_TRIANGLE_FAN, 0, 4));
206
207 mask &= ~this_mask;
208 }
209
210 intel_meta_restore_transform(intel);
211
212 _mesa_ActiveTextureARB(GL_TEXTURE0 + saved_active_texture);
213 if (saved_fp_enable)
214 _mesa_Enable(GL_FRAGMENT_PROGRAM_ARB);
215 if (saved_vp_enable)
216 _mesa_Enable(GL_VERTEX_PROGRAM_ARB);
217
218 _mesa_PopClientAttrib();
219 _mesa_PopAttrib();
220 }
221
222 static const char *buffer_names[] = {
223 [BUFFER_FRONT_LEFT] = "front",
224 [BUFFER_BACK_LEFT] = "back",
225 [BUFFER_FRONT_RIGHT] = "front right",
226 [BUFFER_BACK_RIGHT] = "back right",
227 [BUFFER_AUX0] = "aux0",
228 [BUFFER_AUX1] = "aux1",
229 [BUFFER_AUX2] = "aux2",
230 [BUFFER_AUX3] = "aux3",
231 [BUFFER_DEPTH] = "depth",
232 [BUFFER_STENCIL] = "stencil",
233 [BUFFER_ACCUM] = "accum",
234 [BUFFER_COLOR0] = "color0",
235 [BUFFER_COLOR1] = "color1",
236 [BUFFER_COLOR2] = "color2",
237 [BUFFER_COLOR3] = "color3",
238 [BUFFER_COLOR4] = "color4",
239 [BUFFER_COLOR5] = "color5",
240 [BUFFER_COLOR6] = "color6",
241 [BUFFER_COLOR7] = "color7",
242 };
243
244 /**
245 * Called by ctx->Driver.Clear.
246 */
247 static void
248 intelClear(GLcontext *ctx, GLbitfield mask)
249 {
250 struct intel_context *intel = intel_context(ctx);
251 const GLuint colorMask = *((GLuint *) & ctx->Color.ColorMask);
252 GLbitfield tri_mask = 0;
253 GLbitfield blit_mask = 0;
254 GLbitfield swrast_mask = 0;
255 struct gl_framebuffer *fb = ctx->DrawBuffer;
256 GLuint i;
257
258 if (0)
259 fprintf(stderr, "%s\n", __FUNCTION__);
260
261 /* HW color buffers (front, back, aux, generic FBO, etc) */
262 if (colorMask == ~0) {
263 /* clear all R,G,B,A */
264 /* XXX FBO: need to check if colorbuffers are software RBOs! */
265 blit_mask |= (mask & BUFFER_BITS_COLOR);
266 }
267 else {
268 /* glColorMask in effect */
269 tri_mask |= (mask & BUFFER_BITS_COLOR);
270 }
271
272 /* HW stencil */
273 if (mask & BUFFER_BIT_STENCIL) {
274 const struct intel_region *stencilRegion
275 = intel_get_rb_region(fb, BUFFER_STENCIL);
276 if (stencilRegion) {
277 /* have hw stencil */
278 if (IS_965(intel->intelScreen->deviceID) ||
279 (ctx->Stencil.WriteMask[0] & 0xff) != 0xff) {
280 /* We have to use the 3D engine if we're clearing a partial mask
281 * of the stencil buffer, or if we're on a 965 which has a tiled
282 * depth/stencil buffer in a layout we can't blit to.
283 */
284 tri_mask |= BUFFER_BIT_STENCIL;
285 }
286 else {
287 /* clearing all stencil bits, use blitting */
288 blit_mask |= BUFFER_BIT_STENCIL;
289 }
290 }
291 }
292
293 /* HW depth */
294 if (mask & BUFFER_BIT_DEPTH) {
295 /* clear depth with whatever method is used for stencil (see above) */
296 if (IS_965(intel->intelScreen->deviceID) ||
297 tri_mask & BUFFER_BIT_STENCIL)
298 tri_mask |= BUFFER_BIT_DEPTH;
299 else
300 blit_mask |= BUFFER_BIT_DEPTH;
301 }
302
303 /* If we're doing a tri pass for depth/stencil, include a likely color
304 * buffer with it.
305 */
306 if (mask & (BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL)) {
307 tri_mask |= blit_mask & BUFFER_BIT_BACK_LEFT;
308 blit_mask &= ~BUFFER_BIT_BACK_LEFT;
309 }
310
311 /* SW fallback clearing */
312 swrast_mask = mask & ~tri_mask & ~blit_mask;
313
314 for (i = 0; i < BUFFER_COUNT; i++) {
315 GLuint bufBit = 1 << i;
316 if ((blit_mask | tri_mask) & bufBit) {
317 if (!fb->Attachment[i].Renderbuffer->ClassID) {
318 blit_mask &= ~bufBit;
319 tri_mask &= ~bufBit;
320 swrast_mask |= bufBit;
321 }
322 }
323 }
324
325 if (blit_mask) {
326 if (INTEL_DEBUG & DEBUG_BLIT) {
327 DBG("blit clear:");
328 for (i = 0; i < BUFFER_COUNT; i++) {
329 if (blit_mask & (1 << i))
330 DBG(" %s", buffer_names[i]);
331 }
332 DBG("\n");
333 }
334 intelClearWithBlit(ctx, blit_mask);
335 }
336
337 if (tri_mask) {
338 if (INTEL_DEBUG & DEBUG_BLIT) {
339 DBG("tri clear:");
340 for (i = 0; i < BUFFER_COUNT; i++) {
341 if (tri_mask & (1 << i))
342 DBG(" %s", buffer_names[i]);
343 }
344 DBG("\n");
345 }
346 intel_clear_tris(ctx, tri_mask);
347 }
348
349 if (swrast_mask) {
350 if (INTEL_DEBUG & DEBUG_BLIT) {
351 DBG("swrast clear:");
352 for (i = 0; i < BUFFER_COUNT; i++) {
353 if (swrast_mask & (1 << i))
354 DBG(" %s", buffer_names[i]);
355 }
356 DBG("\n");
357 }
358 _swrast_Clear(ctx, swrast_mask);
359 }
360 }
361
362
363 void
364 intelInitClearFuncs(struct dd_function_table *functions)
365 {
366 functions->Clear = intelClear;
367 }