~ubuntu-branches/ubuntu/gutsy/vnc4/gutsy

« back to all changes in this revision

Viewing changes to unix/xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_frect.c

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2006-05-15 20:35:17 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060515203517-l4lre1ku942mn26k
Tags: 4.1.1+X4.3.0-10
* Correction of critical security issue. Thanks to Martin Kogler
  <e9925248@student.tuwien.ac.at> that informed me about the issue,
  and provided the patch.
  This flaw was originally found by Steve Wiseman of intelliadmin.com.
* Applied patch from Javier Kohen <jkohen@users.sourceforge.net> that
  inform the user that only 8 first characters of the password will
  actually be used when typing more than 8 characters, closes:
  #355619.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Acceleration for the Creator and Creator3D framebuffer - Rectangle filling.
 
3
 *
 
4
 * Copyright (C) 1998,1999 Jakub Jelinek (jakub@redhat.com)
 
5
 * Copyright (C) 1998 Michal Rehacek (majkl@iname.com)
 
6
 * Copyright (C) 1999 David S. Miller (davem@redhat.com)
 
7
 *
 
8
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 
9
 * of this software and associated documentation files (the "Software"), to deal
 
10
 * in the Software without restriction, including without limitation the rights
 
11
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
12
 * copies of the Software, and to permit persons to whom the Software is
 
13
 * furnished to do so, subject to the following conditions:
 
14
 *
 
15
 * The above copyright notice and this permission notice shall be included in
 
16
 * all copies or substantial portions of the 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 NONINFRINGEMENT.  IN NO EVENT SHALL
 
21
 * JAKUB JELINEK, MICHAL REHACEK, OR DAVID MILLER 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
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_frect.c,v 1.3 2001/04/05 17:42:33 dawes Exp $ */
 
28
 
 
29
#include "ffb.h"
 
30
#include "ffb_regs.h"
 
31
#include "ffb_rcache.h"
 
32
#include "ffb_fifo.h"
 
33
#include "ffb_stip.h"
 
34
#include "ffb_loops.h"
 
35
 
 
36
#include "pixmapstr.h"
 
37
#include "scrnintstr.h"
 
38
 
 
39
#define PSZ 8
 
40
#include "cfb.h"
 
41
#undef PSZ
 
42
#include "cfb32.h"
 
43
 
 
44
#define PAGEFILL_DISABLED(pFfb) ((pFfb)->disable_pagefill != 0)
 
45
#define FASTFILL_AP_DISABLED(pFfb) ((pFfb)->disable_fastfill_ap != 0)
 
46
 
 
47
void
 
48
CreatorFillBoxStipple (DrawablePtr pDrawable, int nBox, BoxPtr pBox, CreatorStipplePtr stipple)
 
49
{
 
50
        FFBPtr pFfb = GET_FFB_FROM_SCREEN (pDrawable->pScreen);
 
51
        WindowPtr pWin = (WindowPtr) pDrawable;
 
52
        ffb_fbcPtr ffb = pFfb->regs;
 
53
        unsigned int bits[32];
 
54
        unsigned int newalign;
 
55
 
 
56
        FFBLOG(("CreatorFillBoxStipple: nbox(%d)\n", nBox));
 
57
        newalign = ((pDrawable->y & 31) << 16) | (pDrawable->x & 31);
 
58
        if (stipple->patalign != newalign) {
 
59
                int x, y, i;
 
60
                
 
61
                x = (pDrawable->x - (stipple->patalign & 0xffff)) & 31;
 
62
                y = (pDrawable->y - (stipple->patalign >> 16)) & 31;
 
63
                if (x | y) {
 
64
                        memcpy(bits, stipple->bits, sizeof(bits));
 
65
                        for (i = 0; i < 32; i++)
 
66
                                stipple->bits[(i + y) & 31] =
 
67
                                        (bits[i] >> x) | (bits[i] << (32 - x));
 
68
                        stipple->inhw = 0;
 
69
                }
 
70
                stipple->patalign = newalign;
 
71
        }
 
72
 
 
73
        FFBSetStipple(pFfb, ffb, stipple,
 
74
                      FFB_PPC_APE_DISABLE|FFB_PPC_CS_CONST|FFB_PPC_XS_WID,
 
75
                      FFB_PPC_APE_MASK|FFB_PPC_CS_MASK|FFB_PPC_XS_MASK);
 
76
        FFB_WRITE_PMASK(pFfb, ffb, ~0);
 
77
        FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_RECTANGLE);
 
78
        FFB_WRITE_FBC(pFfb, ffb, FFB_FBC_WIN(pWin));
 
79
        FFB_WRITE_WID(pFfb, ffb, FFB_WID_WIN(pWin));
 
80
 
 
81
        while(nBox--) {
 
82
                register int x, y, w, h;
 
83
 
 
84
                x = pBox->x1;
 
85
                y = pBox->y1;
 
86
                w = (pBox->x2 - x);
 
87
                h = (pBox->y2 - y);
 
88
                FFBFifo(pFfb, 4);
 
89
                FFB_WRITE64(&ffb->by, y, x);
 
90
                FFB_WRITE64_2(&ffb->bh, h, w);
 
91
                pBox++;
 
92
        }
 
93
 
 
94
        pFfb->rp_active = 1;
 
95
        FFBSync(pFfb, ffb);
 
96
}
 
97
 
 
98
enum ffb_fillrect_method { fillrect_page,
 
99
                           fillrect_fast, fillrect_fast_opaque,
 
100
                           fillrect_normal };
 
101
 
 
102
#define BOX_AREA(__w, __h)      ((int)(__w) * (int)(__h))
 
103
 
 
104
/* Compute the page aligned box for a page mode fast fill.
 
105
 * In 'ework' this returns greater than zero if there are some odd
 
106
 * edges to take care of which are outside of the page aligned area.
 
107
 * It will place less than zero there if the box is too small,
 
108
 * indicating that a different method must be used to fill it.
 
109
 */
 
110
#define CreatorPageFillParms(pFfb, ffp, x, y, w, h, px, py, pw, ph, ework) \
 
111
do {    int xdiff, ydiff; \
 
112
        int pf_bh = ffp->pagefill_height; \
 
113
        int pf_bw = ffp->pagefill_width; \
 
114
        py = ((y + (pf_bh - 1)) & ~(pf_bh - 1)); \
 
115
        ydiff = py - y; \
 
116
        px = pFfb->Pf_AlignTab[x + (pf_bw - 1)]; \
 
117
        xdiff = px - x; \
 
118
        ph = ((h - ydiff) & ~(pf_bh - 1)); \
 
119
        if(ph <= 0) \
 
120
                ework = -1; \
 
121
        else { \
 
122
                pw = pFfb->Pf_AlignTab[w - xdiff]; \
 
123
                if(pw <= 0) { \
 
124
                        ework = -1; \
 
125
                } else { \
 
126
                        ework = (((xdiff > 0)           || \
 
127
                                  (ydiff > 0)           || \
 
128
                                  ((w - pw) > 0)        || \
 
129
                                  ((h - ph) > 0))) ? 1 : 0; \
 
130
                } \
 
131
        } \
 
132
} while(0);
 
133
 
 
134
/* Compute fixups of non-page aligned areas after a page fill.
 
135
 * Return the number of fixups needed.
 
136
 */
 
137
static __inline__ int
 
138
CreatorComputePageFillFixups(xRectangle *fixups,
 
139
                             int x, int y, int w, int h,
 
140
                             int paligned_x, int paligned_y,
 
141
                             int paligned_w, int paligned_h)
 
142
{
 
143
        int nfixups = 0;
 
144
 
 
145
        /* FastFill Left */
 
146
        if(paligned_x != x) {
 
147
                fixups[nfixups].x = x;
 
148
                fixups[nfixups].y = paligned_y;
 
149
                fixups[nfixups].width = paligned_x - x;
 
150
                fixups[nfixups].height = paligned_h;
 
151
                nfixups++;
 
152
        }
 
153
        /* FastFill Top */
 
154
        if(paligned_y != y) {
 
155
                fixups[nfixups].x = x;
 
156
                fixups[nfixups].y = y;
 
157
                fixups[nfixups].width = w;
 
158
                fixups[nfixups].height = paligned_y - y;
 
159
                nfixups++;
 
160
        }
 
161
        /* FastFill Right */
 
162
        if((x+w) != (paligned_x+paligned_w)) {
 
163
                fixups[nfixups].x = (paligned_x+paligned_w);
 
164
                fixups[nfixups].y = paligned_y;
 
165
                fixups[nfixups].width = (x+w) - fixups[nfixups].x;
 
166
                fixups[nfixups].height = paligned_h;
 
167
                nfixups++;
 
168
        }
 
169
        /* FastFill Bottom */
 
170
        if((y+h) != (paligned_y+paligned_h)) {
 
171
                fixups[nfixups].x = x;
 
172
                fixups[nfixups].y = (paligned_y+paligned_h);
 
173
                fixups[nfixups].width = w;
 
174
                fixups[nfixups].height = (y+h) - fixups[nfixups].y;
 
175
                nfixups++;
 
176
        }
 
177
        return nfixups;
 
178
}
 
179
 
 
180
/* Fill a set of boxes, pagefill and fastfill not allowed. */
 
181
static void
 
182
CreatorBoxFillNormal(FFBPtr pFfb,
 
183
                     int nbox, BoxPtr pbox)
 
184
{
 
185
        ffb_fbcPtr ffb = pFfb->regs;
 
186
 
 
187
        FFBLOG(("BFNormal: "));
 
188
        if(nbox)
 
189
                FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_RECTANGLE);
 
190
        while(nbox--) {
 
191
                register int x, y, w, h;
 
192
 
 
193
                x = pbox->x1;
 
194
                y = pbox->y1;
 
195
                w = (pbox->x2 - x);
 
196
                h = (pbox->y2 - y);
 
197
                pbox++;
 
198
                FFBLOG(("[%08x:%08x:%08x:%08x] ", x, y, w, h));
 
199
                FFBFifo(pFfb, 4);
 
200
                FFB_WRITE64(&ffb->by, y, x);
 
201
                FFB_WRITE64_2(&ffb->bh, h, w);
 
202
        }
 
203
        FFBLOG(("\n"));
 
204
}
 
205
 
 
206
/* Fill a set of boxes, only non-pagemode fastfill is allowed. */
 
207
static void
 
208
CreatorBoxFillFast(FFBPtr pFfb,
 
209
                   int nbox, BoxPtr pbox)
 
210
{
 
211
        ffb_fbcPtr ffb = pFfb->regs;
 
212
 
 
213
        FFBLOG(("BFFast: "));
 
214
        while(nbox--) {
 
215
                struct fastfill_parms *ffp = &FFB_FFPARMS(pFfb);
 
216
                register int x, y, w, h;
 
217
 
 
218
                x = pbox->x1;
 
219
                y = pbox->y1;
 
220
                w = (pbox->x2 - x);
 
221
                h = (pbox->y2 - y);
 
222
                pbox++;
 
223
                if(BOX_AREA(w, h) < ffp->fastfill_small_area) {
 
224
                        /* Too small for fastfill to be useful. */
 
225
                        FFBLOG(("NRM(%08x:%08x:%08x:%08x) ",
 
226
                                x, y, w, h));
 
227
                        FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_RECTANGLE);
 
228
                        FFBFifo(pFfb, 4);
 
229
                        FFB_WRITE64(&ffb->by, y, x);
 
230
                        FFB_WRITE64_2(&ffb->bh, h, w);
 
231
                } else {
 
232
                        FFBLOG(("FST(%08x:%08x:%08x:%08x:[%08x:%08x]) ",
 
233
                                x, y, w, h,
 
234
                                (w + (x & (ffp->fastfill_width - 1))),
 
235
                                (h + (y & (ffp->fastfill_height - 1)))));
 
236
                        if (pFfb->ffb_res == ffb_res_high &&
 
237
                            ((x & 7) != 0 || (w & 7) != 0)) {
 
238
                                FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_RECTANGLE);
 
239
                                if ((x & 7) != 0) {
 
240
                                        register int nx = x;
 
241
                                        register int nw;
 
242
 
 
243
                                        nw = 8 - (nx & 7);
 
244
                                        if (nw > w)
 
245
                                                nw = w;
 
246
                                        FFBFifo(pFfb, 4);
 
247
                                        FFB_WRITE64(&ffb->by, y, nx);
 
248
                                        FFB_WRITE64_2(&ffb->bh, h, nw);
 
249
                                        x += nw;
 
250
                                        w -= nw;
 
251
                                }
 
252
                                if ((w & 7) != 0) {
 
253
                                        register int nx, nw;
 
254
 
 
255
                                        nw = (w & 7);
 
256
                                        nx = x + (w - nw);
 
257
                                        FFBFifo(pFfb, 4);
 
258
                                        FFB_WRITE64(&ffb->by, y, nx);
 
259
                                        FFB_WRITE64_2(&ffb->bh, h, nw);
 
260
                                        w -= nw;
 
261
                                }
 
262
                                if (w <= 0)
 
263
                                        goto next_rect;
 
264
                        }
 
265
                        FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_FASTFILL);
 
266
                        FFBFifo(pFfb, 10);
 
267
                        ffb->by = FFB_FASTFILL_COLOR_BLK;
 
268
                        FFB_WRITE64(&ffb->dy, 0, 0);
 
269
                        FFB_WRITE64_2(&ffb->bh,
 
270
                                      ffp->fastfill_height,
 
271
                                      (ffp->fastfill_width * 4));
 
272
                        FFB_WRITE64_3(&ffb->dy, y, x);
 
273
                        ffb->bh = (h + (y & (ffp->fastfill_height - 1)));
 
274
                        FFB_WRITE64(&ffb->by, FFB_FASTFILL_BLOCK,
 
275
                                    (w + (x & (ffp->fastfill_width - 1))));
 
276
                }
 
277
        next_rect:
 
278
                ;
 
279
        }
 
280
        FFBLOG(("\n"));
 
281
}
 
282
 
 
283
/* Fill a set of boxes, any fastfill method is allowed. */
 
284
static void
 
285
CreatorBoxFillPage(FFBPtr pFfb,
 
286
                   int nbox, BoxPtr pbox)
 
287
{
 
288
        ffb_fbcPtr ffb = pFfb->regs;
 
289
 
 
290
        FFBLOG(("BFPage: "));
 
291
        while(nbox--) {
 
292
                struct fastfill_parms *ffp = &FFB_FFPARMS(pFfb);
 
293
                register int x, y, w, h;
 
294
 
 
295
                x = pbox->x1;
 
296
                y = pbox->y1;
 
297
                w = (pbox->x2 - x);
 
298
                h = (pbox->y2 - y);
 
299
                pbox++;
 
300
                if(BOX_AREA(w, h) < ffp->fastfill_small_area) {
 
301
                        /* Too small for fastfill or page fill to be useful. */
 
302
                        FFBLOG(("NRM(%08x:%08x:%08x:%08x) ",
 
303
                                x, y, w, h));
 
304
                        FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_RECTANGLE);
 
305
                        FFBFifo(pFfb, 4);
 
306
                        FFB_WRITE64(&ffb->by, y, x);
 
307
                        FFB_WRITE64_2(&ffb->bh, h, w);
 
308
                } else {
 
309
                        int paligned_y, paligned_x;
 
310
                        int paligned_h, paligned_w = 0;
 
311
                        int extra_work;
 
312
 
 
313
                        if (pFfb->ffb_res == ffb_res_high &&
 
314
                            ((x & 7) != 0 || (w & 7) != 0)) {
 
315
                                FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_RECTANGLE);
 
316
                                if ((x & 7) != 0) {
 
317
                                        register int nx = x;
 
318
                                        register int nw;
 
319
 
 
320
                                        nw = 8 - (nx & 7);
 
321
                                        if (nw > w)
 
322
                                                nw = w;
 
323
                                        FFBFifo(pFfb, 4);
 
324
                                        FFB_WRITE64(&ffb->by, y, nx);
 
325
                                        FFB_WRITE64_2(&ffb->bh, h, nw);
 
326
                                        x += nw;
 
327
                                        w -= nw;
 
328
                                }
 
329
                                if ((w & 7) != 0) {
 
330
                                        register int nx, nw;
 
331
 
 
332
                                        nw = (w & 7);
 
333
                                        nx = x + (w - nw);
 
334
                                        FFBFifo(pFfb, 4);
 
335
                                        FFB_WRITE64(&ffb->by, y, nx);
 
336
                                        FFB_WRITE64_2(&ffb->bh, h, nw);
 
337
                                        w -= nw;
 
338
                                }
 
339
                                if (w <= 0)
 
340
                                        goto next_rect;
 
341
                        }
 
342
 
 
343
                        FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_FASTFILL);
 
344
                        if((w < (ffp->pagefill_width<<1)) ||
 
345
                           (h < (ffp->pagefill_height<<1)))
 
346
                                goto do_fastfill;
 
347
 
 
348
                        CreatorPageFillParms(pFfb, ffp,
 
349
                                             x, y, w, h,
 
350
                                             paligned_x, paligned_y,
 
351
                                             paligned_w, paligned_h, extra_work);
 
352
 
 
353
                        /* See if the aligned area is large enough for
 
354
                         * page fill to be worthwhile.
 
355
                         */
 
356
                        if(extra_work < 0 ||
 
357
                           BOX_AREA(paligned_w, paligned_h) < ffp->pagefill_small_area) {
 
358
                   do_fastfill:
 
359
                                FFBLOG(("FST(%08x:%08x:%08x:%08x:[%08x:%08x]) ",
 
360
                                        x, y, w, h,
 
361
                                        (w + (x & (ffp->fastfill_width - 1))),
 
362
                                        (h + (y & (ffp->fastfill_height - 1)))));
 
363
                                FFBFifo(pFfb, 10);
 
364
                                ffb->by = FFB_FASTFILL_COLOR_BLK;
 
365
                                FFB_WRITE64(&ffb->dy, 0, 0);
 
366
                                FFB_WRITE64_2(&ffb->bh,
 
367
                                              ffp->fastfill_height,
 
368
                                              (ffp->fastfill_width * 4));
 
369
                                FFB_WRITE64_3(&ffb->dy, y, x);
 
370
                                ffb->bh = (h + (y & (ffp->fastfill_height - 1)));
 
371
                                FFB_WRITE64(&ffb->by, FFB_FASTFILL_BLOCK,
 
372
                                            (w + (x & (ffp->fastfill_width - 1))));
 
373
                        } else {
 
374
                                /* Ok, page fill is worth it, let it rip. */
 
375
                                FFBLOG(("PAG(%08x:%08x:%08x:%08x) ",
 
376
                                        paligned_x, paligned_y, paligned_w, paligned_h));
 
377
                                FFBFifo(pFfb, 15);
 
378
                                ffb->by = FFB_FASTFILL_COLOR_BLK;
 
379
                                FFB_WRITE64(&ffb->dy, 0, 0);
 
380
                                FFB_WRITE64_2(&ffb->bh, ffp->fastfill_height, (ffp->fastfill_width * 4));
 
381
                                ffb->by = FFB_FASTFILL_BLOCK_X;
 
382
                                FFB_WRITE64(&ffb->dy, 0, 0);
 
383
                                FFB_WRITE64_2(&ffb->bh, ffp->pagefill_height, (ffp->pagefill_width * 4));
 
384
                                FFB_WRITE64_3(&ffb->dy, paligned_y, paligned_x);
 
385
                                ffb->bh = paligned_h;
 
386
                                FFB_WRITE64(&ffb->by, FFB_FASTFILL_PAGE, paligned_w);
 
387
 
 
388
                                if(extra_work) {
 
389
                                        register int nfixups;
 
390
 
 
391
                                        /* Ok, we're going to do at least one fixup. */
 
392
                                        nfixups = CreatorComputePageFillFixups(pFfb->Pf_Fixups,
 
393
                                                                               x, y, w, h,
 
394
                                                                               paligned_x, paligned_y,
 
395
                                                                               paligned_w, paligned_h);
 
396
 
 
397
                                        /* NOTE: For the highres case we have already
 
398
                                         *       aligned the outermost X and W coordinates.
 
399
                                         *       Therefore we can be assured that the fixup
 
400
                                         *       X and W coordinates below will be 8 pixel
 
401
                                         *       aligned as well.  Do the math, it works. -DaveM
 
402
                                         */
 
403
 
 
404
                                        FFBFifo(pFfb, 5 + (nfixups * 5));
 
405
                                        ffb->by = FFB_FASTFILL_COLOR_BLK;
 
406
                                        FFB_WRITE64(&ffb->dy, 0, 0);
 
407
                                        FFB_WRITE64_2(&ffb->bh, ffp->fastfill_height, (ffp->fastfill_width * 4));
 
408
 
 
409
                                        while(--nfixups >= 0) {
 
410
                                                register int xx, yy, ww, hh;
 
411
 
 
412
                                                xx = pFfb->Pf_Fixups[nfixups].x;
 
413
                                                yy = pFfb->Pf_Fixups[nfixups].y;
 
414
                                                FFB_WRITE64(&ffb->dy, yy, xx);
 
415
                                                ww = (pFfb->Pf_Fixups[nfixups].width +
 
416
                                                      (xx & (ffp->fastfill_width - 1)));
 
417
                                                hh = (pFfb->Pf_Fixups[nfixups].height +
 
418
                                                      (yy & (ffp->fastfill_height - 1)));
 
419
                                                FFBLOG(("FIXUP(%08x:%08x:%08x:%08x) ",
 
420
                                                        xx, yy, ww, hh));
 
421
                                                if(nfixups != 0) {
 
422
                                                        ffb->by = FFB_FASTFILL_BLOCK;
 
423
                                                        FFB_WRITE64_2(&ffb->bh, hh, ww);
 
424
                                                } else {
 
425
                                                        ffb->bh = hh;
 
426
                                                        FFB_WRITE64(&ffb->by, FFB_FASTFILL_BLOCK, ww);
 
427
                                                }
 
428
                                        }
 
429
                                }
 
430
                        }
 
431
                }
 
432
        next_rect:
 
433
                ;
 
434
        }
 
435
        FFBLOG(("\n"));
 
436
}
 
437
 
 
438
void
 
439
CreatorFillBoxSolid (DrawablePtr pDrawable, int nBox, BoxPtr pBox, unsigned long pixel)
 
440
{
 
441
        FFBPtr pFfb = GET_FFB_FROM_SCREEN (pDrawable->pScreen);
 
442
        WindowPtr pWin = (WindowPtr) pDrawable;
 
443
 
 
444
        FFBLOG(("CreatorFillBoxSolid: nbox(%d)\n", nBox));
 
445
        FFB_ATTR_FFWIN(pFfb, pWin,
 
446
                       FFB_PPC_APE_DISABLE | FFB_PPC_CS_CONST,
 
447
                       pixel);
 
448
        if (PAGEFILL_DISABLED(pFfb))
 
449
                CreatorBoxFillNormal(pFfb, nBox, pBox);
 
450
        else
 
451
                CreatorBoxFillPage(pFfb, nBox, pBox);
 
452
 
 
453
        pFfb->rp_active = 1;
 
454
        FFBSync(pFfb, pFfb->regs);
 
455
}
 
456
 
 
457
static void
 
458
FFBSetStippleFast(FFBPtr pFfb, ffb_fbcPtr ffb,
 
459
                  CreatorStipplePtr stipple,
 
460
                  unsigned int ppc, unsigned int ppc_mask)
 
461
{
 
462
        ppc |= FFB_PPC_APE_ENABLE | FFB_PPC_TBE_TRANSPARENT | FFB_PPC_XS_WID;
 
463
        ppc_mask |= FFB_PPC_APE_MASK | FFB_PPC_TBE_MASK | FFB_PPC_XS_MASK;
 
464
        FFB_WRITE_PPC(pFfb, ffb, ppc, ppc_mask);
 
465
        FFB_WRITE_ROP(pFfb, ffb, (FFB_ROP_EDIT_BIT|stipple->alu)|(FFB_ROP_NEW<<8));
 
466
        FFB_WRITE_FG(pFfb, ffb, stipple->fg);
 
467
        FFBFifo(pFfb, 32);
 
468
        FFB_STIPPLE_LOAD(&ffb->pattern[0], &stipple->bits[0]);
 
469
}
 
470
 
 
471
static void
 
472
FFBSetStippleFastIdentity(FFBPtr pFfb,
 
473
                          ffb_fbcPtr ffb,
 
474
                          CreatorStipplePtr stipple)
 
475
{
 
476
        int i;
 
477
 
 
478
        FFB_WRITE_FG(pFfb, ffb, stipple->bg);
 
479
        FFBFifo(pFfb, 32);
 
480
        for(i = 0; i < 32; i++)
 
481
                ffb->pattern[i] = ~stipple->bits[i];
 
482
        stipple->inhw = 0;
 
483
        pFfb->laststipple = NULL;
 
484
}
 
485
 
 
486
void
 
487
CreatorPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill, xRectangle *prectInit)
 
488
{
 
489
        FFBPtr pFfb = GET_FFB_FROM_SCREEN (pDrawable->pScreen);
 
490
        ffb_fbcPtr ffb = pFfb->regs;
 
491
        xRectangle      *prect;
 
492
        RegionPtr       prgnClip;
 
493
        register BoxPtr pbox;
 
494
        register BoxPtr pboxClipped;
 
495
        BoxPtr          pboxClippedBase;
 
496
        BoxPtr          pextent;
 
497
        CreatorPrivGCPtr gcPriv;
 
498
        int             numRects;
 
499
        int             n;
 
500
        int             xorg, yorg;
 
501
    
 
502
        /* No garbage please. */
 
503
        if (nrectFill <= 0)
 
504
                return;
 
505
 
 
506
        gcPriv = CreatorGetGCPrivate (pGC);
 
507
        FFBLOG(("CreatorPolyFillRect: nrect(%d) ALU(%x) STIP(%p) pmsk(%08x)\n",
 
508
                nrectFill, pGC->alu, gcPriv->stipple, pGC->planemask));
 
509
        prgnClip = cfbGetCompositeClip(pGC);
 
510
        prect = prectInit;
 
511
        xorg = pDrawable->x;
 
512
        yorg = pDrawable->y;
 
513
        if (xorg || yorg) {
 
514
                prect = prectInit;
 
515
                n = nrectFill;
 
516
                while (n--) {
 
517
                        prect->x += xorg;
 
518
                        prect->y += yorg;
 
519
                        prect++;
 
520
                }
 
521
        }
 
522
 
 
523
        prect = prectInit;
 
524
        numRects = REGION_NUM_RECTS (prgnClip) * nrectFill;
 
525
        if (numRects > 64) {
 
526
                pboxClippedBase = (BoxPtr)ALLOCATE_LOCAL(numRects * sizeof(BoxRec));
 
527
                if (!pboxClippedBase)
 
528
                        return;
 
529
        } else
 
530
                pboxClippedBase = pFfb->ClippedBoxBuf;
 
531
 
 
532
        pboxClipped = pboxClippedBase;
 
533
        if (REGION_NUM_RECTS(prgnClip) == 1) {
 
534
                int x1, y1, x2, y2, bx2, by2;
 
535
 
 
536
                pextent = REGION_RECTS(prgnClip);
 
537
                x1 = pextent->x1;
 
538
                y1 = pextent->y1;
 
539
                x2 = pextent->x2;
 
540
                y2 = pextent->y2;
 
541
                while (nrectFill--) {
 
542
                        if ((pboxClipped->x1 = prect->x) < x1)
 
543
                                pboxClipped->x1 = x1;
 
544
 
 
545
                        if ((pboxClipped->y1 = prect->y) < y1)
 
546
                                pboxClipped->y1 = y1;
 
547
 
 
548
                        bx2 = (int) prect->x + (int) prect->width;
 
549
                        if (bx2 > x2)
 
550
                                bx2 = x2;
 
551
                        pboxClipped->x2 = bx2;
 
552
 
 
553
                        by2 = (int) prect->y + (int) prect->height;
 
554
                        if (by2 > y2)
 
555
                                by2 = y2;
 
556
                        pboxClipped->y2 = by2;
 
557
 
 
558
                        prect++;
 
559
                        if ((pboxClipped->x1 < pboxClipped->x2) &&
 
560
                            (pboxClipped->y1 < pboxClipped->y2))
 
561
                                pboxClipped++;
 
562
                }
 
563
        } else {
 
564
                int x1, y1, x2, y2, bx2, by2;
 
565
 
 
566
                pextent = REGION_EXTENTS(pGC->pScreen, prgnClip);
 
567
                x1 = pextent->x1;
 
568
                y1 = pextent->y1;
 
569
                x2 = pextent->x2;
 
570
                y2 = pextent->y2;
 
571
                while (nrectFill--) {
 
572
                        BoxRec box;
 
573
 
 
574
                        if ((box.x1 = prect->x) < x1)
 
575
                                box.x1 = x1;
 
576
 
 
577
                        if ((box.y1 = prect->y) < y1)
 
578
                                box.y1 = y1;
 
579
 
 
580
                        bx2 = (int) prect->x + (int) prect->width;
 
581
                        if (bx2 > x2)
 
582
                                bx2 = x2;
 
583
                        box.x2 = bx2;
 
584
 
 
585
                        by2 = (int) prect->y + (int) prect->height;
 
586
                        if (by2 > y2)
 
587
                                by2 = y2;
 
588
                        box.y2 = by2;
 
589
 
 
590
                        prect++;
 
591
 
 
592
                        if ((box.x1 >= box.x2) || (box.y1 >= box.y2))
 
593
                                continue;
 
594
 
 
595
                        n = REGION_NUM_RECTS (prgnClip);
 
596
                        pbox = REGION_RECTS(prgnClip);
 
597
 
 
598
                        /* Clip the rectangle to each box in the clip region
 
599
                         * this is logically equivalent to calling Intersect()
 
600
                         */
 
601
                        while(n--) {
 
602
                                pboxClipped->x1 = max(box.x1, pbox->x1);
 
603
                                pboxClipped->y1 = max(box.y1, pbox->y1);
 
604
                                pboxClipped->x2 = min(box.x2, pbox->x2);
 
605
                                pboxClipped->y2 = min(box.y2, pbox->y2);
 
606
                                pbox++;
 
607
 
 
608
                                /* see if clipping left anything */
 
609
                                if(pboxClipped->x1 < pboxClipped->x2 &&
 
610
                                   pboxClipped->y1 < pboxClipped->y2)
 
611
                                        pboxClipped++;
 
612
                        }
 
613
                }
 
614
        }
 
615
        /* Now fill the pre-clipped boxes. */
 
616
        if(pboxClipped != pboxClippedBase) {
 
617
                enum ffb_fillrect_method how = fillrect_page;
 
618
                int num = (pboxClipped - pboxClippedBase);
 
619
                int f_w = pboxClippedBase->x2 - pboxClippedBase->x1;
 
620
                int f_h = pboxClippedBase->y2 - pboxClippedBase->y1;
 
621
                WindowPtr pWin = (WindowPtr) pDrawable;
 
622
                unsigned int fbc = FFB_FBC_WIN(pWin);
 
623
                unsigned int drawop = FFB_DRAWOP_FASTFILL;
 
624
 
 
625
                if (PAGEFILL_DISABLED(pFfb) ||
 
626
                    pGC->alu != GXcopy ||
 
627
                    BOX_AREA(f_w, f_h) < 128) {
 
628
                        drawop = FFB_DRAWOP_RECTANGLE;
 
629
                        how = fillrect_normal;
 
630
                } else if (gcPriv->stipple != NULL) {
 
631
                        if (FASTFILL_AP_DISABLED(pFfb)) {
 
632
                                drawop = FFB_DRAWOP_RECTANGLE;
 
633
                                how = fillrect_normal;
 
634
                        } else {
 
635
                                if ((gcPriv->stipple->alu & FFB_ROP_EDIT_BIT) != 0)
 
636
                                        how = fillrect_fast;
 
637
                                else
 
638
                                        how = fillrect_fast_opaque;
 
639
                        }
 
640
                } else {
 
641
                        int all_planes;
 
642
 
 
643
                        /* Plane masks are not controllable with page fills. */
 
644
                        if (pGC->depth == 8)
 
645
                                all_planes = 0xff;
 
646
                        else
 
647
                                all_planes = 0xffffff;
 
648
                        if ((pGC->planemask & all_planes) != all_planes)
 
649
                                how = fillrect_fast;
 
650
                }
 
651
 
 
652
                if (how == fillrect_page) {
 
653
                        fbc &= ~(FFB_FBC_XE_MASK | FFB_FBC_RGBE_MASK);
 
654
                        fbc |= FFB_FBC_XE_ON | FFB_FBC_RGBE_ON;
 
655
                }
 
656
 
 
657
                /* In the high-resolution modes, the Creator3D transforms
 
658
                 * the framebuffer such that the dual-buffers present become
 
659
                 * one large single buffer.  As such you need to enable both
 
660
                 * A and B write buffers for page/fast fills to work properly
 
661
                 * under this configuration. -DaveM
 
662
                 */
 
663
                if (pFfb->ffb_res == ffb_res_high)
 
664
                        fbc |= FFB_FBC_WB_B;
 
665
 
 
666
                /* Setup the attributes. */
 
667
                if (gcPriv->stipple == NULL) {
 
668
                        FFB_ATTR_RAW(pFfb,
 
669
                                     FFB_PPC_APE_DISABLE|FFB_PPC_CS_CONST|FFB_PPC_XS_WID,
 
670
                                     FFB_PPC_APE_MASK|FFB_PPC_CS_MASK|FFB_PPC_XS_MASK,
 
671
                                     pGC->planemask,
 
672
                                     ((FFB_ROP_EDIT_BIT|pGC->alu)|(FFB_ROP_NEW<<8)),
 
673
                                     drawop,
 
674
                                     pGC->fgPixel,
 
675
                                     fbc, FFB_WID_WIN(pWin));
 
676
                } else {
 
677
                        if (how == fillrect_fast_opaque) {
 
678
                                FFBSetStippleFast(pFfb, ffb, gcPriv->stipple,
 
679
                                                  FFB_PPC_CS_CONST|FFB_PPC_XS_WID,
 
680
                                                  FFB_PPC_CS_MASK|FFB_PPC_XS_MASK);
 
681
                        } else {
 
682
                                FFBSetStipple(pFfb, ffb, gcPriv->stipple,
 
683
                                              FFB_PPC_CS_CONST|FFB_PPC_XS_WID,
 
684
                                              FFB_PPC_CS_MASK|FFB_PPC_XS_MASK);
 
685
                        }
 
686
                        FFB_WRITE_DRAWOP(pFfb, ffb, drawop);
 
687
                        FFB_WRITE_FBC(pFfb, ffb, fbc);
 
688
                        FFB_WRITE_WID(pFfb, ffb, FFB_WID_WIN(pWin));
 
689
                }
 
690
 
 
691
                /* Now render. */
 
692
                if(how == fillrect_normal)
 
693
                        CreatorBoxFillNormal(pFfb, num, pboxClippedBase);
 
694
                else if(how == fillrect_fast || how == fillrect_fast_opaque)
 
695
                        CreatorBoxFillFast(pFfb, num, pboxClippedBase);
 
696
                else
 
697
                        CreatorBoxFillPage(pFfb, num, pboxClippedBase);
 
698
 
 
699
                if(how == fillrect_fast_opaque) {
 
700
                        FFBSetStippleFastIdentity(pFfb, ffb, gcPriv->stipple);
 
701
                        CreatorBoxFillFast(pFfb, num, pboxClippedBase);
 
702
                }
 
703
 
 
704
                pFfb->rp_active = 1;
 
705
                FFBSync(pFfb, ffb);
 
706
        }
 
707
        if (pboxClippedBase != pFfb->ClippedBoxBuf)
 
708
                DEALLOCATE_LOCAL (pboxClippedBase);
 
709
}