Tizen 2.0 Release
[profile/ivi/osmesa.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( struct gl_context * ctx, GLbitfield mask,
42                                 GLint x, GLint y, GLint width,
43                                 GLint height );
44 static void sis_clear_color_buffer( struct gl_context *ctx, GLenum mask, GLint x,
45                                     GLint y, GLint width, GLint height );
46 static void sis_clear_z_stencil_buffer( struct gl_context * 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( struct gl_context * 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( struct gl_context * 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( struct gl_context * ctx, GLclampd d )
166 {
167    sisContextPtr smesa = SIS_CONTEXT(ctx);
168
169    sisUpdateZStencilPattern( smesa, d, ctx->Stencil.Clear );
170 }
171
172 void
173 sisDDClearStencil( struct gl_context * 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( struct gl_context * 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( struct gl_context *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( struct gl_context * ctx, GLbitfield mask,
393                             GLint x, GLint y, GLint width, GLint height )
394 {
395    sisContextPtr smesa = SIS_CONTEXT(ctx);
396
397    mWait3DCmdQueue (8);
398    MMIO(REG_SRC_PITCH, (smesa->zFormat == SiS_ZFORMAT_Z16) ?
399                         BLIT_DEPTH_16 : BLIT_DEPTH_32);
400    MMIO(REG_DST_X_Y, (x << 16) | y);
401    MMIO(REG_DST_ADDR, smesa->depth.offset);
402    MMIO(REG_DST_PITCH_HEIGHT, (smesa->virtualY << 16) | smesa->depth.pitch);
403    MMIO(REG_WIDTH_HEIGHT, (height << 16) | width);
404    MMIO(REG_PATFG, smesa->clearZStencilPattern);
405    MMIO(REG_BLIT_CMD, CMD_DIR_X_INC | CMD_DIR_Y_INC | CMD_ROP_PAT);
406    MMIO(REG_CommandQueue, -1);
407 }
408