2506cd5a37bc982ffba4a6dcfa99cf24184440f1
[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 ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS 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 #include "macros.h"
39 #include "swrast/swrast.h"
40
41 #if 0
42 static GLbitfield sis_3D_Clear( GLcontext * ctx, GLbitfield mask,
43 GLint x, GLint y, GLint width,
44 GLint height );
45 #endif
46 static void sis_clear_color_buffer( GLcontext *ctx, GLenum mask, GLint x,
47 GLint y, GLint width, GLint height );
48 static void sis_clear_z_stencil_buffer( GLcontext * ctx,
49 GLbitfield mask, GLint x,
50 GLint y, GLint width,
51 GLint height );
52
53 static void
54 set_color_pattern( sisContextPtr smesa, GLubyte red, GLubyte green,
55 GLubyte blue, GLubyte alpha )
56 {
57 /* XXX only RGB565 and ARGB8888 */
58 switch (GET_ColorFormat(smesa))
59 {
60 case DST_FORMAT_ARGB_8888:
61 smesa->clearColorPattern = (alpha << 24) +
62 (red << 16) + (green << 8) + (blue);
63 break;
64 case DST_FORMAT_RGB_565:
65 smesa->clearColorPattern = ((red >> 3) << 11) +
66 ((green >> 2) << 5) + (blue >> 3);
67 smesa->clearColorPattern |= smesa->clearColorPattern << 16;
68 break;
69 default:
70 assert(0);
71 }
72 }
73
74 void
75 sisUpdateZStencilPattern( sisContextPtr smesa, GLclampd z, GLint stencil )
76 {
77 GLuint zPattern;
78
79 if (z <= 0.0f)
80 zPattern = 0x0;
81 else if (z >= 1.0f)
82 zPattern = 0xFFFFFFFF;
83 else
84 zPattern = doFPtoFixedNoRound( z, 32 );
85
86 switch (smesa->zFormat)
87 {
88 case SiS_ZFORMAT_Z16:
89 zPattern = zPattern >> 16;
90 zPattern |= zPattern << 16;
91 break;
92 case SiS_ZFORMAT_S8Z24:
93 zPattern = zPattern >> 8;
94 zPattern |= stencil << 24;
95 break;
96 case SiS_ZFORMAT_Z32:
97 break;
98 default:
99 assert(0);
100 }
101 smesa->clearZStencilPattern = zPattern;
102 }
103
104 void
105 sisDDClear( GLcontext * ctx, GLbitfield mask, GLboolean all,
106 GLint x, GLint y, GLint width, GLint height )
107 {
108 sisContextPtr smesa = SIS_CONTEXT(ctx);
109
110 GLint x1, y1, width1, height1;
111
112 if (all) {
113 GLframebuffer *buffer = ctx->DrawBuffer;
114
115 x1 = 0;
116 y1 = 0;
117 width1 = buffer->Width;
118 height1 = buffer->Height;
119 } else {
120 x1 = x;
121 y1 = Y_FLIP(y+height-1);
122 width1 = width;
123 height1 = height;
124 }
125
126 LOCK_HARDWARE();
127
128 #if 0
129 /* The 3d clear code is disabled because it appears to be slower, even
130 * in the case of being requested to clear Z and color buffers at the
131 * same time.
132 */
133 if (mask & (DD_BACK_LEFT_BIT | DD_DEPTH_BIT | DD_STENCIL_BIT))
134 {
135 /* only Clear either depth or stencil buffer */
136 mask = sis_3D_Clear( ctx, mask, x1, y1, width1, height1 );
137 }
138 #endif
139
140 if ( mask & DD_FRONT_LEFT_BIT || mask & DD_BACK_LEFT_BIT) {
141 sis_clear_color_buffer( ctx, mask, x1, y1, width1, height1 );
142 mask &= ~(DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT);
143 }
144
145 if (mask & (DD_DEPTH_BIT | DD_STENCIL_BIT)) {
146 if (smesa->depthbuffer != NULL)
147 sis_clear_z_stencil_buffer( ctx, mask, x1, y1, width1, height1 );
148 mask &= ~(DD_DEPTH_BIT | DD_STENCIL_BIT);
149 }
150
151 UNLOCK_HARDWARE();
152
153 if (mask != 0)
154 _swrast_Clear( ctx, mask, all, x1, y1, width, height );
155 }
156
157
158 void
159 sisDDClearColor( GLcontext * ctx, const GLfloat color[4] )
160 {
161 sisContextPtr smesa = SIS_CONTEXT(ctx);
162 GLubyte c[4];
163
164 CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]);
165 CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]);
166 CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]);
167 CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]);
168
169 set_color_pattern( smesa, c[0], c[1], c[2], c[3] );
170 }
171
172 void
173 sisDDClearDepth( GLcontext * ctx, GLclampd d )
174 {
175 sisContextPtr smesa = SIS_CONTEXT(ctx);
176
177 sisUpdateZStencilPattern( smesa, d, ctx->Stencil.Clear );
178 }
179
180 void
181 sisDDClearStencil( GLcontext * ctx, GLint s )
182 {
183 sisContextPtr smesa = SIS_CONTEXT(ctx);
184
185 sisUpdateZStencilPattern( smesa, ctx->Depth.Clear, s );
186 }
187
188 #if 0
189 static GLbitfield
190 sis_3D_Clear( GLcontext * ctx, GLbitfield mask,
191 GLint x, GLint y, GLint width, GLint height )
192 {
193 sisContextPtr smesa = SIS_CONTEXT(ctx);
194
195 __GLSiSHardware *current = &smesa->current;
196
197 float left, top, right, bottom, zClearVal;
198 GLboolean bClrColor, bClrDepth, bClrStencil;
199 GLint dwPrimitiveSet;
200 GLint dwEnable1 = 0, dwEnable2 = 0, dwDepthMask = 0, dwSten1 = 0, dwSten2 = 0;
201 GLint dirtyflags = GFLAG_ENABLESETTING | GFLAG_ENABLESETTING2 |
202 GFLAG_CLIPPING | GFLAG_DESTSETTING;
203
204 int count;
205 XF86DRIClipRectPtr pExtents;
206
207 bClrColor = ((mask & DD_BACK_LEFT_BIT) != 0);
208 bClrDepth = ((mask & DD_DEPTH_BIT) != 0) && (ctx->Visual.depthBits != 0);
209 bClrStencil = ((mask & DD_STENCIL_BIT) != 0) && (ctx->Visual.stencilBits != 0);
210
211 if (smesa->GlobalFlag & GFLAG_RENDER_STATES)
212 sis_update_render_state( smesa );
213
214 if (!bClrColor)
215 dwEnable2 |= MASK_ColorMaskWriteEnable;
216
217 if (bClrStencil) {
218 dwSten1 = STENCIL_FORMAT_8 | SiS_STENCIL_ALWAYS |
219 (ctx->Stencil.Clear << 8) | 0xff;
220 dwSten2 = SiS_SFAIL_REPLACE | SiS_SPASS_ZFAIL_REPLACE |
221 SiS_SPASS_ZPASS_REPLACE;
222 dwEnable1 = MASK_ZWriteEnable | MASK_StencilTestEnable;
223 dwEnable2 |= MASK_ZMaskWriteEnable;
224 dwDepthMask |= ctx->Stencil.WriteMask[0] << 24;
225 } else if (bClrDepth) {
226 dwEnable1 = MASK_ZWriteEnable;
227 dwEnable2 |= MASK_ZMaskWriteEnable;
228 }
229
230 if (bClrDepth) {
231 zClearVal = ctx->Depth.Clear;
232 if (ctx->Visual.depthBits != 32)
233 dwDepthMask |= 0x00ffffff;
234 else
235 dwDepthMask = 0xffffffff;
236 } else
237 zClearVal = 0.0;
238
239 mWait3DCmdQueue(9);
240 MMIO(REG_3D_TEnable, dwEnable1);
241 MMIO(REG_3D_TEnable2, dwEnable2);
242 if (bClrDepth || bClrStencil) {
243 MMIO(REG_3D_ZSet, (current->hwZ & ~MASK_ZTestMode) | SiS_Z_COMP_ALWAYS);
244 dirtyflags |= GFLAG_ZSETTING;
245 }
246 if (bClrColor) {
247 MMIO(REG_3D_DstSet, (current->hwDstSet & ~MASK_ROP2) | LOP_COPY);
248 } else {
249 MMIO(REG_3D_DstAlphaWriteMask, 0L);
250 }
251 if (bClrStencil) {
252 MMIO(REG_3D_StencilSet, dwSten1);
253 MMIO(REG_3D_StencilSet2, dwSten2);
254 dirtyflags |= GFLAG_STENCILSETTING;
255 }
256
257 if (mask & DD_FRONT_LEFT_BIT) {
258 pExtents = smesa->driDrawable->pClipRects;
259 count = smesa->driDrawable->numClipRects;
260 } else {
261 pExtents = NULL;
262 count = 1;
263 }
264
265 while(count--) {
266 left = x;
267 right = x + width;
268 top = y;
269 bottom = y + height;
270
271 if (pExtents != NULL) {
272 GLuint x1, y1, x2, y2;
273
274 x1 = pExtents->x1 - smesa->driDrawable->x;
275 y1 = pExtents->y1 - smesa->driDrawable->y;
276 x2 = pExtents->x2 - smesa->driDrawable->x - 1;
277 y2 = pExtents->y2 - smesa->driDrawable->y - 1;
278
279 left = (left > x1) ? left : x1;
280 right = (right > x2) ? x2 : right;
281 top = (top > y1) ? top : y1;
282 bottom = (bottom > y2) ? y2 : bottom;
283 pExtents++;
284 if (left > right || top > bottom)
285 continue;
286 }
287
288 mWait3DCmdQueue(20);
289
290 MMIO(REG_3D_ClipTopBottom, ((GLint)top << 13) | (GLint)bottom);
291 MMIO(REG_3D_ClipLeftRight, ((GLint)left << 13) | (GLint)right);
292
293 /* the first triangle */
294 dwPrimitiveSet = OP_3D_TRIANGLE_DRAW | OP_3D_FIRE_TSARGBc |
295 SHADE_FLAT_VertexC;
296 MMIO(REG_3D_PrimitiveSet, dwPrimitiveSet);
297
298 MMIO(REG_3D_TSZa, *(GLint *) &zClearVal);
299 MMIO(REG_3D_TSXa, *(GLint *) &right);
300 MMIO(REG_3D_TSYa, *(GLint *) &top);
301 MMIO(REG_3D_TSARGBa, smesa->clearColorPattern);
302
303 MMIO(REG_3D_TSZb, *(GLint *) &zClearVal);
304 MMIO(REG_3D_TSXb, *(GLint *) &left);
305 MMIO(REG_3D_TSYb, *(GLint *) &top);
306 MMIO(REG_3D_TSARGBb, smesa->clearColorPattern);
307
308 MMIO(REG_3D_TSZc, *(GLint *) &zClearVal);
309 MMIO(REG_3D_TSXc, *(GLint *) &left);
310 MMIO(REG_3D_TSYc, *(GLint *) &bottom);
311 MMIO(REG_3D_TSARGBc, smesa->clearColorPattern);
312
313 /* second triangle */
314 dwPrimitiveSet = OP_3D_TRIANGLE_DRAW | OP_3D_FIRE_TSARGBb |
315 SHADE_FLAT_VertexB;
316 MMIO(REG_3D_PrimitiveSet, dwPrimitiveSet);
317
318 MMIO(REG_3D_TSZb, *(GLint *) &zClearVal);
319 MMIO(REG_3D_TSXb, *(GLint *) &right);
320 MMIO(REG_3D_TSYb, *(GLint *) &bottom);
321 MMIO(REG_3D_TSARGBb, smesa->clearColorPattern);
322 }
323
324 mEndPrimitive();
325
326 smesa->GlobalFlag |= dirtyflags;
327
328 return (mask & ~(DD_BACK_LEFT_BIT | DD_DEPTH_BIT | DD_STENCIL_BIT));
329 }
330 #endif
331
332 static void
333 sis_bitblt_clear_cmd( sisContextPtr smesa, ENGPACKET * pkt )
334 {
335 GLint *lpdwDest, *lpdwSrc;
336 int i;
337
338 lpdwSrc = (GLint *) pkt + 1;
339 lpdwDest = (GLint *) (GET_IOBase (smesa) + REG_SRC_ADDR) + 1;
340
341 mWait3DCmdQueue (10);
342
343 *lpdwDest++ = *lpdwSrc++;
344 lpdwSrc++;
345 lpdwDest++;
346 for (i = 3; i < 8; i++) {
347 *lpdwDest++ = *lpdwSrc++;
348 }
349
350 MMIO(REG_CMD0, *(GLint *) & pkt->stdwCmd);
351 MMIO(REG_QueueLen, -1);
352 }
353
354 static void
355 sis_clear_color_buffer( GLcontext *ctx, GLenum mask, GLint x, GLint y,
356 GLint width, GLint height )
357 {
358 sisContextPtr smesa = SIS_CONTEXT(ctx);
359
360 int count;
361 GLuint depth = GET_DEPTH (smesa);
362 XF86DRIClipRectPtr pExtents = NULL;
363 GLint xx, yy;
364 GLint x0, y0, width0, height0;
365
366 ENGPACKET stEngPacket;
367
368 /* Clear back buffer */
369 if (mask & DD_BACK_LEFT_BIT) {
370 smesa->cbClearPacket.stdwDestPos.wY = y;
371 smesa->cbClearPacket.stdwDestPos.wX = x;
372 smesa->cbClearPacket.stdwDim.wWidth = (GLshort) width;
373 smesa->cbClearPacket.stdwDim.wHeight = (GLshort) height;
374 smesa->cbClearPacket.dwFgRopColor = smesa->clearColorPattern;
375
376 sis_bitblt_clear_cmd( smesa, &smesa->cbClearPacket );
377 }
378
379 if ((mask & DD_FRONT_LEFT_BIT) == 0)
380 return;
381
382 /* Clear front buffer */
383 x0 = x;
384 y0 = y;
385 width0 = width;
386 height0 = height;
387
388 pExtents = smesa->driDrawable->pClipRects;
389 count = smesa->driDrawable->numClipRects;
390
391 memset( &stEngPacket, 0, sizeof (ENGPACKET) );
392
393 stEngPacket.dwSrcPitch = (depth == 2) ? 0x80000000 : 0xc0000000;
394 stEngPacket.dwDestBaseAddr = smesa->frontOffset;
395 stEngPacket.wDestPitch = smesa->frontPitch;
396 /* TODO: set maximum value? */
397 stEngPacket.wDestHeight = smesa->virtualY;
398 stEngPacket.stdwCmd.cRop = 0xf0;
399 stEngPacket.dwFgRopColor = smesa->clearColorPattern;
400
401 /* for SGRAM Block Write Enable */
402 if (smesa->blockWrite)
403 stEngPacket.stdwCmd.cCmd0 = CMD0_PAT_FG_COLOR;
404 else
405 stEngPacket.stdwCmd.cCmd0 = 0;
406 stEngPacket.stdwCmd.cCmd1 = CMD1_DIR_X_INC | CMD1_DIR_Y_INC;
407
408 while (count--) {
409 GLint x2 = pExtents->x1 - smesa->driDrawable->x;
410 GLint y2 = pExtents->y1 - smesa->driDrawable->y;
411 GLint xx2 = pExtents->x2 - smesa->driDrawable->x;
412 GLint yy2 = pExtents->y2 - smesa->driDrawable->y;
413
414 x = (x0 > x2) ? x0 : x2;
415 y = (y0 > y2) ? y0 : y2;
416 xx = ((x0 + width0) > (xx2)) ? xx2 : x0 + width0;
417 yy = ((y0 + height0) > (yy2)) ? yy2 : y0 + height0;
418 width = xx - x;
419 height = yy - y;
420 pExtents++;
421
422 if (width <= 0 || height <= 0)
423 continue;
424
425 stEngPacket.stdwDestPos.wY = y;
426 stEngPacket.stdwDestPos.wX = x;
427 stEngPacket.stdwDim.wWidth = (GLshort)width;
428 stEngPacket.stdwDim.wHeight = (GLshort)height;
429
430 sis_bitblt_clear_cmd( smesa, &stEngPacket );
431 }
432 }
433
434 static void
435 sis_clear_z_stencil_buffer( GLcontext * ctx, GLbitfield mask,
436 GLint x, GLint y, GLint width, GLint height )
437 {
438 sisContextPtr smesa = SIS_CONTEXT(ctx);
439
440 /* TODO: check write mask */
441
442 if ( smesa->depthbuffer == NULL )
443 return;
444
445 /* TODO: consider alignment of width, height? */
446 smesa->zClearPacket.stdwDestPos.wY = y;
447 smesa->zClearPacket.stdwDestPos.wX = x;
448 smesa->zClearPacket.stdwDim.wWidth = (GLshort) width;
449 smesa->zClearPacket.stdwDim.wHeight = (GLshort) height;
450 smesa->zClearPacket.dwFgRopColor = smesa->clearZStencilPattern;
451
452 sis_bitblt_clear_cmd( smesa, &smesa->zClearPacket );
453 }
454