637d502381e82c17b3114981fdfead24eeb11bcf
[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, GLboolean all,
99 GLint x, GLint y, GLint width, GLint height )
100 {
101 sisContextPtr smesa = SIS_CONTEXT(ctx);
102
103 GLint x1, y1, width1, height1;
104
105 if (all) {
106 GLframebuffer *buffer = ctx->DrawBuffer;
107
108 x1 = 0;
109 y1 = 0;
110 width1 = buffer->Width;
111 height1 = buffer->Height;
112 } else {
113 x1 = x;
114 y1 = Y_FLIP(y+height-1);
115 width1 = width;
116 height1 = height;
117 }
118 /* XXX: Scissoring */
119
120 /* Mask out any non-existent buffers */
121 if (ctx->Visual.depthBits == 0 || !ctx->Depth.Mask)
122 mask &= ~BUFFER_BIT_DEPTH;
123 if (ctx->Visual.stencilBits == 0)
124 mask &= ~BUFFER_BIT_STENCIL;
125
126 LOCK_HARDWARE();
127
128 /* The 3d clear code is use for masked clears because apparently the SiS
129 * 300-series can't do write masks for 2d blits. 3d isn't used in general
130 * because it's slower, even in the case of clearing multiple buffers.
131 */
132 /* XXX: Appears to be broken with stencil. */
133 if ((smesa->current.hwCapEnable2 & (MASK_AlphaMaskWriteEnable |
134 MASK_ColorMaskWriteEnable) &&
135 (mask & (BUFFER_BIT_BACK_LEFT | BUFFER_BIT_FRONT_LEFT)) != 0) ||
136 ((ctx->Stencil.WriteMask[0] & 0xff) != 0xff &&
137 (mask & BUFFER_BIT_STENCIL) != 0) )
138 {
139 mask = sis_3D_Clear( ctx, mask, x1, y1, width1, height1 );
140 }
141
142 if ( mask & BUFFER_BIT_FRONT_LEFT || mask & BUFFER_BIT_BACK_LEFT) {
143 sis_clear_color_buffer( ctx, mask, x1, y1, width1, height1 );
144 mask &= ~(BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT);
145 }
146
147 if (mask & (BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL)) {
148 if (smesa->depth.offset != 0)
149 sis_clear_z_stencil_buffer( ctx, mask, x1, y1, width1, height1 );
150 mask &= ~(BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL);
151 }
152
153 UNLOCK_HARDWARE();
154
155 if (mask != 0)
156 _swrast_Clear( ctx, mask, all, x1, y1, width, height );
157 }
158
159
160 void
161 sisDDClearColor( GLcontext * ctx, const GLfloat color[4] )
162 {
163 sisContextPtr smesa = SIS_CONTEXT(ctx);
164 GLubyte c[4];
165
166 CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]);
167 CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]);
168 CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]);
169 CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]);
170
171 set_color_pattern( smesa, c[0], c[1], c[2], c[3] );
172 }
173
174 void
175 sisDDClearDepth( GLcontext * ctx, GLclampd d )
176 {
177 sisContextPtr smesa = SIS_CONTEXT(ctx);
178
179 sisUpdateZStencilPattern( smesa, d, ctx->Stencil.Clear );
180 }
181
182 void
183 sisDDClearStencil( GLcontext * ctx, GLint s )
184 {
185 sisContextPtr smesa = SIS_CONTEXT(ctx);
186
187 sisUpdateZStencilPattern( smesa, ctx->Depth.Clear, s );
188 }
189
190 static GLbitfield
191 sis_3D_Clear( GLcontext * ctx, GLbitfield mask,
192 GLint x, GLint y, GLint width, GLint height )
193 {
194 sisContextPtr smesa = SIS_CONTEXT(ctx);
195
196 __GLSiSHardware *current = &smesa->current;
197
198 float left, top, right, bottom, zClearVal;
199 GLboolean bClrColor, bClrDepth, bClrStencil;
200 GLint dwPrimitiveSet;
201 GLint dwEnable1 = 0, dwEnable2 = MASK_ColorMaskWriteEnable;
202 GLint dwDepthMask = 0, dwSten1 = 0, dwSten2 = 0;
203 GLint dirtyflags = GFLAG_ENABLESETTING | GFLAG_ENABLESETTING2 |
204 GFLAG_CLIPPING | GFLAG_DESTSETTING;
205 int count;
206 drm_clip_rect_t *pExtents;
207
208 bClrColor = (mask & (BUFFER_BIT_BACK_LEFT | BUFFER_BIT_FRONT_LEFT)) != 0;
209 bClrDepth = (mask & BUFFER_BIT_DEPTH) != 0;
210 bClrStencil = (mask & BUFFER_BIT_STENCIL) != 0;
211
212 if (smesa->GlobalFlag & GFLAG_RENDER_STATES)
213 sis_update_render_state( smesa );
214
215 if (bClrStencil) {
216 dwSten1 = STENCIL_FORMAT_8 | SiS_STENCIL_ALWAYS |
217 ((ctx->Stencil.Clear & 0xff) << 8) | 0xff;
218 dwSten2 = SiS_SFAIL_REPLACE | SiS_SPASS_ZFAIL_REPLACE |
219 SiS_SPASS_ZPASS_REPLACE;
220 dwEnable1 = MASK_ZWriteEnable | MASK_StencilWriteEnable |
221 MASK_StencilTestEnable;
222 dwEnable2 |= MASK_ZMaskWriteEnable;
223 dwDepthMask |= (ctx->Stencil.WriteMask[0] & 0xff) << 24;
224 } else if (bClrDepth) {
225 dwEnable1 = MASK_ZWriteEnable;
226 dwEnable2 |= MASK_ZMaskWriteEnable;
227 }
228
229 if (bClrDepth) {
230 zClearVal = ctx->Depth.Clear;
231 if (ctx->Visual.depthBits != 32)
232 dwDepthMask |= 0x00ffffff;
233 else
234 dwDepthMask = 0xffffffff;
235 } else
236 zClearVal = 0.0;
237
238 mWait3DCmdQueue(9);
239 MMIO(REG_3D_TEnable, dwEnable1);
240 MMIO(REG_3D_TEnable2, dwEnable2);
241 if (bClrDepth || bClrStencil) {
242 MMIO(REG_3D_ZSet, (current->hwZ & ~MASK_ZTestMode) | SiS_Z_COMP_ALWAYS);
243 dirtyflags |= GFLAG_ZSETTING;
244 }
245 if (bClrColor) {
246 MMIO(REG_3D_DstSet, (current->hwDstSet & ~MASK_ROP2) | LOP_COPY);
247 } else {
248 MMIO(REG_3D_DstAlphaWriteMask, 0L);
249 }
250 if (bClrStencil) {
251 MMIO(REG_3D_StencilSet, dwSten1);
252 MMIO(REG_3D_StencilSet2, dwSten2);
253 dirtyflags |= GFLAG_STENCILSETTING;
254 }
255
256 if (mask & BUFFER_BIT_FRONT_LEFT) {
257 pExtents = smesa->driDrawable->pClipRects;
258 count = smesa->driDrawable->numClipRects;
259 } else {
260 pExtents = NULL;
261 count = 1;
262 }
263
264 while(count--) {
265 left = x;
266 right = x + width;
267 top = y;
268 bottom = y + height;
269
270 if (pExtents != NULL) {
271 GLuint x1, y1, x2, y2;
272
273 x1 = pExtents->x1 - smesa->driDrawable->x;
274 y1 = pExtents->y1 - smesa->driDrawable->y;
275 x2 = pExtents->x2 - smesa->driDrawable->x - 1;
276 y2 = pExtents->y2 - smesa->driDrawable->y - 1;
277
278 left = (left > x1) ? left : x1;
279 right = (right > x2) ? x2 : right;
280 top = (top > y1) ? top : y1;
281 bottom = (bottom > y2) ? y2 : bottom;
282 pExtents++;
283 if (left > right || top > bottom)
284 continue;
285 }
286
287 mWait3DCmdQueue(20);
288
289 MMIO(REG_3D_ClipTopBottom, ((GLint)top << 13) | (GLint)bottom);
290 MMIO(REG_3D_ClipLeftRight, ((GLint)left << 13) | (GLint)right);
291
292 /* the first triangle */
293 dwPrimitiveSet = OP_3D_TRIANGLE_DRAW | OP_3D_FIRE_TSARGBc |
294 SHADE_FLAT_VertexC;
295 MMIO(REG_3D_PrimitiveSet, dwPrimitiveSet);
296
297 MMIO(REG_3D_TSZa, *(GLint *) &zClearVal);
298 MMIO(REG_3D_TSXa, *(GLint *) &right);
299 MMIO(REG_3D_TSYa, *(GLint *) &top);
300 MMIO(REG_3D_TSARGBa, smesa->clearColorPattern);
301
302 MMIO(REG_3D_TSZb, *(GLint *) &zClearVal);
303 MMIO(REG_3D_TSXb, *(GLint *) &left);
304 MMIO(REG_3D_TSYb, *(GLint *) &top);
305 MMIO(REG_3D_TSARGBb, smesa->clearColorPattern);
306
307 MMIO(REG_3D_TSZc, *(GLint *) &zClearVal);
308 MMIO(REG_3D_TSXc, *(GLint *) &left);
309 MMIO(REG_3D_TSYc, *(GLint *) &bottom);
310 MMIO(REG_3D_TSARGBc, smesa->clearColorPattern);
311
312 /* second triangle */
313 dwPrimitiveSet = OP_3D_TRIANGLE_DRAW | OP_3D_FIRE_TSARGBb |
314 SHADE_FLAT_VertexB;
315 MMIO(REG_3D_PrimitiveSet, dwPrimitiveSet);
316
317 MMIO(REG_3D_TSZb, *(GLint *) &zClearVal);
318 MMIO(REG_3D_TSXb, *(GLint *) &right);
319 MMIO(REG_3D_TSYb, *(GLint *) &bottom);
320 MMIO(REG_3D_TSARGBb, smesa->clearColorPattern);
321 }
322
323 mEndPrimitive();
324
325 /* If BUFFER_BIT_FRONT_LEFT is set, we've only cleared the front buffer so far */
326 if ((mask & BUFFER_BIT_FRONT_LEFT) != 0 && (mask & BUFFER_BIT_BACK_LEFT) != 0)
327 sis_3D_Clear( ctx, BUFFER_BIT_BACK_LEFT, x, y, width, height );
328
329 smesa->GlobalFlag |= dirtyflags;
330
331 return mask & ~(BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL | BUFFER_BIT_BACK_LEFT |
332 BUFFER_BIT_FRONT_LEFT);
333 }
334
335 static void
336 sis_clear_color_buffer( GLcontext *ctx, GLenum mask, GLint x, GLint y,
337 GLint width, GLint height )
338 {
339 sisContextPtr smesa = SIS_CONTEXT(ctx);
340
341 int count;
342 GLuint depth = smesa->bytesPerPixel;
343 drm_clip_rect_t *pExtents = NULL;
344 GLint xx, yy;
345 GLint x0, y0, width0, height0;
346
347 /* Clear back buffer */
348 if (mask & BUFFER_BIT_BACK_LEFT) {
349 mWait3DCmdQueue (8);
350 MMIO(REG_SRC_PITCH, (smesa->bytesPerPixel == 4) ?
351 BLIT_DEPTH_32 : BLIT_DEPTH_16);
352 MMIO(REG_DST_X_Y, (x << 16) | y);
353 MMIO(REG_DST_ADDR, smesa->back.offset);
354 MMIO(REG_DST_PITCH_HEIGHT, (smesa->virtualY << 16) | smesa->back.pitch);
355 MMIO(REG_WIDTH_HEIGHT, (height << 16) | width);
356 MMIO(REG_PATFG, smesa->clearColorPattern);
357 MMIO(REG_BLIT_CMD, CMD_DIR_X_INC | CMD_DIR_Y_INC | CMD_ROP_PAT);
358 MMIO(REG_CommandQueue, -1);
359 }
360
361 if ((mask & BUFFER_BIT_FRONT_LEFT) == 0)
362 return;
363
364 /* Clear front buffer */
365 x0 = x;
366 y0 = y;
367 width0 = width;
368 height0 = height;
369
370 pExtents = smesa->driDrawable->pClipRects;
371 count = smesa->driDrawable->numClipRects;
372
373 while (count--) {
374 GLint x2 = pExtents->x1 - smesa->driDrawable->x;
375 GLint y2 = pExtents->y1 - smesa->driDrawable->y;
376 GLint xx2 = pExtents->x2 - smesa->driDrawable->x;
377 GLint yy2 = pExtents->y2 - smesa->driDrawable->y;
378
379 x = (x0 > x2) ? x0 : x2;
380 y = (y0 > y2) ? y0 : y2;
381 xx = ((x0 + width0) > (xx2)) ? xx2 : x0 + width0;
382 yy = ((y0 + height0) > (yy2)) ? yy2 : y0 + height0;
383 width = xx - x;
384 height = yy - y;
385 pExtents++;
386
387 if (width <= 0 || height <= 0)
388 continue;
389
390 int cmd;
391
392 mWait3DCmdQueue (8);
393 MMIO(REG_SRC_PITCH, (smesa->bytesPerPixel == 4) ?
394 BLIT_DEPTH_32 : BLIT_DEPTH_16);
395 MMIO(REG_DST_X_Y, (x << 16) | y);
396 MMIO(REG_DST_ADDR, smesa->front.offset);
397 MMIO(REG_DST_PITCH_HEIGHT, (smesa->virtualY << 16) | smesa->front.pitch);
398 MMIO(REG_WIDTH_HEIGHT, (height << 16) | width);
399 MMIO(REG_PATFG, smesa->clearColorPattern);
400 MMIO(REG_BLIT_CMD, CMD_DIR_X_INC | CMD_DIR_Y_INC | CMD_ROP_PAT);
401 MMIO(REG_CommandQueue, -1);
402 }
403 }
404
405 static void
406 sis_clear_z_stencil_buffer( GLcontext * ctx, GLbitfield mask,
407 GLint x, GLint y, GLint width, GLint height )
408 {
409 sisContextPtr smesa = SIS_CONTEXT(ctx);
410 int cmd;
411
412 mWait3DCmdQueue (8);
413 MMIO(REG_SRC_PITCH, (smesa->zFormat == SiS_ZFORMAT_Z16) ?
414 BLIT_DEPTH_16 : BLIT_DEPTH_32);
415 MMIO(REG_DST_X_Y, (x << 16) | y);
416 MMIO(REG_DST_ADDR, smesa->depth.offset);
417 MMIO(REG_DST_PITCH_HEIGHT, (smesa->virtualY << 16) | smesa->depth.pitch);
418 MMIO(REG_WIDTH_HEIGHT, (height << 16) | width);
419 MMIO(REG_PATFG, smesa->clearZStencilPattern);
420 MMIO(REG_BLIT_CMD, CMD_DIR_X_INC | CMD_DIR_Y_INC | CMD_ROP_PAT);
421 MMIO(REG_CommandQueue, -1);
422 }
423