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>
28 #include "main/mtypes.h"
29 #include "main/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(GLcontext
*ctx
, __DRIdrawablePrivate
*dPriv
)
128 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
129 FFBDRIPtr gDRIPriv
= (FFBDRIPtr
) fmesa
->driScreen
->pDevPriv
;
130 ffb_fbcPtr ffb
= fmesa
->regs
;
131 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
132 int nc
= dPriv
->numClipRects
;
133 GLint cx
, cy
, cw
, ch
;
135 /* compute region after locking: */
136 cx
= ctx
->DrawBuffer
->_Xmin
;
137 cy
= ctx
->DrawBuffer
->_Ymin
;
138 cw
= ctx
->DrawBuffer
->_Xmax
- cx
;
139 ch
= ctx
->DrawBuffer
->_Ymax
- cy
;
141 cy
= dPriv
->h
- cy
- ch
;
146 GLint x
= box
[nc
].x1
;
147 GLint y
= box
[nc
].y1
;
148 GLint width
= box
[nc
].x2
- x
;
149 GLint height
= box
[nc
].y2
- y
;
150 int paligned_y
, paligned_x
;
151 int paligned_h
, paligned_w
= 0;
154 if (BOX_AREA(width
, height
) < gDRIPriv
->fastfill_small_area
) {
156 ffb
->drawop
= FFB_DRAWOP_RECTANGLE
;
165 ffb
->drawop
= FFB_DRAWOP_FASTFILL
;
167 if (gDRIPriv
->disable_pagefill
||
168 (width
< (gDRIPriv
->pagefill_width
<<1)) ||
169 (height
< (gDRIPriv
->pagefill_height
<<1)))
172 CreatorPageFillParms(gDRIPriv
,
174 paligned_x
, paligned_y
,
175 paligned_w
, paligned_h
, extra_work
);
177 if (extra_work
< 0 ||
178 BOX_AREA(paligned_w
, paligned_h
) < gDRIPriv
->pagefill_small_area
) {
181 ffb
->by
= FFB_FASTFILL_COLOR_BLK
;
184 ffb
->bh
= gDRIPriv
->fastfill_height
;
185 ffb
->bw
= (gDRIPriv
->fastfill_width
* 4);
186 ffb
->by
= FFB_FASTFILL_BLOCK
;
189 ffb
->bh
= (height
+ (y
& (gDRIPriv
->fastfill_height
- 1)));
190 ffb
->bx
= (width
+ (x
& (gDRIPriv
->fastfill_width
- 1)));
194 /* Ok, page fill is possible and worth it. */
196 ffb
->by
= FFB_FASTFILL_COLOR_BLK
;
199 ffb
->bh
= gDRIPriv
->fastfill_height
;
200 ffb
->bw
= gDRIPriv
->fastfill_width
* 4;
201 ffb
->by
= FFB_FASTFILL_BLOCK_X
;
204 ffb
->bh
= gDRIPriv
->pagefill_height
;
205 ffb
->bw
= gDRIPriv
->pagefill_width
* 4;
206 ffb
->by
= FFB_FASTFILL_PAGE
;
207 ffb
->dy
= paligned_y
;
208 ffb
->dx
= paligned_x
;
209 ffb
->bh
= paligned_h
;
210 ffb
->bx
= paligned_w
;
213 struct ff_fixups local_fixups
[4];
216 nfixups
= CreatorComputePageFillFixups(local_fixups
,
218 paligned_x
, paligned_y
,
219 paligned_w
, paligned_h
);
220 FFBFifo(fmesa
, 5 + (nfixups
* 5));
221 ffb
->by
= FFB_FASTFILL_COLOR_BLK
;
224 ffb
->bh
= gDRIPriv
->fastfill_height
;
225 ffb
->bw
= gDRIPriv
->fastfill_width
* 4;
227 while (--nfixups
>= 0) {
230 xx
= local_fixups
[nfixups
].x
;
231 yy
= local_fixups
[nfixups
].y
;
234 ww
= (local_fixups
[nfixups
].width
+
235 (xx
& (gDRIPriv
->fastfill_width
- 1)));
236 hh
= (local_fixups
[nfixups
].height
+
237 (yy
& (gDRIPriv
->fastfill_height
- 1)));
239 ffb
->by
= FFB_FASTFILL_BLOCK
;
244 ffb
->by
= FFB_FASTFILL_BLOCK
;
252 void ffbDDClear(GLcontext
*ctx
, GLbitfield mask
)
254 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
255 __DRIdrawablePrivate
*dPriv
= fmesa
->driDrawable
;
256 unsigned int stcmask
= BUFFER_BIT_STENCIL
;
259 fprintf(stderr
, "ffbDDClear: mask(%08x) \n", mask
);
261 if (!(fmesa
->ffb_sarea
->flags
& FFB_DRI_FFB2PLUS
))
264 if (mask
& (BUFFER_BIT_FRONT_LEFT
| BUFFER_BIT_BACK_LEFT
| BUFFER_BIT_DEPTH
| stcmask
)) {
265 ffb_fbcPtr ffb
= fmesa
->regs
;
266 unsigned int fbc
, ppc
;
268 fbc
= (FFB_FBC_XE_ON
);
269 ppc
= (FFB_PPC_ACE_DISABLE
| FFB_PPC_DCE_DISABLE
|
270 FFB_PPC_ABE_DISABLE
| FFB_PPC_VCE_DISABLE
|
271 FFB_PPC_APE_DISABLE
| FFB_PPC_XS_WID
|
272 FFB_PPC_ZS_CONST
| FFB_PPC_CS_CONST
);
274 /* Y/X enables must be both on or both off. */
275 if (mask
& (BUFFER_BIT_DEPTH
| stcmask
)) {
276 fbc
|= (FFB_FBC_ZE_ON
| FFB_FBC_YE_ON
| FFB_FBC_WB_C
);
278 fbc
|= FFB_FBC_ZE_OFF
| FFB_FBC_YE_OFF
;
280 /* All RGB enables must be both on or both off. */
281 if (mask
& (BUFFER_BIT_FRONT_LEFT
| BUFFER_BIT_BACK_LEFT
)) {
282 if (mask
& BUFFER_BIT_FRONT_LEFT
) {
283 if (fmesa
->back_buffer
== 0)
288 if (mask
& BUFFER_BIT_BACK_LEFT
) {
289 if (fmesa
->back_buffer
== 0)
294 fbc
|= FFB_FBC_RGBE_ON
;
296 fbc
|= FFB_FBC_RGBE_OFF
;
298 LOCK_HARDWARE(fmesa
);
300 if (dPriv
->numClipRects
) {
304 ffb
->xclip
= FFB_XCLIP_TEST_ALWAYS
;
305 ffb
->cmp
= 0x80808080;
306 ffb
->rop
= FFB_ROP_NEW
;
308 if (mask
& (BUFFER_BIT_FRONT_LEFT
| BUFFER_BIT_BACK_LEFT
))
309 ffb
->fg
= fmesa
->clear_pixel
;
310 if (mask
& BUFFER_BIT_DEPTH
)
311 ffb
->constz
= fmesa
->clear_depth
;
313 ffb
->consty
= fmesa
->clear_stencil
;
315 ffb_do_clear(ctx
, dPriv
);
318 ffb
->ppc
= fmesa
->ppc
;
319 ffb
->fbc
= fmesa
->fbc
;
320 ffb
->xclip
= fmesa
->xclip
;
321 ffb
->cmp
= fmesa
->cmp
;
322 ffb
->rop
= fmesa
->rop
;
323 ffb
->drawop
= fmesa
->drawop
;
325 ffb
->consty
= fmesa
->consty
;
326 fmesa
->ffbScreen
->rp_active
= 1;
329 UNLOCK_HARDWARE(fmesa
);
331 mask
&= ~(BUFFER_BIT_FRONT_LEFT
| BUFFER_BIT_BACK_LEFT
|
332 BUFFER_BIT_DEPTH
| stcmask
);
336 _swrast_Clear(ctx
, mask
);