1 /* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_clear.c,v 1.2 2002/02/22 21:32:58 dawes Exp $
3 * GLX Hardware Device Driver for Sun Creator/Creator3D
4 * Copyright (C) 2000 David S. Miller
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * DAVID MILLER, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
22 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 * David S. Miller <davem@redhat.com>
29 #include "extensions.h"
34 #include "ffb_depth.h"
35 #include "ffb_context.h"
38 #include "ffb_clear.h"
43 #define BOX_AREA(__w, __h) ((int)(__w) * (int)(__h))
45 /* Compute the page aligned box for a page mode fast fill.
46 * In 'ework' this returns greater than zero if there are some odd
47 * edges to take care of which are outside of the page aligned area.
48 * It will place less than zero there if the box is too small,
49 * indicating that a different method must be used to fill it.
51 #define CreatorPageFillParms(ffp, x, y, w, h, px, py, pw, ph, ework) \
52 do { int xdiff, ydiff; \
53 int pf_bh = ffp->pagefill_height; \
54 int pf_bw = ffp->pagefill_width; \
55 py = ((y + (pf_bh - 1)) & ~(pf_bh - 1)); \
57 px = ffp->Pf_AlignTab[x + (pf_bw - 1)]; \
59 ph = ((h - ydiff) & ~(pf_bh - 1)); \
63 pw = ffp->Pf_AlignTab[w - xdiff]; \
67 ework = (((xdiff > 0) || \
70 ((h - ph) > 0))) ? 1 : 0; \
76 int x
, y
, width
, height
;
79 /* Compute fixups of non-page aligned areas after a page fill.
80 * Return the number of fixups needed.
83 CreatorComputePageFillFixups(struct ff_fixups
*fixups
,
84 int x
, int y
, int w
, int h
,
85 int paligned_x
, int paligned_y
,
86 int paligned_w
, int paligned_h
)
92 fixups
[nfixups
].x
= x
;
93 fixups
[nfixups
].y
= paligned_y
;
94 fixups
[nfixups
].width
= paligned_x
- x
;
95 fixups
[nfixups
].height
= paligned_h
;
100 fixups
[nfixups
].x
= x
;
101 fixups
[nfixups
].y
= y
;
102 fixups
[nfixups
].width
= w
;
103 fixups
[nfixups
].height
= paligned_y
- y
;
107 if((x
+w
) != (paligned_x
+paligned_w
)) {
108 fixups
[nfixups
].x
= (paligned_x
+paligned_w
);
109 fixups
[nfixups
].y
= paligned_y
;
110 fixups
[nfixups
].width
= (x
+w
) - fixups
[nfixups
].x
;
111 fixups
[nfixups
].height
= paligned_h
;
114 /* FastFill Bottom */
115 if((y
+h
) != (paligned_y
+paligned_h
)) {
116 fixups
[nfixups
].x
= x
;
117 fixups
[nfixups
].y
= (paligned_y
+paligned_h
);
118 fixups
[nfixups
].width
= w
;
119 fixups
[nfixups
].height
= (y
+h
) - fixups
[nfixups
].y
;
126 ffb_do_clear(ffbContextPtr fmesa
, __DRIdrawablePrivate
*dPriv
,
127 GLboolean all
, GLint cx
, GLint cy
, GLint cwidth
,
130 FFBDRIPtr gDRIPriv
= (FFBDRIPtr
) fmesa
->driScreen
->pDevPriv
;
131 ffb_fbcPtr ffb
= fmesa
->regs
;
132 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
133 int nc
= dPriv
->numClipRects
;
135 cy
= dPriv
->h
- cy
- cheight
;
140 GLint x
= box
[nc
].x1
;
141 GLint y
= box
[nc
].y1
;
142 GLint width
= box
[nc
].x2
- x
;
143 GLint height
= box
[nc
].y2
- y
;
144 int paligned_y
, paligned_x
;
145 int paligned_h
, paligned_w
= 0;
157 if (x
+ width
> cx
+ cwidth
)
158 width
= cx
+ cwidth
- x
;
159 if (y
+ height
> cy
+ cheight
)
160 height
= cy
+ cheight
- y
;
167 if (BOX_AREA(width
, height
) < gDRIPriv
->fastfill_small_area
) {
169 ffb
->drawop
= FFB_DRAWOP_RECTANGLE
;
178 ffb
->drawop
= FFB_DRAWOP_FASTFILL
;
180 if (gDRIPriv
->disable_pagefill
||
181 (width
< (gDRIPriv
->pagefill_width
<<1)) ||
182 (height
< (gDRIPriv
->pagefill_height
<<1)))
185 CreatorPageFillParms(gDRIPriv
,
187 paligned_x
, paligned_y
,
188 paligned_w
, paligned_h
, extra_work
);
190 if (extra_work
< 0 ||
191 BOX_AREA(paligned_w
, paligned_h
) < gDRIPriv
->pagefill_small_area
) {
194 ffb
->by
= FFB_FASTFILL_COLOR_BLK
;
197 ffb
->bh
= gDRIPriv
->fastfill_height
;
198 ffb
->bw
= (gDRIPriv
->fastfill_width
* 4);
199 ffb
->by
= FFB_FASTFILL_BLOCK
;
202 ffb
->bh
= (height
+ (y
& (gDRIPriv
->fastfill_height
- 1)));
203 ffb
->bx
= (width
+ (x
& (gDRIPriv
->fastfill_width
- 1)));
207 /* Ok, page fill is possible and worth it. */
209 ffb
->by
= FFB_FASTFILL_COLOR_BLK
;
212 ffb
->bh
= gDRIPriv
->fastfill_height
;
213 ffb
->bw
= gDRIPriv
->fastfill_width
* 4;
214 ffb
->by
= FFB_FASTFILL_BLOCK_X
;
217 ffb
->bh
= gDRIPriv
->pagefill_height
;
218 ffb
->bw
= gDRIPriv
->pagefill_width
* 4;
219 ffb
->by
= FFB_FASTFILL_PAGE
;
220 ffb
->dy
= paligned_y
;
221 ffb
->dx
= paligned_x
;
222 ffb
->bh
= paligned_h
;
223 ffb
->bx
= paligned_w
;
226 struct ff_fixups local_fixups
[4];
229 nfixups
= CreatorComputePageFillFixups(local_fixups
,
231 paligned_x
, paligned_y
,
232 paligned_w
, paligned_h
);
233 FFBFifo(fmesa
, 5 + (nfixups
* 5));
234 ffb
->by
= FFB_FASTFILL_COLOR_BLK
;
237 ffb
->bh
= gDRIPriv
->fastfill_height
;
238 ffb
->bw
= gDRIPriv
->fastfill_width
* 4;
240 while (--nfixups
>= 0) {
243 xx
= local_fixups
[nfixups
].x
;
244 yy
= local_fixups
[nfixups
].y
;
247 ww
= (local_fixups
[nfixups
].width
+
248 (xx
& (gDRIPriv
->fastfill_width
- 1)));
249 hh
= (local_fixups
[nfixups
].height
+
250 (yy
& (gDRIPriv
->fastfill_height
- 1)));
252 ffb
->by
= FFB_FASTFILL_BLOCK
;
257 ffb
->by
= FFB_FASTFILL_BLOCK
;
265 void ffbDDClear(GLcontext
*ctx
, GLbitfield mask
, GLboolean all
,
266 GLint cx
, GLint cy
, GLint cwidth
, GLint cheight
)
268 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
269 __DRIdrawablePrivate
*dPriv
= fmesa
->driDrawable
;
270 unsigned int stcmask
= DD_STENCIL_BIT
;
273 fprintf(stderr
, "ffbDDClear: mask(%08x) all(%d) "
274 "[x(%x)y(%x)w(%x)h(%x)]\n",
275 mask
, (int) all
, cx
, cy
, cwidth
, cheight
);
277 if (!(fmesa
->ffb_sarea
->flags
& FFB_DRI_FFB2PLUS
))
280 if (mask
& (DD_FRONT_LEFT_BIT
| DD_BACK_LEFT_BIT
| DD_DEPTH_BIT
| stcmask
)) {
281 ffb_fbcPtr ffb
= fmesa
->regs
;
282 unsigned int fbc
, ppc
;
284 fbc
= (FFB_FBC_XE_ON
);
285 ppc
= (FFB_PPC_ACE_DISABLE
| FFB_PPC_DCE_DISABLE
|
286 FFB_PPC_ABE_DISABLE
| FFB_PPC_VCE_DISABLE
|
287 FFB_PPC_APE_DISABLE
| FFB_PPC_XS_WID
|
288 FFB_PPC_ZS_CONST
| FFB_PPC_CS_CONST
);
290 /* Y/X enables must be both on or both off. */
291 if (mask
& (DD_DEPTH_BIT
| stcmask
)) {
292 fbc
|= (FFB_FBC_ZE_ON
| FFB_FBC_YE_ON
| FFB_FBC_WB_C
);
294 fbc
|= FFB_FBC_ZE_OFF
| FFB_FBC_YE_OFF
;
296 /* All RGB enables must be both on or both off. */
297 if (mask
& (DD_FRONT_LEFT_BIT
| DD_BACK_LEFT_BIT
)) {
298 if (mask
& DD_FRONT_LEFT_BIT
) {
299 if (fmesa
->back_buffer
== 0)
304 if (mask
& DD_BACK_LEFT_BIT
) {
305 if (fmesa
->back_buffer
== 0)
310 fbc
|= FFB_FBC_RGBE_ON
;
312 fbc
|= FFB_FBC_RGBE_OFF
;
314 LOCK_HARDWARE(fmesa
);
316 if (dPriv
->numClipRects
) {
320 ffb
->xclip
= FFB_XCLIP_TEST_ALWAYS
;
321 ffb
->cmp
= 0x80808080;
322 ffb
->rop
= FFB_ROP_NEW
;
324 if (mask
& (DD_FRONT_LEFT_BIT
| DD_BACK_LEFT_BIT
))
325 ffb
->fg
= fmesa
->clear_pixel
;
326 if (mask
& DD_DEPTH_BIT
)
327 ffb
->constz
= fmesa
->clear_depth
;
329 ffb
->consty
= fmesa
->clear_stencil
;
331 ffb_do_clear(fmesa
, dPriv
, all
, cx
, cy
, cwidth
, cheight
);
334 ffb
->ppc
= fmesa
->ppc
;
335 ffb
->fbc
= fmesa
->fbc
;
336 ffb
->xclip
= fmesa
->xclip
;
337 ffb
->cmp
= fmesa
->cmp
;
338 ffb
->rop
= fmesa
->rop
;
339 ffb
->drawop
= fmesa
->drawop
;
341 ffb
->consty
= fmesa
->consty
;
342 fmesa
->ffbScreen
->rp_active
= 1;
345 UNLOCK_HARDWARE(fmesa
);
347 mask
&= ~(DD_FRONT_LEFT_BIT
| DD_BACK_LEFT_BIT
|
348 DD_DEPTH_BIT
| stcmask
);
352 _swrast_Clear(ctx
, mask
, all
, cx
, cy
, cwidth
, cheight
);