2
* Acceleration for the Creator and Creator3D framebuffer - Rectangle filling.
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)
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:
15
* The above copyright notice and this permission notice shall be included in
16
* all copies or substantial portions of the Software.
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.
27
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_frect.c,v 1.3 2001/04/05 17:42:33 dawes Exp $ */
31
#include "ffb_rcache.h"
34
#include "ffb_loops.h"
36
#include "pixmapstr.h"
37
#include "scrnintstr.h"
44
#define PAGEFILL_DISABLED(pFfb) ((pFfb)->disable_pagefill != 0)
45
#define FASTFILL_AP_DISABLED(pFfb) ((pFfb)->disable_fastfill_ap != 0)
48
CreatorFillBoxStipple (DrawablePtr pDrawable, int nBox, BoxPtr pBox, CreatorStipplePtr stipple)
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;
56
FFBLOG(("CreatorFillBoxStipple: nbox(%d)\n", nBox));
57
newalign = ((pDrawable->y & 31) << 16) | (pDrawable->x & 31);
58
if (stipple->patalign != newalign) {
61
x = (pDrawable->x - (stipple->patalign & 0xffff)) & 31;
62
y = (pDrawable->y - (stipple->patalign >> 16)) & 31;
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));
70
stipple->patalign = newalign;
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));
82
register int x, y, w, h;
89
FFB_WRITE64(&ffb->by, y, x);
90
FFB_WRITE64_2(&ffb->bh, h, w);
98
enum ffb_fillrect_method { fillrect_page,
99
fillrect_fast, fillrect_fast_opaque,
102
#define BOX_AREA(__w, __h) ((int)(__w) * (int)(__h))
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.
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)); \
116
px = pFfb->Pf_AlignTab[x + (pf_bw - 1)]; \
118
ph = ((h - ydiff) & ~(pf_bh - 1)); \
122
pw = pFfb->Pf_AlignTab[w - xdiff]; \
126
ework = (((xdiff > 0) || \
129
((h - ph) > 0))) ? 1 : 0; \
134
/* Compute fixups of non-page aligned areas after a page fill.
135
* Return the number of fixups needed.
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)
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;
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;
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;
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;
180
/* Fill a set of boxes, pagefill and fastfill not allowed. */
182
CreatorBoxFillNormal(FFBPtr pFfb,
183
int nbox, BoxPtr pbox)
185
ffb_fbcPtr ffb = pFfb->regs;
187
FFBLOG(("BFNormal: "));
189
FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_RECTANGLE);
191
register int x, y, w, h;
198
FFBLOG(("[%08x:%08x:%08x:%08x] ", x, y, w, h));
200
FFB_WRITE64(&ffb->by, y, x);
201
FFB_WRITE64_2(&ffb->bh, h, w);
206
/* Fill a set of boxes, only non-pagemode fastfill is allowed. */
208
CreatorBoxFillFast(FFBPtr pFfb,
209
int nbox, BoxPtr pbox)
211
ffb_fbcPtr ffb = pFfb->regs;
213
FFBLOG(("BFFast: "));
215
struct fastfill_parms *ffp = &FFB_FFPARMS(pFfb);
216
register int x, y, w, h;
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) ",
227
FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_RECTANGLE);
229
FFB_WRITE64(&ffb->by, y, x);
230
FFB_WRITE64_2(&ffb->bh, h, w);
232
FFBLOG(("FST(%08x:%08x:%08x:%08x:[%08x:%08x]) ",
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);
247
FFB_WRITE64(&ffb->by, y, nx);
248
FFB_WRITE64_2(&ffb->bh, h, nw);
258
FFB_WRITE64(&ffb->by, y, nx);
259
FFB_WRITE64_2(&ffb->bh, h, nw);
265
FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_FASTFILL);
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))));
283
/* Fill a set of boxes, any fastfill method is allowed. */
285
CreatorBoxFillPage(FFBPtr pFfb,
286
int nbox, BoxPtr pbox)
288
ffb_fbcPtr ffb = pFfb->regs;
290
FFBLOG(("BFPage: "));
292
struct fastfill_parms *ffp = &FFB_FFPARMS(pFfb);
293
register int x, y, w, h;
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) ",
304
FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_RECTANGLE);
306
FFB_WRITE64(&ffb->by, y, x);
307
FFB_WRITE64_2(&ffb->bh, h, w);
309
int paligned_y, paligned_x;
310
int paligned_h, paligned_w = 0;
313
if (pFfb->ffb_res == ffb_res_high &&
314
((x & 7) != 0 || (w & 7) != 0)) {
315
FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_RECTANGLE);
324
FFB_WRITE64(&ffb->by, y, nx);
325
FFB_WRITE64_2(&ffb->bh, h, nw);
335
FFB_WRITE64(&ffb->by, y, nx);
336
FFB_WRITE64_2(&ffb->bh, h, nw);
343
FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_FASTFILL);
344
if((w < (ffp->pagefill_width<<1)) ||
345
(h < (ffp->pagefill_height<<1)))
348
CreatorPageFillParms(pFfb, ffp,
350
paligned_x, paligned_y,
351
paligned_w, paligned_h, extra_work);
353
/* See if the aligned area is large enough for
354
* page fill to be worthwhile.
357
BOX_AREA(paligned_w, paligned_h) < ffp->pagefill_small_area) {
359
FFBLOG(("FST(%08x:%08x:%08x:%08x:[%08x:%08x]) ",
361
(w + (x & (ffp->fastfill_width - 1))),
362
(h + (y & (ffp->fastfill_height - 1)))));
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))));
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));
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);
389
register int nfixups;
391
/* Ok, we're going to do at least one fixup. */
392
nfixups = CreatorComputePageFillFixups(pFfb->Pf_Fixups,
394
paligned_x, paligned_y,
395
paligned_w, paligned_h);
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
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));
409
while(--nfixups >= 0) {
410
register int xx, yy, ww, hh;
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) ",
422
ffb->by = FFB_FASTFILL_BLOCK;
423
FFB_WRITE64_2(&ffb->bh, hh, ww);
426
FFB_WRITE64(&ffb->by, FFB_FASTFILL_BLOCK, ww);
439
CreatorFillBoxSolid (DrawablePtr pDrawable, int nBox, BoxPtr pBox, unsigned long pixel)
441
FFBPtr pFfb = GET_FFB_FROM_SCREEN (pDrawable->pScreen);
442
WindowPtr pWin = (WindowPtr) pDrawable;
444
FFBLOG(("CreatorFillBoxSolid: nbox(%d)\n", nBox));
445
FFB_ATTR_FFWIN(pFfb, pWin,
446
FFB_PPC_APE_DISABLE | FFB_PPC_CS_CONST,
448
if (PAGEFILL_DISABLED(pFfb))
449
CreatorBoxFillNormal(pFfb, nBox, pBox);
451
CreatorBoxFillPage(pFfb, nBox, pBox);
454
FFBSync(pFfb, pFfb->regs);
458
FFBSetStippleFast(FFBPtr pFfb, ffb_fbcPtr ffb,
459
CreatorStipplePtr stipple,
460
unsigned int ppc, unsigned int ppc_mask)
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);
468
FFB_STIPPLE_LOAD(&ffb->pattern[0], &stipple->bits[0]);
472
FFBSetStippleFastIdentity(FFBPtr pFfb,
474
CreatorStipplePtr stipple)
478
FFB_WRITE_FG(pFfb, ffb, stipple->bg);
480
for(i = 0; i < 32; i++)
481
ffb->pattern[i] = ~stipple->bits[i];
483
pFfb->laststipple = NULL;
487
CreatorPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill, xRectangle *prectInit)
489
FFBPtr pFfb = GET_FFB_FROM_SCREEN (pDrawable->pScreen);
490
ffb_fbcPtr ffb = pFfb->regs;
493
register BoxPtr pbox;
494
register BoxPtr pboxClipped;
495
BoxPtr pboxClippedBase;
497
CreatorPrivGCPtr gcPriv;
502
/* No garbage please. */
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);
524
numRects = REGION_NUM_RECTS (prgnClip) * nrectFill;
526
pboxClippedBase = (BoxPtr)ALLOCATE_LOCAL(numRects * sizeof(BoxRec));
527
if (!pboxClippedBase)
530
pboxClippedBase = pFfb->ClippedBoxBuf;
532
pboxClipped = pboxClippedBase;
533
if (REGION_NUM_RECTS(prgnClip) == 1) {
534
int x1, y1, x2, y2, bx2, by2;
536
pextent = REGION_RECTS(prgnClip);
541
while (nrectFill--) {
542
if ((pboxClipped->x1 = prect->x) < x1)
543
pboxClipped->x1 = x1;
545
if ((pboxClipped->y1 = prect->y) < y1)
546
pboxClipped->y1 = y1;
548
bx2 = (int) prect->x + (int) prect->width;
551
pboxClipped->x2 = bx2;
553
by2 = (int) prect->y + (int) prect->height;
556
pboxClipped->y2 = by2;
559
if ((pboxClipped->x1 < pboxClipped->x2) &&
560
(pboxClipped->y1 < pboxClipped->y2))
564
int x1, y1, x2, y2, bx2, by2;
566
pextent = REGION_EXTENTS(pGC->pScreen, prgnClip);
571
while (nrectFill--) {
574
if ((box.x1 = prect->x) < x1)
577
if ((box.y1 = prect->y) < y1)
580
bx2 = (int) prect->x + (int) prect->width;
585
by2 = (int) prect->y + (int) prect->height;
592
if ((box.x1 >= box.x2) || (box.y1 >= box.y2))
595
n = REGION_NUM_RECTS (prgnClip);
596
pbox = REGION_RECTS(prgnClip);
598
/* Clip the rectangle to each box in the clip region
599
* this is logically equivalent to calling Intersect()
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);
608
/* see if clipping left anything */
609
if(pboxClipped->x1 < pboxClipped->x2 &&
610
pboxClipped->y1 < pboxClipped->y2)
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;
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;
635
if ((gcPriv->stipple->alu & FFB_ROP_EDIT_BIT) != 0)
638
how = fillrect_fast_opaque;
643
/* Plane masks are not controllable with page fills. */
647
all_planes = 0xffffff;
648
if ((pGC->planemask & all_planes) != all_planes)
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;
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
663
if (pFfb->ffb_res == ffb_res_high)
666
/* Setup the attributes. */
667
if (gcPriv->stipple == NULL) {
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,
672
((FFB_ROP_EDIT_BIT|pGC->alu)|(FFB_ROP_NEW<<8)),
675
fbc, FFB_WID_WIN(pWin));
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);
682
FFBSetStipple(pFfb, ffb, gcPriv->stipple,
683
FFB_PPC_CS_CONST|FFB_PPC_XS_WID,
684
FFB_PPC_CS_MASK|FFB_PPC_XS_MASK);
686
FFB_WRITE_DRAWOP(pFfb, ffb, drawop);
687
FFB_WRITE_FBC(pFfb, ffb, fbc);
688
FFB_WRITE_WID(pFfb, ffb, FFB_WID_WIN(pWin));
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);
697
CreatorBoxFillPage(pFfb, num, pboxClippedBase);
699
if(how == fillrect_fast_opaque) {
700
FFBSetStippleFastIdentity(pFfb, ffb, gcPriv->stipple);
701
CreatorBoxFillFast(pFfb, num, pboxClippedBase);
707
if (pboxClippedBase != pFfb->ClippedBoxBuf)
708
DEALLOCATE_LOCAL (pboxClippedBase);