Merge remote branch 'origin/gallium-0.2' into gallium-0.2
[mesa.git] / src / mesa / drivers / dri / ffb / ffb_clear.c
1 /*
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 "main/mtypes.h"
29 #include "main/extensions.h"
30
31 #include "main/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(GLcontext *ctx, __DRIdrawablePrivate *dPriv)
127 {
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;
134
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;
140
141 cy = dPriv->h - cy - ch;
142 cx += dPriv->x;
143 cy += dPriv->y;
144
145 while (nc--) {
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;
152 int extra_work;
153
154 if (BOX_AREA(width, height) < gDRIPriv->fastfill_small_area) {
155 FFBFifo(fmesa, 5);
156 ffb->drawop = FFB_DRAWOP_RECTANGLE;
157 ffb->by = y;
158 ffb->bx = x;
159 ffb->bh = height;
160 ffb->bw = width;
161 continue;
162 }
163
164 FFBFifo(fmesa, 1);
165 ffb->drawop = FFB_DRAWOP_FASTFILL;
166
167 if (gDRIPriv->disable_pagefill ||
168 (width < (gDRIPriv->pagefill_width<<1)) ||
169 (height < (gDRIPriv->pagefill_height<<1)))
170 goto do_fastfill;
171
172 CreatorPageFillParms(gDRIPriv,
173 x, y, width, height,
174 paligned_x, paligned_y,
175 paligned_w, paligned_h, extra_work);
176
177 if (extra_work < 0 ||
178 BOX_AREA(paligned_w, paligned_h) < gDRIPriv->pagefill_small_area) {
179 do_fastfill:
180 FFBFifo(fmesa, 10);
181 ffb->by = FFB_FASTFILL_COLOR_BLK;
182 ffb->dy = 0;
183 ffb->dx = 0;
184 ffb->bh = gDRIPriv->fastfill_height;
185 ffb->bw = (gDRIPriv->fastfill_width * 4);
186 ffb->by = FFB_FASTFILL_BLOCK;
187 ffb->dy = y;
188 ffb->dx = x;
189 ffb->bh = (height + (y & (gDRIPriv->fastfill_height - 1)));
190 ffb->bx = (width + (x & (gDRIPriv->fastfill_width - 1)));
191 continue;
192 }
193
194 /* Ok, page fill is possible and worth it. */
195 FFBFifo(fmesa, 15);
196 ffb->by = FFB_FASTFILL_COLOR_BLK;
197 ffb->dy = 0;
198 ffb->dx = 0;
199 ffb->bh = gDRIPriv->fastfill_height;
200 ffb->bw = gDRIPriv->fastfill_width * 4;
201 ffb->by = FFB_FASTFILL_BLOCK_X;
202 ffb->dy = 0;
203 ffb->dx = 0;
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;
211
212 if (extra_work) {
213 struct ff_fixups local_fixups[4];
214 int nfixups;
215
216 nfixups = CreatorComputePageFillFixups(local_fixups,
217 x, y, width, height,
218 paligned_x, paligned_y,
219 paligned_w, paligned_h);
220 FFBFifo(fmesa, 5 + (nfixups * 5));
221 ffb->by = FFB_FASTFILL_COLOR_BLK;
222 ffb->dy = 0;
223 ffb->dx = 0;
224 ffb->bh = gDRIPriv->fastfill_height;
225 ffb->bw = gDRIPriv->fastfill_width * 4;
226
227 while (--nfixups >= 0) {
228 int xx, yy, ww, hh;
229
230 xx = local_fixups[nfixups].x;
231 yy = local_fixups[nfixups].y;
232 ffb->dy = yy;
233 ffb->dx = xx;
234 ww = (local_fixups[nfixups].width +
235 (xx & (gDRIPriv->fastfill_width - 1)));
236 hh = (local_fixups[nfixups].height +
237 (yy & (gDRIPriv->fastfill_height - 1)));
238 if (nfixups != 0) {
239 ffb->by = FFB_FASTFILL_BLOCK;
240 ffb->bh = hh;
241 ffb->bw = ww;
242 } else {
243 ffb->bh = hh;
244 ffb->by = FFB_FASTFILL_BLOCK;
245 ffb->bx = ww;
246 }
247 }
248 }
249 }
250 }
251
252 void ffbDDClear(GLcontext *ctx, GLbitfield mask)
253 {
254 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
255 __DRIdrawablePrivate *dPriv = fmesa->driDrawable;
256 unsigned int stcmask = BUFFER_BIT_STENCIL;
257
258 #ifdef CLEAR_TRACE
259 fprintf(stderr, "ffbDDClear: mask(%08x) \n", mask);
260 #endif
261 if (!(fmesa->ffb_sarea->flags & FFB_DRI_FFB2PLUS))
262 stcmask = 0;
263
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;
267
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);
273
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);
277 } else
278 fbc |= FFB_FBC_ZE_OFF | FFB_FBC_YE_OFF;
279
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)
284 fbc |= FFB_FBC_WB_B;
285 else
286 fbc |= FFB_FBC_WB_A;
287 }
288 if (mask & BUFFER_BIT_BACK_LEFT) {
289 if (fmesa->back_buffer == 0)
290 fbc |= FFB_FBC_WB_A;
291 else
292 fbc |= FFB_FBC_WB_B;
293 }
294 fbc |= FFB_FBC_RGBE_ON;
295 } else
296 fbc |= FFB_FBC_RGBE_OFF;
297
298 LOCK_HARDWARE(fmesa);
299
300 if (dPriv->numClipRects) {
301 FFBFifo(fmesa, 8);
302 ffb->fbc = fbc;
303 ffb->ppc = ppc;
304 ffb->xclip = FFB_XCLIP_TEST_ALWAYS;
305 ffb->cmp = 0x80808080;
306 ffb->rop = FFB_ROP_NEW;
307
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;
312 if (mask & stcmask)
313 ffb->consty = fmesa->clear_stencil;
314
315 ffb_do_clear(ctx, dPriv);
316
317 FFBFifo(fmesa, 6);
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;
324 if (mask & stcmask)
325 ffb->consty = fmesa->consty;
326 fmesa->ffbScreen->rp_active = 1;
327 }
328
329 UNLOCK_HARDWARE(fmesa);
330
331 mask &= ~(BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT |
332 BUFFER_BIT_DEPTH | stcmask);
333 }
334
335 if (mask)
336 _swrast_Clear(ctx, mask);
337 }
338