Merge commit 'origin/gallium-0.1' into gallium-0.2
[mesa.git] / src / mesa / drivers / dri / sis / sis_clear.c
1 /**************************************************************************
2
3 Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
4 Copyright 2003 Eric Anholt
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 "Software"),
9 to deal in the Software without restriction, including without limitation
10 on the rights to use, copy, modify, merge, publish, distribute, sub
11 license, and/or sell copies of the Software, and to permit persons to whom
12 the Software is furnished to do so, subject to the following conditions:
13
14 The above copyright notice and this permission notice (including the next
15 paragraph) shall be included in all copies or substantial portions of the
16 Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
22 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 USE OR OTHER DEALINGS IN THE SOFTWARE.
25
26 **************************************************************************/
27
28 /*
29 * Authors:
30 * Sung-Ching Lin <sclin@sis.com.tw>
31 * Eric Anholt <anholt@FreeBSD.org>
32 */
33
34 #include "sis_context.h"
35 #include "sis_state.h"
36 #include "sis_lock.h"
37
38 #include "swrast/swrast.h"
39 #include "main/macros.h"
40
41 static GLbitfield sis_3D_Clear( GLcontext * ctx, GLbitfield mask,
42 GLint x, GLint y, GLint width,
43 GLint height );
44 static void sis_clear_color_buffer( GLcontext *ctx, GLenum mask, GLint x,
45 GLint y, GLint width, GLint height );
46 static void sis_clear_z_stencil_buffer( GLcontext * ctx,
47 GLbitfield mask, GLint x,
48 GLint y, GLint width,
49 GLint height );
50
51 static void
52 set_color_pattern( sisContextPtr smesa, GLubyte red, GLubyte green,
53 GLubyte blue, GLubyte alpha )
54 {
55 /* XXX only RGB565 and ARGB8888 */
56 switch (smesa->colorFormat)
57 {
58 case DST_FORMAT_ARGB_8888:
59 smesa->clearColorPattern = (alpha << 24) +
60 (red << 16) + (green << 8) + (blue);
61 break;
62 case DST_FORMAT_RGB_565:
63 smesa->clearColorPattern = ((red >> 3) << 11) +
64 ((green >> 2) << 5) + (blue >> 3);
65 smesa->clearColorPattern |= smesa->clearColorPattern << 16;
66 break;
67 default:
68 sis_fatal_error("Bad dst color format\n");
69 }
70 }
71
72 void
73 sisUpdateZStencilPattern( sisContextPtr smesa, GLclampd z, GLint stencil )
74 {
75 GLuint zPattern;
76
77 switch (smesa->zFormat)
78 {
79 case SiS_ZFORMAT_Z16:
80 CLAMPED_FLOAT_TO_USHORT(zPattern, z);
81 zPattern |= zPattern << 16;
82 break;
83 case SiS_ZFORMAT_S8Z24:
84 zPattern = FLOAT_TO_UINT(z) >> 8;
85 zPattern |= stencil << 24;
86 break;
87 case SiS_ZFORMAT_Z32:
88 zPattern = FLOAT_TO_UINT(z);
89 break;
90 default:
91 sis_fatal_error("Bad Z format\n");
92 }
93 smesa->clearZStencilPattern = zPattern;
94 }
95
96 void
97 sisDDClear( GLcontext * ctx, GLbitfield mask )
98 {
99 sisContextPtr smesa = SIS_CONTEXT(ctx);
100
101 GLint x1, y1, width1, height1;
102
103 /* get region after locking: */
104 x1 = ctx->DrawBuffer->_Xmin;
105 y1 = ctx->DrawBuffer->_Ymin;
106 width1 = ctx->DrawBuffer->_Xmax - x1;
107 height1 = ctx->DrawBuffer->_Ymax - y1;
108 y1 = Y_FLIP(y1 + height1 - 1);
109
110 /* Mask out any non-existent buffers */
111 if (ctx->Visual.depthBits == 0 || !ctx->Depth.Mask)
112 mask &= ~BUFFER_BIT_DEPTH;
113 if (ctx->Visual.stencilBits == 0)
114 mask &= ~BUFFER_BIT_STENCIL;
115
116 LOCK_HARDWARE();
117
118 /* The 3d clear code is use for masked clears because apparently the SiS
119 * 300-series can't do write masks for 2d blits. 3d isn't used in general
120 * because it's slower, even in the case of clearing multiple buffers.
121 */
122 /* XXX: Appears to be broken with stencil. */
123 if ((smesa->current.hwCapEnable2 & (MASK_AlphaMaskWriteEnable |
124 MASK_ColorMaskWriteEnable) &&
125 (mask & (BUFFER_BIT_BACK_LEFT | BUFFER_BIT_FRONT_LEFT)) != 0) ||
126 ((ctx->Stencil.WriteMask[0] & 0xff) != 0xff &&
127 (mask & BUFFER_BIT_STENCIL) != 0) )
128 {
129 mask = sis_3D_Clear( ctx, mask, x1, y1, width1, height1 );
130 }
131
132 if ( mask & BUFFER_BIT_FRONT_LEFT || mask & BUFFER_BIT_BACK_LEFT) {
133 sis_clear_color_buffer( ctx, mask, x1, y1, width1, height1 );
134 mask &= ~(BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT);
135 }
136
137 if (mask & (BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL)) {
138 if (smesa->depth.offset != 0)
139 sis_clear_z_stencil_buffer( ctx, mask, x1, y1, width1, height1 );
140 mask &= ~(BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL);
141 }
142
143 UNLOCK_HARDWARE();
144
145 if (mask != 0)
146 _swrast_Clear( ctx, mask);
147 }
148
149
150 void
151 sisDDClearColor( GLcontext * ctx, const GLfloat color[4] )
152 {
153 sisContextPtr smesa = SIS_CONTEXT(ctx);
154 GLubyte c[4];
155
156 CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]);
157 CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]);
158 CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]);
159 CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]);
160
161 set_color_pattern( smesa, c[0], c[1], c[2], c[3] );
162 }
163
164 void
165 sisDDClearDepth( GLcontext * ctx, GLclampd d )
166 {
167 sisContextPtr smesa = SIS_CONTEXT(ctx);
168
169 sisUpdateZStencilPattern( smesa, d, ctx->Stencil.Clear );
170 }
171
172 void
173 sisDDClearStencil( GLcontext * ctx, GLint s )
174 {
175 sisContextPtr smesa = SIS_CONTEXT(ctx);
176
177 sisUpdateZStencilPattern( smesa, ctx->Depth.Clear, s );
178 }
179
180 static GLbitfield
181 sis_3D_Clear( GLcontext * ctx, GLbitfield mask,
182 GLint x, GLint y, GLint width, GLint height )
183 {
184 sisContextPtr smesa = SIS_CONTEXT(ctx);
185
186 __GLSiSHardware *current = &smesa->current;
187
188 float left, top, right, bottom, zClearVal;
189 GLboolean bClrColor, bClrDepth, bClrStencil;
190 GLint dwPrimitiveSet;
191 GLint dwEnable1 = 0, dwEnable2 = MASK_ColorMaskWriteEnable;
192 GLint dwDepthMask = 0, dwSten1 = 0, dwSten2 = 0;
193 GLint dirtyflags = GFLAG_ENABLESETTING | GFLAG_ENABLESETTING2 |
194 GFLAG_CLIPPING | GFLAG_DESTSETTING;
195 int count;
196 drm_clip_rect_t *pExtents;
197
198 bClrColor = (mask & (BUFFER_BIT_BACK_LEFT | BUFFER_BIT_FRONT_LEFT)) != 0;
199 bClrDepth = (mask & BUFFER_BIT_DEPTH) != 0;
200 bClrStencil = (mask & BUFFER_BIT_STENCIL) != 0;
201
202 if (smesa->GlobalFlag & GFLAG_RENDER_STATES)
203 sis_update_render_state( smesa );
204
205 if (bClrStencil) {
206 dwSten1 = STENCIL_FORMAT_8 | SiS_STENCIL_ALWAYS |
207 ((ctx->Stencil.Clear & 0xff) << 8) | 0xff;
208 dwSten2 = SiS_SFAIL_REPLACE | SiS_SPASS_ZFAIL_REPLACE |
209 SiS_SPASS_ZPASS_REPLACE;
210 dwEnable1 = MASK_ZWriteEnable | MASK_StencilWriteEnable |
211 MASK_StencilTestEnable;
212 dwEnable2 |= MASK_ZMaskWriteEnable;
213 dwDepthMask |= (ctx->Stencil.WriteMask[0] & 0xff) << 24;
214 } else if (bClrDepth) {
215 dwEnable1 = MASK_ZWriteEnable;
216 dwEnable2 |= MASK_ZMaskWriteEnable;
217 }
218
219 if (bClrDepth) {
220 zClearVal = ctx->Depth.Clear;
221 if (ctx->Visual.depthBits != 32)
222 dwDepthMask |= 0x00ffffff;
223 else
224 dwDepthMask = 0xffffffff;
225 } else
226 zClearVal = 0.0;
227
228 mWait3DCmdQueue(9);
229 MMIO(REG_3D_TEnable, dwEnable1);
230 MMIO(REG_3D_TEnable2, dwEnable2);
231 if (bClrDepth || bClrStencil) {
232 MMIO(REG_3D_ZSet, (current->hwZ & ~MASK_ZTestMode) | SiS_Z_COMP_ALWAYS);
233 dirtyflags |= GFLAG_ZSETTING;
234 }
235 if (bClrColor) {
236 MMIO(REG_3D_DstSet, (current->hwDstSet & ~MASK_ROP2) | LOP_COPY);
237 } else {
238 MMIO(REG_3D_DstAlphaWriteMask, 0L);
239 }
240 if (bClrStencil) {
241 MMIO(REG_3D_StencilSet, dwSten1);
242 MMIO(REG_3D_StencilSet2, dwSten2);
243 dirtyflags |= GFLAG_STENCILSETTING;
244 }
245
246 if (mask & BUFFER_BIT_FRONT_LEFT) {
247 pExtents = smesa->driDrawable->pClipRects;
248 count = smesa->driDrawable->numClipRects;
249 } else {
250 pExtents = NULL;
251 count = 1;
252 }
253
254 while(count--) {
255 left = x;
256 right = x + width;
257 top = y;
258 bottom = y + height;
259
260 if (pExtents != NULL) {
261 GLuint x1, y1, x2, y2;
262
263 x1 = pExtents->x1 - smesa->driDrawable->x;
264 y1 = pExtents->y1 - smesa->driDrawable->y;
265 x2 = pExtents->x2 - smesa->driDrawable->x - 1;
266 y2 = pExtents->y2 - smesa->driDrawable->y - 1;
267
268 left = (left > x1) ? left : x1;
269 right = (right > x2) ? x2 : right;
270 top = (top > y1) ? top : y1;
271 bottom = (bottom > y2) ? y2 : bottom;
272 pExtents++;
273 if (left > right || top > bottom)
274 continue;
275 }
276
277 mWait3DCmdQueue(20);
278
279 MMIO(REG_3D_ClipTopBottom, ((GLint)top << 13) | (GLint)bottom);
280 MMIO(REG_3D_ClipLeftRight, ((GLint)left << 13) | (GLint)right);
281
282 /* the first triangle */
283 dwPrimitiveSet = OP_3D_TRIANGLE_DRAW | OP_3D_FIRE_TSARGBc |
284 SHADE_FLAT_VertexC;
285 MMIO(REG_3D_PrimitiveSet, dwPrimitiveSet);
286
287 MMIO(REG_3D_TSZa, *(GLint *) &zClearVal);
288 MMIO(REG_3D_TSXa, *(GLint *) &right);
289 MMIO(REG_3D_TSYa, *(GLint *) &top);
290 MMIO(REG_3D_TSARGBa, smesa->clearColorPattern);
291
292 MMIO(REG_3D_TSZb, *(GLint *) &zClearVal);
293 MMIO(REG_3D_TSXb, *(GLint *) &left);
294 MMIO(REG_3D_TSYb, *(GLint *) &top);
295 MMIO(REG_3D_TSARGBb, smesa->clearColorPattern);
296
297 MMIO(REG_3D_TSZc, *(GLint *) &zClearVal);
298 MMIO(REG_3D_TSXc, *(GLint *) &left);
299 MMIO(REG_3D_TSYc, *(GLint *) &bottom);
300 MMIO(REG_3D_TSARGBc, smesa->clearColorPattern);
301
302 /* second triangle */
303 dwPrimitiveSet = OP_3D_TRIANGLE_DRAW | OP_3D_FIRE_TSARGBb |
304 SHADE_FLAT_VertexB;
305 MMIO(REG_3D_PrimitiveSet, dwPrimitiveSet);
306
307 MMIO(REG_3D_TSZb, *(GLint *) &zClearVal);
308 MMIO(REG_3D_TSXb, *(GLint *) &right);
309 MMIO(REG_3D_TSYb, *(GLint *) &bottom);
310 MMIO(REG_3D_TSARGBb, smesa->clearColorPattern);
311 }
312
313 mEndPrimitive();
314
315 /* If BUFFER_BIT_FRONT_LEFT is set, we've only cleared the front buffer so far */
316 if ((mask & BUFFER_BIT_FRONT_LEFT) != 0 && (mask & BUFFER_BIT_BACK_LEFT) != 0)
317 sis_3D_Clear( ctx, BUFFER_BIT_BACK_LEFT, x, y, width, height );
318
319 smesa->GlobalFlag |= dirtyflags;
320
321 return mask & ~(BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL | BUFFER_BIT_BACK_LEFT |
322 BUFFER_BIT_FRONT_LEFT);
323 }
324
325 static void
326 sis_clear_color_buffer( GLcontext *ctx, GLenum mask, GLint x, GLint y,
327 GLint width, GLint height )
328 {
329 sisContextPtr smesa = SIS_CONTEXT(ctx);
330 int count;
331 drm_clip_rect_t *pExtents = NULL;
332 GLint xx, yy;
333 GLint x0, y0, width0, height0;
334
335 /* Clear back buffer */
336 if (mask & BUFFER_BIT_BACK_LEFT) {
337 mWait3DCmdQueue (8);
338 MMIO(REG_SRC_PITCH, (smesa->bytesPerPixel == 4) ?
339 BLIT_DEPTH_32 : BLIT_DEPTH_16);
340 MMIO(REG_DST_X_Y, (x << 16) | y);
341 MMIO(REG_DST_ADDR, smesa->back.offset);
342 MMIO(REG_DST_PITCH_HEIGHT, (smesa->virtualY << 16) | smesa->back.pitch);
343 MMIO(REG_WIDTH_HEIGHT, (height << 16) | width);
344 MMIO(REG_PATFG, smesa->clearColorPattern);
345 MMIO(REG_BLIT_CMD, CMD_DIR_X_INC | CMD_DIR_Y_INC | CMD_ROP_PAT);
346 MMIO(REG_CommandQueue, -1);
347 }
348
349 if ((mask & BUFFER_BIT_FRONT_LEFT) == 0)
350 return;
351
352 /* Clear front buffer */
353 x0 = x;
354 y0 = y;
355 width0 = width;
356 height0 = height;
357
358 pExtents = smesa->driDrawable->pClipRects;
359 count = smesa->driDrawable->numClipRects;
360
361 while (count--) {
362 GLint x2 = pExtents->x1 - smesa->driDrawable->x;
363 GLint y2 = pExtents->y1 - smesa->driDrawable->y;
364 GLint xx2 = pExtents->x2 - smesa->driDrawable->x;
365 GLint yy2 = pExtents->y2 - smesa->driDrawable->y;
366
367 x = (x0 > x2) ? x0 : x2;
368 y = (y0 > y2) ? y0 : y2;
369 xx = ((x0 + width0) > (xx2)) ? xx2 : x0 + width0;
370 yy = ((y0 + height0) > (yy2)) ? yy2 : y0 + height0;
371 width = xx - x;
372 height = yy - y;
373 pExtents++;
374
375 if (width <= 0 || height <= 0)
376 continue;
377
378 mWait3DCmdQueue (8);
379 MMIO(REG_SRC_PITCH, (smesa->bytesPerPixel == 4) ?
380 BLIT_DEPTH_32 : BLIT_DEPTH_16);
381 MMIO(REG_DST_X_Y, (x << 16) | y);
382 MMIO(REG_DST_ADDR, smesa->front.offset);
383 MMIO(REG_DST_PITCH_HEIGHT, (smesa->virtualY << 16) | smesa->front.pitch);
384 MMIO(REG_WIDTH_HEIGHT, (height << 16) | width);
385 MMIO(REG_PATFG, smesa->clearColorPattern);
386 MMIO(REG_BLIT_CMD, CMD_DIR_X_INC | CMD_DIR_Y_INC | CMD_ROP_PAT);
387 MMIO(REG_CommandQueue, -1);
388 }
389 }
390
391 static void
392 sis_clear_z_stencil_buffer( GLcontext * ctx, GLbitfield mask,
393 GLint x, GLint y, GLint width, GLint height )
394 {
395 sisContextPtr smesa = SIS_CONTEXT(ctx);
396 int cmd;
397
398 mWait3DCmdQueue (8);
399 MMIO(REG_SRC_PITCH, (smesa->zFormat == SiS_ZFORMAT_Z16) ?
400 BLIT_DEPTH_16 : BLIT_DEPTH_32);
401 MMIO(REG_DST_X_Y, (x << 16) | y);
402 MMIO(REG_DST_ADDR, smesa->depth.offset);
403 MMIO(REG_DST_PITCH_HEIGHT, (smesa->virtualY << 16) | smesa->depth.pitch);
404 MMIO(REG_WIDTH_HEIGHT, (height << 16) | width);
405 MMIO(REG_PATFG, smesa->clearZStencilPattern);
406 MMIO(REG_BLIT_CMD, CMD_DIR_X_INC | CMD_DIR_Y_INC | CMD_ROP_PAT);
407 MMIO(REG_CommandQueue, -1);
408 }
409