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