(Stephane Marchesin, me) add hyperz support to radeon and r200 drivers. Only fast...
[mesa.git] / src / mesa / drivers / dri / ffb / ffb_clear.c
1 /* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_clear.c,v 1.2 2002/02/22 21:32:58 dawes Exp $
2 *
3 * GLX Hardware Device Driver for Sun Creator/Creator3D
4 * Copyright (C) 2000 David S. Miller
5 *
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:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
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.
23 *
24 *
25 * David S. Miller <davem@redhat.com>
26 */
27
28 #include "mtypes.h"
29 #include "extensions.h"
30
31 #include "mm.h"
32 #include "ffb_dd.h"
33 #include "ffb_span.h"
34 #include "ffb_depth.h"
35 #include "ffb_context.h"
36 #include "ffb_vb.h"
37 #include "ffb_tris.h"
38 #include "ffb_clear.h"
39 #include "ffb_lock.h"
40
41 #undef CLEAR_TRACE
42
43 #define BOX_AREA(__w, __h) ((int)(__w) * (int)(__h))
44
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.
50 */
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)); \
56 ydiff = py - y; \
57 px = ffp->Pf_AlignTab[x + (pf_bw - 1)]; \
58 xdiff = px - x; \
59 ph = ((h - ydiff) & ~(pf_bh - 1)); \
60 if(ph <= 0) \
61 ework = -1; \
62 else { \
63 pw = ffp->Pf_AlignTab[w - xdiff]; \
64 if(pw <= 0) { \
65 ework = -1; \
66 } else { \
67 ework = (((xdiff > 0) || \
68 (ydiff > 0) || \
69 ((w - pw) > 0) || \
70 ((h - ph) > 0))) ? 1 : 0; \
71 } \
72 } \
73 } while(0);
74
75 struct ff_fixups {
76 int x, y, width, height;
77 };
78
79 /* Compute fixups of non-page aligned areas after a page fill.
80 * Return the number of fixups needed.
81 */
82 static __inline__ int
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)
87 {
88 int nfixups = 0;
89
90 /* FastFill Left */
91 if(paligned_x != x) {
92 fixups[nfixups].x = x;
93 fixups[nfixups].y = paligned_y;
94 fixups[nfixups].width = paligned_x - x;
95 fixups[nfixups].height = paligned_h;
96 nfixups++;
97 }
98 /* FastFill Top */
99 if(paligned_y != y) {
100 fixups[nfixups].x = x;
101 fixups[nfixups].y = y;
102 fixups[nfixups].width = w;
103 fixups[nfixups].height = paligned_y - y;
104 nfixups++;
105 }
106 /* FastFill Right */
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;
112 nfixups++;
113 }
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;
120 nfixups++;
121 }
122 return nfixups;
123 }
124
125 static void
126 ffb_do_clear(ffbContextPtr fmesa, __DRIdrawablePrivate *dPriv,
127 GLboolean all, GLint cx, GLint cy, GLint cwidth,
128 GLint cheight)
129 {
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;
134
135 cy = dPriv->h - cy - cheight;
136 cx += dPriv->x;
137 cy += dPriv->y;
138
139 while (nc--) {
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;
146 int extra_work;
147
148 if (!all) {
149 if (x < cx) {
150 width -= cx - x;
151 x = cx;
152 }
153 if (y < cy) {
154 height -= cy - y;
155 y = cy;
156 }
157 if (x + width > cx + cwidth)
158 width = cx + cwidth - x;
159 if (y + height > cy + cheight)
160 height = cy + cheight - y;
161 if (width <= 0)
162 continue;
163 if (height <= 0)
164 continue;
165 }
166
167 if (BOX_AREA(width, height) < gDRIPriv->fastfill_small_area) {
168 FFBFifo(fmesa, 5);
169 ffb->drawop = FFB_DRAWOP_RECTANGLE;
170 ffb->by = y;
171 ffb->bx = x;
172 ffb->bh = height;
173 ffb->bw = width;
174 continue;
175 }
176
177 FFBFifo(fmesa, 1);
178 ffb->drawop = FFB_DRAWOP_FASTFILL;
179
180 if (gDRIPriv->disable_pagefill ||
181 (width < (gDRIPriv->pagefill_width<<1)) ||
182 (height < (gDRIPriv->pagefill_height<<1)))
183 goto do_fastfill;
184
185 CreatorPageFillParms(gDRIPriv,
186 x, y, width, height,
187 paligned_x, paligned_y,
188 paligned_w, paligned_h, extra_work);
189
190 if (extra_work < 0 ||
191 BOX_AREA(paligned_w, paligned_h) < gDRIPriv->pagefill_small_area) {
192 do_fastfill:
193 FFBFifo(fmesa, 10);
194 ffb->by = FFB_FASTFILL_COLOR_BLK;
195 ffb->dy = 0;
196 ffb->dx = 0;
197 ffb->bh = gDRIPriv->fastfill_height;
198 ffb->bw = (gDRIPriv->fastfill_width * 4);
199 ffb->by = FFB_FASTFILL_BLOCK;
200 ffb->dy = y;
201 ffb->dx = x;
202 ffb->bh = (height + (y & (gDRIPriv->fastfill_height - 1)));
203 ffb->bx = (width + (x & (gDRIPriv->fastfill_width - 1)));
204 continue;
205 }
206
207 /* Ok, page fill is possible and worth it. */
208 FFBFifo(fmesa, 15);
209 ffb->by = FFB_FASTFILL_COLOR_BLK;
210 ffb->dy = 0;
211 ffb->dx = 0;
212 ffb->bh = gDRIPriv->fastfill_height;
213 ffb->bw = gDRIPriv->fastfill_width * 4;
214 ffb->by = FFB_FASTFILL_BLOCK_X;
215 ffb->dy = 0;
216 ffb->dx = 0;
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;
224
225 if (extra_work) {
226 struct ff_fixups local_fixups[4];
227 int nfixups;
228
229 nfixups = CreatorComputePageFillFixups(local_fixups,
230 x, y, width, height,
231 paligned_x, paligned_y,
232 paligned_w, paligned_h);
233 FFBFifo(fmesa, 5 + (nfixups * 5));
234 ffb->by = FFB_FASTFILL_COLOR_BLK;
235 ffb->dy = 0;
236 ffb->dx = 0;
237 ffb->bh = gDRIPriv->fastfill_height;
238 ffb->bw = gDRIPriv->fastfill_width * 4;
239
240 while (--nfixups >= 0) {
241 int xx, yy, ww, hh;
242
243 xx = local_fixups[nfixups].x;
244 yy = local_fixups[nfixups].y;
245 ffb->dy = yy;
246 ffb->dx = xx;
247 ww = (local_fixups[nfixups].width +
248 (xx & (gDRIPriv->fastfill_width - 1)));
249 hh = (local_fixups[nfixups].height +
250 (yy & (gDRIPriv->fastfill_height - 1)));
251 if (nfixups != 0) {
252 ffb->by = FFB_FASTFILL_BLOCK;
253 ffb->bh = hh;
254 ffb->bw = ww;
255 } else {
256 ffb->bh = hh;
257 ffb->by = FFB_FASTFILL_BLOCK;
258 ffb->bx = ww;
259 }
260 }
261 }
262 }
263 }
264
265 void ffbDDClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
266 GLint cx, GLint cy, GLint cwidth, GLint cheight)
267 {
268 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
269 __DRIdrawablePrivate *dPriv = fmesa->driDrawable;
270 unsigned int stcmask = DD_STENCIL_BIT;
271
272 #ifdef CLEAR_TRACE
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);
276 #endif
277 if (!(fmesa->ffb_sarea->flags & FFB_DRI_FFB2PLUS))
278 stcmask = 0;
279
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;
283
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);
289
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);
293 } else
294 fbc |= FFB_FBC_ZE_OFF | FFB_FBC_YE_OFF;
295
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)
300 fbc |= FFB_FBC_WB_B;
301 else
302 fbc |= FFB_FBC_WB_A;
303 }
304 if (mask & DD_BACK_LEFT_BIT) {
305 if (fmesa->back_buffer == 0)
306 fbc |= FFB_FBC_WB_A;
307 else
308 fbc |= FFB_FBC_WB_B;
309 }
310 fbc |= FFB_FBC_RGBE_ON;
311 } else
312 fbc |= FFB_FBC_RGBE_OFF;
313
314 LOCK_HARDWARE(fmesa);
315
316 if (dPriv->numClipRects) {
317 FFBFifo(fmesa, 8);
318 ffb->fbc = fbc;
319 ffb->ppc = ppc;
320 ffb->xclip = FFB_XCLIP_TEST_ALWAYS;
321 ffb->cmp = 0x80808080;
322 ffb->rop = FFB_ROP_NEW;
323
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;
328 if (mask & stcmask)
329 ffb->consty = fmesa->clear_stencil;
330
331 ffb_do_clear(fmesa, dPriv, all, cx, cy, cwidth, cheight);
332
333 FFBFifo(fmesa, 6);
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;
340 if (mask & stcmask)
341 ffb->consty = fmesa->consty;
342 fmesa->ffbScreen->rp_active = 1;
343 }
344
345 UNLOCK_HARDWARE(fmesa);
346
347 mask &= ~(DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT |
348 DD_DEPTH_BIT | stcmask);
349 }
350
351 if (mask)
352 _swrast_Clear(ctx, mask, all, cx, cy, cwidth, cheight);
353 }
354