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