summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaleb Keithley <kaleb@freedesktop.org>2003-11-14 16:48:55 +0000
committerKaleb Keithley <kaleb@freedesktop.org>2003-11-14 16:48:55 +0000
commit68c56916d79bf06e26e01c3e84206edc928d9b51 (patch)
treed39c13092dc680721e163e448a57df847a6fad62
Initial revision
-rw-r--r--man/sunffb.man30
-rw-r--r--src/VISmoveImage.s2710
-rw-r--r--src/ffb.h325
-rw-r--r--src/ffb_accel.c961
-rw-r--r--src/ffb_asm.s349
-rw-r--r--src/ffb_attr.c256
-rw-r--r--src/ffb_bcopy.c561
-rw-r--r--src/ffb_checks.c288
-rw-r--r--src/ffb_circle.c210
-rw-r--r--src/ffb_clip.c103
-rw-r--r--src/ffb_clip.h49
-rw-r--r--src/ffb_cplane.c393
-rw-r--r--src/ffb_cursor.c139
-rw-r--r--src/ffb_dac.c612
-rw-r--r--src/ffb_dac.h365
-rw-r--r--src/ffb_dbe.c902
-rw-r--r--src/ffb_ddc.c195
-rw-r--r--src/ffb_dga.c280
-rw-r--r--src/ffb_dri.c529
-rw-r--r--src/ffb_drishare.h53
-rw-r--r--src/ffb_driver.c1122
-rw-r--r--src/ffb_fifo.h69
-rw-r--r--src/ffb_frect.c709
-rw-r--r--src/ffb_fspans.c121
-rw-r--r--src/ffb_gc.c754
-rw-r--r--src/ffb_gc.h151
-rw-r--r--src/ffb_glyph.c380
-rw-r--r--src/ffb_gspans.c130
-rw-r--r--src/ffb_line.c195
-rw-r--r--src/ffb_loops.h212
-rw-r--r--src/ffb_plygon.c167
-rw-r--r--src/ffb_point.c108
-rw-r--r--src/ffb_rcache.h333
-rw-r--r--src/ffb_rect.c207
-rw-r--r--src/ffb_regs.h509
-rw-r--r--src/ffb_seg.c196
-rw-r--r--src/ffb_sspans.c166
-rw-r--r--src/ffb_stip.c64
-rw-r--r--src/ffb_stip.h36
-rw-r--r--src/ffb_stubs.c544
-rw-r--r--src/ffb_wid.c464
-rw-r--r--src/ffb_wline.c896
-rw-r--r--src/ffb_zeroarc.c536
43 files changed, 17379 insertions, 0 deletions
diff --git a/man/sunffb.man b/man/sunffb.man
new file mode 100644
index 0000000..e30c73a
--- /dev/null
+++ b/man/sunffb.man
@@ -0,0 +1,30 @@
+.\" $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/sunffb.man,v 1.2 2001/01/27 18:20:54 dawes Exp $
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH FFB __drivermansuffix__ __vendorversion__
+.SH NAME
+ffb \- SUNFFB video driver
+.SH SYNOPSIS
+.nf
+.B "Section \*qDevice\*q"
+.BI " Identifier \*q" devname \*q
+.B " Driver \*qsunffb\*q"
+\ \ ...
+.B EndSection
+.fi
+.SH DESCRIPTION
+.B ffb
+is an XFree86 driver for Sun Creator, Creator 3D and Elite 3D video cards.
+THIS MAN PAGE NEEDS TO BE FILLED IN.
+.SH SUPPORTED HARDWARE
+The
+.B ffb
+driver supports...
+.SH CONFIGURATION DETAILS
+Please refer to XF86Config(__filemansuffix__) for general configuration
+details. This section only covers configuration details specific to this
+driver.
+.SH "SEE ALSO"
+XFree86(1), XF86Config(__filemansuffix__), xf86config(1), Xserver(1), X(__miscmansuffix__)
+.SH AUTHORS
+Authors include: Jakub Jelinek <jakub@redhat.com>, David S. Miller <davem@redhat.com>, Michal Rehacek <majkl@iname.com>
diff --git a/src/VISmoveImage.s b/src/VISmoveImage.s
new file mode 100644
index 0000000..43815f5
--- /dev/null
+++ b/src/VISmoveImage.s
@@ -0,0 +1,2710 @@
+/*
+ * VISmoveImage.S: High speed moveImage operations utilizing the UltraSPARC
+ * Visual Instruction Set.
+ *
+ * Copyright (C) 1998,1999 Jakub Jelinek (jakub@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * JAKUB JELINEK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/VISmoveImage.s,v 1.2 2000/05/23 04:47:43 dawes Exp $ */
+
+
+/* NOTE NOTE NOTE: All loads in these routines _MUST_ be 64-byte block
+ * loads. If any non-block loads are done to the frame-
+ * buffer when prefetching is enabled (which we use, when
+ * available) this will cause lockups on FFB2 due to a
+ * hardware bug. -DaveM
+ */
+
+/*
+ void
+ VISmoveImageLR(unsigned char *src, unsigned char *dst, long w, long h, long skind, long dkind)
+ {
+ int i;
+
+ // Handles copying non-overlapping images and for overlapping images
+ // copying where dstx <= srcx.
+ // To copy overlapping images where dsty > srcy, set src and dst
+ // to start of the last scanline and negate both skind and dkind arguments.
+
+ assert(abs(skind) >= w && abs(dkind) >= w);
+
+ while (h--) {
+ for (i = 0; i < w; i++)
+ *d++ = *s++;
+ s += skind - w;
+ d += dkind - w;
+ }
+ }
+
+ void
+ VISmoveImageRL(unsigned char *src, unsigned char *dst, long w, long h, long skind, long dkind)
+ {
+ int i;
+
+ // Handles copying non-overlapping images and for overlapping images
+ // copying where dstx >= srcx.
+ // To copy overlapping images where dsty > srcy, set src and dst
+ // to start of the last scanline and negate both skind and dkind arguments.
+
+ assert(abs(skind) >= w && abs(dkind) >= w);
+
+ s += w;
+ d += w;
+ while (h--) {
+ for (i = 0; i < w; i++)
+ *--d = *--s;
+ s += skind + w;
+ d += dkind + w;
+ }
+ }
+
+ */
+
+#if defined(__sparc_v9__) || defined(__sparcv9) || defined(__arch64__)
+#define SMUL mulx
+#define ICC xcc
+#else
+#define SMUL smul
+#define ICC icc
+#endif
+
+#define ASI_PST8_P 0xc0
+#define ASI_BLK_P 0xf0
+#define SYNC 0x40
+
+/* Register usage: */
+/* integer registers: */
+#define src i0
+#define dst i1
+#define w i2
+#define h i3
+#define skind i4
+#define dkind i5
+#define branchbase l0
+#define tmp1 l1
+#define tmp4 l2
+#define tmp5 l3
+#define leftw l4
+#define rightw l5
+#define srcstart l6
+#define mode l7
+#define fregset o0 /* Must be [og]? for v8plusa */
+#define srcend o1
+#define srcn o2
+#define srcnext o3
+#define rightw2 o4
+#define tmp2 o5 /* Must be [og]? for v8plusa */
+#define narrow o7
+#define prepw g1 /* Must be [og]? for v8plusa */
+#define srcstop g2
+#define srcnotdone g3
+#define curw g4 /* Must be [og]? for v8plusa */
+#define leftw2 rightw2
+#define tmp3 g5 /* Must be [og]? for v8plusa */
+/* floating point registers: */
+#define ftmp1 f0
+#define ftmp2 f2
+#define ftmp3 f4
+#define ftmp4 f6
+#define ftmp5 f8
+#define ftmp6 f10
+#define ftmp7 f12
+#define ftmp8 f14
+#define store_regs f16-f31
+#define load_bank1 f32-f46
+#define load_bank2 f48-f62
+#define fnop fmovd %ftmp2, %ftmp2
+
+#define LOAD(f32,f46,tgt,tgtr) \
+ subcc %curw, 64, %curw; \
+ bleu,pn %ICC, tgt; \
+ fmovd %f46, %ftmp1; \
+ ldda [%src] ASI_BLK_P, %f32; \
+ add %src, 64, %src; \
+tgtr:
+
+#define PREPLOAD(f32,f46,tgt,tgtr) \
+ brlez,pn %prepw, tgt; \
+ fmovd %f46, %ftmp1; \
+ ldda [%src] ASI_BLK_P, %f32; \
+ add %src, 64, %src; \
+tgtr:
+
+#define STORE \
+ stda %f16, [%dst] ASI_BLK_P;
+
+#define FREG_FROB(f0,A0,F2,f2,A1,F4,f4,A2,F6,f6,A3,F8,f8,A4,F10,f10,A5,F12,f12,A6,F14,f14,A7,F16) \
+ A0 \
+ faligndata %f0,%F2,%f16; \
+ A1 \
+ faligndata %f2,%F4,%f18; \
+ A2 \
+ faligndata %f4,%F6,%f20; \
+ A3 \
+ faligndata %f6,%F8,%f22; \
+ A4 \
+ faligndata %f8,%F10,%f24; \
+ A5 \
+ faligndata %f10,%F12,%f26; \
+ A6 \
+ faligndata %f12,%F14,%f28; \
+ A7 \
+ faligndata %f14,%F16,%f30;
+
+ .section ".rodata"
+ .asciz "VISmoveImage (C) 1998,1999 Jakub Jelinek"
+
+/* The code might not be self-explanatory, but it was written to be processed
+ * by machines, not humans. Comments are deliberately left as an exercise
+ * to the occasional reader. */
+
+ .text
+ .globl VISmoveImageLR
+ .align 32
+VISmoveImageLR:
+ save %sp, -160, %sp ! Group 0
+0: rd %pc, %tmp3 ! Group 1
+ sub %src, %dst, %mode ! Group 7
+ brz,pn %h, return
+ neg %dst, %leftw ! Group 8
+ mov %src, %srcstart
+ andn %src, 63, %src ! Group 9
+ cmp %w, 128
+ blu,pn %ICC, prepare_narrow
+ and %mode, 63, %mode ! Group 10
+ add %dst, %w, %rightw
+ ldda [%src] ASI_BLK_P, %f32 ! Group 11
+ add %src, 64, %src ! Group 12
+ clr %narrow
+ ldda [%src] ASI_BLK_P, %f48 ! Group 13
+ and %leftw, 63, %leftw ! Group 14
+ sub %rightw, 1, %rightw
+ andn %dst, 63, %dst ! Group 15
+ and %rightw, 63, %rightw
+ alignaddr %mode, %g0, %g0 ! Group 16
+ add %rightw, 1, %rightw ! Group 17
+ clr %fregset
+ add %src, 64, %src ! Group 18
+ add %tmp3, (BranchBase - 0b), %branchbase
+ mov 64, %prepw ! Group 19
+ ba,pt %xcc, roll_wide
+ sub %h, 1, %srcnotdone
+prepare_narrow:
+#if defined(__sparc_v9__) || defined(__sparcv9) || defined(__arch64__)
+ brlez,pn %w, return
+#else
+ tst %w
+ ble,pn %icc, return
+#endif
+ add %dst, %w, %rightw ! Group 11
+ and %leftw, 63, %leftw
+ ldda [%src] ASI_BLK_P, %f32 ! Group 12
+ sub %rightw, 1, %rightw ! Group 13
+ andn %dst, 63, %dst
+ and %rightw, 63, %rightw ! Group 14
+ sub %w, %leftw, %tmp2
+ add %rightw, 1, %rightw ! Group 15
+ clr %fregset
+ subcc %tmp2, %rightw, %curw ! Group 16
+ and %srcstart, 63, %tmp1
+ mov %curw, %prepw ! Group 17
+ add %tmp1, %w, %tmp1
+ bg,pt %ICC, 1f
+ add %src, 64, %src ! Group 18
+ cmp %tmp1, 128
+ movg %icc, 64, %prepw ! Group 19
+1: add %srcstart, %w, %srcend
+ sub %h, 1, %srcnotdone ! Group 20
+ add %srcstart, %skind, %srcnext
+ add %srcend, 63, %tmp4 ! Group 21
+ andn %srcnext, 63, %srcnext
+ add %w, 64, %tmp2 ! Group 22
+ cmp %skind, 0
+ bl,pn %ICC, 1f
+ clr %srcstop ! Group 23
+ cmp %skind, %tmp2
+ bgeu,pt %ICC, 2f
+ andn %tmp4, 63, %tmp2 ! Group 24
+ SMUL %skind, %srcnotdone, %srcstop
+ ba,pt %xcc, 2f
+ add %tmp4, %srcstop, %srcstop
+1: addcc %tmp2, %skind, %g0
+ ble,pt %ICC, 2f
+ sub %srcnext, 64, %tmp2
+ SMUL %skind, %srcnotdone, %srcstop
+ sub %srcstart, 64, %narrow
+ add %srcstop, %narrow, %srcstop
+2: add %srcnext, 64, %narrow
+ andn %tmp4, 63, %srcend ! Group 25
+ mov %srcnext, %srcn
+ cmp %narrow, %srcend ! Group 26
+ andn %srcstop, 63, %srcstop
+ move %ICC, %tmp2, %srcnext ! Group 27
+ alignaddr %mode, %g0, %g0 ! Group 28
+ add %tmp3, (BranchBase - 0b), %branchbase
+ mov 1, %narrow ! Group 29
+ cmp %srcnext, %srcstop
+ move %ICC, 0, %srcnotdone ! Group 30
+ cmp %tmp1, 64
+ bleu,pn %ICC, 1f
+ dec %h ! Group 31
+ ldda [%src] ASI_BLK_P, %f48 ! Group 32
+ ba,pt %xcc, roll_narrow ! Group 33
+ addcc %src, 64, %src
+1: brz,a,pn %srcnotdone, roll_narrow
+ membar #Sync
+ ldda [%srcnext] ASI_BLK_P, %f48
+ ba,pt %xcc, roll_narrow
+ addcc %srcnext, 64, %src
+
+ .align 32
+prepr0: faligndata %f32, %f34, %f16
+ faligndata %f34, %f36, %f18
+ faligndata %f36, %f38, %f20
+ faligndata %f38, %f40, %f22
+ faligndata %f40, %f42, %f24
+ faligndata %f42, %f44, %f26
+ ba,pt %xcc, 4f
+ faligndata %f44, %f46, %f28
+ .align 32
+prepr1: faligndata %f48, %f50, %f16
+ faligndata %f50, %f52, %f18
+ faligndata %f52, %f54, %f20
+ faligndata %f54, %f56, %f22
+ faligndata %f56, %f58, %f24
+ faligndata %f58, %f60, %f26
+ ba,pt %xcc, 5f
+ faligndata %f60, %f62, %f28
+ .align 32
+prepr2: faligndata %f34, %f36, %f16
+ faligndata %f36, %f38, %f18
+ faligndata %f38, %f40, %f20
+ faligndata %f40, %f42, %f22
+ faligndata %f42, %f44, %f24
+ faligndata %f44, %f46, %f26
+ ba,pt %xcc, narrowst
+ faligndata %f46, %f0, %f28
+ .align 32
+prepr3: faligndata %f50, %f52, %f16
+ faligndata %f52, %f54, %f18
+ faligndata %f54, %f56, %f20
+ faligndata %f56, %f58, %f22
+ faligndata %f58, %f60, %f24
+ faligndata %f60, %f62, %f26
+ ba,pt %xcc, narrowst
+ faligndata %f62, %f0, %f28
+ .align 32
+prepr4: faligndata %f36, %f38, %f16
+ faligndata %f38, %f40, %f18
+ faligndata %f40, %f42, %f20
+ faligndata %f42, %f44, %f22
+ faligndata %f44, %f46, %f24
+ ba,pt %xcc, narrowst
+ faligndata %f46, %f0, %f26
+ .align 32
+prepr5: faligndata %f52, %f54, %f16
+ faligndata %f54, %f56, %f18
+ faligndata %f56, %f58, %f20
+ faligndata %f58, %f60, %f22
+ faligndata %f60, %f62, %f24
+ ba,pt %xcc, narrowst
+ faligndata %f62, %f0, %f26
+ .align 32
+prepr6: faligndata %f38, %f40, %f16
+ faligndata %f40, %f42, %f18
+ faligndata %f42, %f44, %f20
+ faligndata %f44, %f46, %f22
+ ba,pt %xcc, narrowst
+ faligndata %f46, %f0, %f24
+ .align 32
+prepr7: faligndata %f54, %f56, %f16
+ faligndata %f56, %f58, %f18
+ faligndata %f58, %f60, %f20
+ faligndata %f60, %f62, %f22
+ ba,pt %xcc, narrowst
+ faligndata %f62, %f0, %f24
+ .align 32
+prepr8: faligndata %f40, %f42, %f16
+ faligndata %f42, %f44, %f18
+ faligndata %f44, %f46, %f20
+ ba,pt %xcc, narrowst
+ faligndata %f46, %f0, %f22
+ .align 32
+prepr9: faligndata %f56, %f58, %f16
+ faligndata %f58, %f60, %f18
+ faligndata %f60, %f62, %f20
+ ba,pt %xcc, narrowst
+ faligndata %f62, %f0, %f22
+ .align 32
+prepr10:faligndata %f42, %f44, %f16
+ faligndata %f44, %f46, %f18
+ ba,pt %xcc, narrowst
+ faligndata %f46, %f0, %f20
+ .align 32
+prepr11:faligndata %f58, %f60, %f16
+ faligndata %f60, %f62, %f18
+ ba,pt %xcc, narrowst
+ faligndata %f62, %f0, %f20
+ .align 32
+prepr12:faligndata %f44, %f46, %f16
+ ba,pt %xcc, narrowst
+ faligndata %f46, %f0, %f18
+ .align 32
+prepr13:faligndata %f60, %f62, %f16
+ ba,pt %xcc, narrowst
+ faligndata %f62, %f0, %f18
+ .align 32
+prepr14:ba,pt %xcc, narrowst
+ faligndata %f46, %f0, %f16
+ nop
+ nop
+4: ba,pt %xcc, narrowst
+ faligndata %f46, %f0, %f30
+ .align 32
+prepr15:ba,pt %xcc, narrowst
+ faligndata %f62, %f0, %f16
+ nop
+ nop
+5: ba,pt %xcc, narrowst
+ faligndata %f62, %f0, %f30
+
+ .align 32
+prepn0: faligndata %ftmp1, %f32, %f30
+ ba,pt %xcc, leftst
+ mov (vis0 - BranchBase), %tmp3
+ nop
+1: ba,pt %xcc, leftst
+ mov (vis12 - BranchBase), %tmp3
+ .align 32
+prepn1: faligndata %ftmp1, %f48, %f30
+ ba,pt %xcc, leftst
+ mov (vis1 - BranchBase), %tmp3
+ nop
+2: ba,pt %xcc, leftst
+ mov (vis13 - BranchBase), %tmp3
+ .align 32
+prepn2: faligndata %ftmp1, %f32, %f28
+ faligndata %f32, %f34, %f30
+ ba,pt %xcc, leftst
+ mov (vis2 - BranchBase), %tmp3
+3: faligndata %f44, %f46, %f30
+ ba,pt %xcc, leftst
+ mov (vis14 - BranchBase), %tmp3
+ .align 32
+prepn3: faligndata %ftmp1, %f48, %f28
+ faligndata %f48, %f50, %f30
+ ba,pt %xcc, leftst
+ mov (vis3 - BranchBase), %tmp3
+ .align 32
+prepn4: faligndata %ftmp1, %f32, %f26
+ faligndata %f32, %f34, %f28
+ faligndata %f34, %f36, %f30
+ ba,pt %xcc, leftst
+ mov (vis4 - BranchBase), %tmp3
+ .align 32
+prepn5: faligndata %ftmp1, %f48, %f26
+ faligndata %f48, %f50, %f28
+ faligndata %f50, %f52, %f30
+ ba,pt %xcc, leftst
+ mov (vis5 - BranchBase), %tmp3
+ .align 32
+prepn6: faligndata %ftmp1, %f32, %f24
+ faligndata %f32, %f34, %f26
+ faligndata %f34, %f36, %f28
+ faligndata %f36, %f38, %f30
+ ba,pt %xcc, leftst
+ mov (vis6 - BranchBase), %tmp3
+ .align 32
+prepn7: faligndata %ftmp1, %f48, %f24
+ faligndata %f48, %f50, %f26
+ faligndata %f50, %f52, %f28
+ faligndata %f52, %f54, %f30
+ ba,pt %xcc, leftst
+ mov (vis7 - BranchBase), %tmp3
+ .align 32
+prepn8: faligndata %ftmp1, %f32, %f22
+ faligndata %f32, %f34, %f24
+ faligndata %f34, %f36, %f26
+ faligndata %f36, %f38, %f28
+ faligndata %f38, %f40, %f30
+ ba,pt %xcc, leftst
+ mov (vis8 - BranchBase), %tmp3
+ .align 32
+prepn9: faligndata %ftmp1, %f48, %f22
+ faligndata %f48, %f50, %f24
+ faligndata %f50, %f52, %f26
+ faligndata %f52, %f54, %f28
+ faligndata %f54, %f56, %f30
+ ba,pt %xcc, leftst
+ mov (vis9 - BranchBase), %tmp3
+ .align 32
+prepn10:faligndata %ftmp1, %f32, %f20
+ faligndata %f32, %f34, %f22
+ faligndata %f34, %f36, %f24
+ faligndata %f36, %f38, %f26
+ faligndata %f38, %f40, %f28
+ faligndata %f40, %f42, %f30
+ ba,pt %xcc, leftst
+ mov (vis10 - BranchBase), %tmp3
+ .align 32
+prepn11:faligndata %ftmp1, %f48, %f20
+ faligndata %f48, %f50, %f22
+ faligndata %f50, %f52, %f24
+ faligndata %f52, %f54, %f26
+ faligndata %f54, %f56, %f28
+ faligndata %f56, %f58, %f30
+ ba,pt %xcc, leftst
+ mov (vis11 - BranchBase), %tmp3
+ .align 32
+prepn12:faligndata %ftmp1, %f32, %f18
+ faligndata %f32, %f34, %f20
+ faligndata %f34, %f36, %f22
+ faligndata %f36, %f38, %f24
+ faligndata %f38, %f40, %f26
+ faligndata %f40, %f42, %f28
+ ba,pt %xcc, 1b
+ faligndata %f42, %f44, %f30
+ .align 32
+prepn13:faligndata %ftmp1, %f48, %f18
+ faligndata %f48, %f50, %f20
+ faligndata %f50, %f52, %f22
+ faligndata %f52, %f54, %f24
+ faligndata %f54, %f56, %f26
+ faligndata %f56, %f58, %f28
+ ba,pt %xcc, 2b
+ faligndata %f58, %f60, %f30
+ .align 32
+prepn14:faligndata %ftmp1, %f32, %f16
+ faligndata %f32, %f34, %f18
+ faligndata %f34, %f36, %f20
+ faligndata %f36, %f38, %f22
+ faligndata %f38, %f40, %f24
+ faligndata %f40, %f42, %f26
+ ba,pt %xcc, 3b
+ faligndata %f42, %f44, %f28
+ .align 32
+prepn15:faligndata %ftmp1, %f48, %f16
+ faligndata %f48, %f50, %f18
+ faligndata %f50, %f52, %f20
+ faligndata %f52, %f54, %f22
+ faligndata %f54, %f56, %f24
+ faligndata %f56, %f58, %f26
+ faligndata %f58, %f60, %f28
+ faligndata %f60, %f62, %f30
+ ba,pt %xcc, leftst
+ mov (vis15 - BranchBase), %tmp3
+
+ .align 64
+BranchBase:
+prepl0: FREG_FROB(f32,,f34,f34,,f36,f36,,f38,f38,,f40,f40,,f42,f42,,f44,f44,,f46,ftmp1,PREPLOAD(f32,f46,prep0e,prep0r),f48)
+ ba,pt %xcc, leftst
+ mov (vis1 - BranchBase), %tmp3
+ .align 64
+prepl1: FREG_FROB(f48,,f50,f50,,f52,f52,,f54,f54,,f56,f56,,f58,f58,,f60,f60,,f62,ftmp1,PREPLOAD(f48,f62,prep1e,prep1r),f32)
+ ba,pt %xcc, leftst
+ mov (vis0 - BranchBase), %tmp3
+ .align 64
+prepl2: FREG_FROB(f34,,f36,f36,,f38,f38,,f40,f40,,f42,f42,,f44,f44,,f46,ftmp1,PREPLOAD(f32,f46,prep2e,prep2r),f48,f48,,f50)
+ ba,pt %xcc, leftst
+ mov (vis3 - BranchBase), %tmp3
+ .align 64
+prepl3: FREG_FROB(f50,,f52,f52,,f54,f54,,f56,f56,,f58,f58,,f60,f60,,f62,ftmp1,PREPLOAD(f48,f62,prep3e,prep3r),f32,f32,,f34)
+ ba,pt %xcc, leftst
+ mov (vis2 - BranchBase), %tmp3
+ .align 64
+prepl4: FREG_FROB(f36,,f38,f38,,f40,f40,,f42,f42,,f44,f44,,f46,ftmp1,PREPLOAD(f32,f46,prep4e,prep4r),f48,f48,,f50,f50,,f52)
+ ba,pt %xcc, leftst
+ mov (vis5 - BranchBase), %tmp3
+ .align 64
+prepl5: FREG_FROB(f52,,f54,f54,,f56,f56,,f58,f58,,f60,f60,,f62,ftmp1,PREPLOAD(f48,f62,prep5e,prep5r),f32,f32,,f34,f34,,f36)
+ ba,pt %xcc, leftst
+ mov (vis4 - BranchBase), %tmp3
+ .align 64
+prepl6: FREG_FROB(f38,,f40,f40,,f42,f42,,f44,f44,,f46,ftmp1,PREPLOAD(f32,f46,prep6e,prep6r),f48,f48,,f50,f50,,f52,f52,,f54)
+ ba,pt %xcc, leftst
+ mov (vis7 - BranchBase), %tmp3
+ .align 64
+prepl7: FREG_FROB(f54,,f56,f56,,f58,f58,,f60,f60,,f62,ftmp1,PREPLOAD(f48,f62,prep7e,prep7r),f32,f32,,f34,f34,,f36,f36,,f38)
+ ba,pt %xcc, leftst
+ mov (vis6 - BranchBase), %tmp3
+ .align 64
+prepl8: FREG_FROB(f40,,f42,f42,,f44,f44,,f46,ftmp1,PREPLOAD(f32,f46,prep8e,prep8r),f48,f48,,f50,f50,,f52,f52,,f54,f54,,f56)
+ ba,pt %xcc, leftst
+ mov (vis9 - BranchBase), %tmp3
+ .align 64
+prepl9: FREG_FROB(f56,,f58,f58,,f60,f60,,f62,ftmp1,PREPLOAD(f48,f62,prep9e,prep9r),f32,f32,,f34,f34,,f36,f36,,f38,f38,,f40)
+ ba,pt %xcc, leftst
+ mov (vis8 - BranchBase), %tmp3
+ .align 64
+prepl10:FREG_FROB(f42,,f44,f44,,f46,ftmp1,PREPLOAD(f32,f46,prep10e,prep10r),f48,f48,,f50,f50,,f52,f52,,f54,f54,,f56,f56,,f58)
+ ba,pt %xcc, leftst
+ mov (vis11 - BranchBase), %tmp3
+ .align 64
+prepl11:FREG_FROB(f58,,f60,f60,,f62,ftmp1,PREPLOAD(f48,f62,prep11e,prep11r),f32,f32,,f34,f34,,f36,f36,,f38,f38,,f40,f40,,f42)
+ ba,pt %xcc, leftst
+ mov (vis10 - BranchBase), %tmp3
+ .align 64
+prepl12:FREG_FROB(f44,,f46,ftmp1,PREPLOAD(f32,f46,prep12e,prep12r),f48,f48,,f50,f50,,f52,f52,,f54,f54,,f56,f56,,f58,f58,,f60)
+ ba,pt %xcc, leftst
+ mov (vis13 - BranchBase), %tmp3
+ .align 64
+prepl13:FREG_FROB(f60,,f62,ftmp1,PREPLOAD(f48,f62,prep13e,prep13r),f32,f32,,f34,f34,,f36,f36,,f38,f38,,f40,f40,,f42,f42,,f44)
+ ba,pt %xcc, leftst
+ mov (vis12 - BranchBase), %tmp3
+ .align 64
+prepl14:FREG_FROB(ftmp1,PREPLOAD(f32,f46,prep14e,prep14r),f48,f48,,f50,f50,,f52,f52,,f54,f54,,f56,f56,,f58,f58,,f60,f60,,f62)
+ ba,pt %xcc, leftst
+ mov (vis15 - BranchBase), %tmp3
+ .align 64
+prepl15:FREG_FROB(ftmp1,PREPLOAD(f48,f62,prep15e,prep15r),f32,f32,,f34,f34,,f36,f36,,f38,f38,,f40,f40,,f42,f42,,f44,f44,,f46)
+ ba,pt %xcc, leftst
+ mov (vis14 - BranchBase), %tmp3
+
+ .align 128
+vis0: FREG_FROB(f32,,f34,f34,,f36,f36,,f38,f38,,f40,f40,,f42,f42,,f44,f44,,f46,ftmp1,LOAD(f32,f46,vis0e,vis0r),f48)
+ STORE
+ add %dst, 64, %dst
+vis1: FREG_FROB(f48,,f50,f50,,f52,f52,,f54,f54,,f56,f56,,f58,f58,,f60,f60,,f62,ftmp1,LOAD(f48,f62,vis1e,vis1r),f32)
+ STORE
+ ba,pt %xcc, vis0
+ add %dst, 64, %dst
+ .align 128
+vis2: FREG_FROB(f34,,f36,f36,,f38,f38,,f40,f40,,f42,f42,,f44,f44,,f46,ftmp1,LOAD(f32,f46,vis2e,vis2r),f48,f48,,f50)
+ STORE
+ add %dst, 64, %dst
+vis3: FREG_FROB(f50,,f52,f52,,f54,f54,,f56,f56,,f58,f58,,f60,f60,,f62,ftmp1,LOAD(f48,f62,vis3e,vis3r),f32,f32,,f34)
+ STORE
+ ba,pt %xcc, vis2
+ add %dst, 64, %dst
+ .align 128
+vis4: FREG_FROB(f36,,f38,f38,,f40,f40,,f42,f42,,f44,f44,,f46,ftmp1,LOAD(f32,f46,vis4e,vis4r),f48,f48,,f50,f50,,f52)
+ STORE
+ add %dst, 64, %dst
+vis5: FREG_FROB(f52,,f54,f54,,f56,f56,,f58,f58,,f60,f60,,f62,ftmp1,LOAD(f48,f62,vis5e,vis5r),f32,f32,,f34,f34,,f36)
+ STORE
+ ba,pt %xcc, vis4
+ add %dst, 64, %dst
+ .align 128
+vis6: FREG_FROB(f38,,f40,f40,,f42,f42,,f44,f44,,f46,ftmp1,LOAD(f32,f46,vis6e,vis6r),f48,f48,,f50,f50,,f52,f52,,f54)
+ STORE
+ add %dst, 64, %dst
+vis7: FREG_FROB(f54,,f56,f56,,f58,f58,,f60,f60,,f62,ftmp1,LOAD(f48,f62,vis7e,vis7r),f32,f32,,f34,f34,,f36,f36,,f38)
+ STORE
+ ba,pt %xcc, vis6
+ add %dst, 64, %dst
+ .align 128
+vis8: FREG_FROB(f40,,f42,f42,,f44,f44,,f46,ftmp1,LOAD(f32,f46,vis8e,vis8r),f48,f48,,f50,f50,,f52,f52,,f54,f54,,f56)
+ STORE
+ add %dst, 64, %dst
+vis9: FREG_FROB(f56,,f58,f58,,f60,f60,,f62,ftmp1,LOAD(f48,f62,vis9e,vis9r),f32,f32,,f34,f34,,f36,f36,,f38,f38,,f40)
+ STORE
+ ba,pt %xcc, vis8
+ add %dst, 64, %dst
+ .align 128
+vis10: FREG_FROB(f42,,f44,f44,,f46,ftmp1,LOAD(f32,f46,vis10e,vis10r),f48,f48,,f50,f50,,f52,f52,,f54,f54,,f56,f56,,f58)
+ STORE
+ add %dst, 64, %dst
+vis11: FREG_FROB(f58,,f60,f60,,f62,ftmp1,LOAD(f48,f62,vis11e,vis11r),f32,f32,,f34,f34,,f36,f36,,f38,f38,,f40,f40,,f42)
+ STORE
+ ba,pt %xcc, vis10
+ add %dst, 64, %dst
+ .align 128
+vis12: FREG_FROB(f44,,f46,ftmp1,LOAD(f32,f46,vis12e,vis12r),f48,f48,,f50,f50,,f52,f52,,f54,f54,,f56,f56,,f58,f58,,f60)
+ STORE
+ add %dst, 64, %dst
+vis13: FREG_FROB(f60,,f62,ftmp1,LOAD(f48,f62,vis13e,vis13r),f32,f32,,f34,f34,,f36,f36,,f38,f38,,f40,f40,,f42,f42,,f44)
+ STORE
+ ba,pt %xcc, vis12
+ add %dst, 64, %dst
+ .align 128
+vis14: FREG_FROB(ftmp1,LOAD(f32,f46,vis14e,vis14r),f48,f48,,f50,f50,,f52,f52,,f54,f54,,f56,f56,,f58,f58,,f60,f60,,f62)
+ STORE
+ add %dst, 64, %dst
+vis15: FREG_FROB(ftmp1,LOAD(f48,f62,vis15e,vis15r),f32,f32,,f34,f34,,f36,f36,,f38,f38,,f40,f40,,f42,f42,,f44,f44,,f46)
+ STORE
+ ba,pt %xcc, vis14
+ add %dst, 64, %dst
+
+leftst: brlz,pn %curw, narrowst + 4
+ and %leftw, 0x38, %tmp1
+ andcc %leftw, 7, %g0
+ be,pn %icc, 1f
+ neg %tmp1
+ sub %dst, %leftw, %tmp4
+ add %branchbase, (2f - BranchBase - 8), %tmp2
+ edge8 %tmp4, %g0, %tmp5
+ jmpl %tmp2 + %tmp1, %g0
+ andn %tmp4, 7, %tmp4
+1: addcc %branchbase, (3f - BranchBase), %tmp2
+ sra %tmp1, 1, %tmp1
+ jmpl %tmp2 + %tmp1, %g0
+ nop
+ ba,pt %xcc, 2f+0x00
+ stda %f16, [%tmp4 + %tmp5] ASI_PST8_P
+ ba,pt %xcc, 2f+0x04
+ stda %f18, [%tmp4 + %tmp5] ASI_PST8_P
+ ba,pt %xcc, 2f+0x08
+ stda %f20, [%tmp4 + %tmp5] ASI_PST8_P
+ ba,pt %xcc, 2f+0x0c
+ stda %f22, [%tmp4 + %tmp5] ASI_PST8_P
+ ba,pt %xcc, 2f+0x10
+ stda %f24, [%tmp4 + %tmp5] ASI_PST8_P
+ ba,pt %xcc, 2f+0x14
+ stda %f26, [%tmp4 + %tmp5] ASI_PST8_P
+ ba,pt %xcc, 2f+0x18
+ stda %f28, [%tmp4 + %tmp5] ASI_PST8_P
+ jmpl %branchbase + %tmp3, %g0
+ stda %f30, [%tmp4 + %tmp5] ASI_PST8_P
+2: std %f18, [%dst - 0x38]
+ std %f20, [%dst - 0x30]
+ std %f22, [%dst - 0x28]
+ std %f24, [%dst - 0x20]
+ std %f26, [%dst - 0x18]
+ std %f28, [%dst - 0x10]
+ std %f30, [%dst - 0x08]
+3: jmpl %branchbase + %tmp3, %g0
+ nop
+
+rightst:cmp %rightw, 64
+ be,pn %icc, 2f
+ and %rightw, 0x38, %tmp1
+ andcc %rightw, 7, %g0
+ be,pn %icc, 1f
+ neg %tmp1
+ sub %g0, %rightw, %tmp5
+ add %branchbase, (3f - BranchBase - 8), %tmp2
+ edge8l %tmp5, %g0, %tmp5
+ add %mode, %skind, %mode
+ jmpl %tmp1 + %tmp2, %g0
+ sub %dst, %tmp1, %tmp4
+1: addcc %branchbase, (4f - BranchBase), %tmp2
+ sra %tmp1, 1, %tmp1
+ jmpl %tmp1 + %tmp2, %g0
+2: add %mode, %skind, %mode
+ ba,pt %xcc, 4f
+ stda %f16, [%dst] ASI_BLK_P
+ ba,pt %xcc, 3f+0x00
+ stda %f30, [%tmp4 + %tmp5] ASI_PST8_P
+ ba,pt %xcc, 3f+0x04
+ stda %f28, [%tmp4 + %tmp5] ASI_PST8_P
+ ba,pt %xcc, 3f+0x08
+ stda %f26, [%tmp4 + %tmp5] ASI_PST8_P
+ ba,pt %xcc, 3f+0x0c
+ stda %f24, [%tmp4 + %tmp5] ASI_PST8_P
+ ba,pt %xcc, 3f+0x10
+ stda %f22, [%tmp4 + %tmp5] ASI_PST8_P
+ ba,pt %xcc, 3f+0x14
+ stda %f20, [%tmp4 + %tmp5] ASI_PST8_P
+ ba,pt %xcc, 3f+0x18
+ stda %f18, [%tmp4 + %tmp5] ASI_PST8_P
+ ba,pt %xcc, 3f+0x1c
+ stda %f16, [%tmp4 + %tmp5] ASI_PST8_P
+3: std %f28, [%dst + 0x30]
+ std %f26, [%dst + 0x28]
+ std %f24, [%dst + 0x20]
+ std %f22, [%dst + 0x18]
+ std %f20, [%dst + 0x10]
+ std %f18, [%dst + 0x08]
+ std %f16, [%dst + 0x00]
+4: brnz,pn %narrow, narrow_cont
+ deccc %srcnotdone
+ blu,pn %ICC, return
+ sub %mode, %dkind, %mode
+ alignaddr %mode, %g0, %g0
+ and %mode, 63, %mode
+ cmp %srcnext, %srcn
+ bne,a,pn %ICC, 6f
+ xor %fregset, 64, %fregset
+ brnz,a,pn %fregset, 5f
+ ldda [%src] ASI_BLK_P, %f32
+ ldda [%src] ASI_BLK_P, %f48
+5: add %src, 64, %src
+6: add %dst, %dkind, %dst
+ sub %w, %rightw, %tmp1
+ add %srcstart, %skind, %srcstart
+ sub %dst, %tmp1, %dst
+ add %rightw, %dkind, %rightw
+ andn %dst, 63, %dst
+ sub %rightw, 1, %rightw
+ sub %leftw, %dkind, %leftw
+ and %rightw, 63, %rightw
+ and %leftw, 63, %leftw
+ add %rightw, 1, %rightw
+roll_wide:
+ add %srcstart, %w, %srcend
+ add %srcstart, %skind, %srcnext
+ fnop
+ add %srcend, 63, %srcend
+ andncc %srcnext, 63, %srcnext
+ fnop
+ sll %mode, 4, %tmp1
+ andn %srcend, 63, %srcend
+ fnop
+ mov %srcnext, %srcn
+ and %mode, 7, %rightw2
+ fnop
+ andn %tmp1, 127, %tmp1
+ add %rightw2, %rightw, %rightw2
+ fnop
+ add %tmp1, %fregset, %tmp1
+ subcc %w, %leftw, %tmp3
+ fnop
+ srl %tmp1, 1, %tmp2
+ add %srcnext, 64, %tmp4
+ fnop
+ add %tmp2, (prepn0 - BranchBase), %tmp2
+ cmp %mode, %leftw
+ movgeu %icc, %tmp2, %tmp1
+ cmp %tmp4, %srcend
+ add %dst, 64, %tmp4
+ move %ICC, %srcend, %srcnext
+ movrnz %leftw, %tmp4, %dst
+ jmpl %branchbase + %tmp1, %g0
+ sub %tmp3, %rightw, %curw
+
+return: return %i7+8
+ wr %g0, 0, %fprs
+
+narrowst:
+ and %leftw, 0x38, %tmp1
+ sub %dst, %leftw, %tmp5
+ sub %w, 1, %fregset
+ andcc %leftw, 7, %tmp4
+ add %fregset, %tmp5, %fregset
+ neg %tmp1
+ and %fregset, 7, %srcend
+ be,pn %icc, 1f
+ edge8 %g0, %srcend, %srcend
+ add %tmp1, (2f - BranchBase - 8), %tmp1
+ edge8 %tmp5, %fregset, %tmp2
+ andn %tmp5, 7, %tmp5
+ andn %fregset, 7, %fregset
+ jmpl %branchbase + %tmp1, %g0
+ sub %w, %tmp4, %tmp4
+1: addcc %branchbase, (3f - BranchBase - 8), %tmp2
+ sll %tmp1, 1, %tmp1
+ andn %fregset, 7, %fregset
+ jmpl %tmp2 + %tmp1, %g0
+ mov %w, %tmp4
+ ba,pt %xcc, 2f+0x00
+ stda %f16, [%tmp5 + %tmp2] ASI_PST8_P
+ ba,pt %xcc, 2f+0x10
+ stda %f18, [%tmp5 + %tmp2] ASI_PST8_P
+ ba,pt %xcc, 2f+0x20
+ stda %f20, [%tmp5 + %tmp2] ASI_PST8_P
+ ba,pt %xcc, 2f+0x30
+ stda %f22, [%tmp5 + %tmp2] ASI_PST8_P
+ ba,pt %xcc, 2f+0x40
+ stda %f24, [%tmp5 + %tmp2] ASI_PST8_P
+ ba,pt %xcc, 2f+0x50
+ stda %f26, [%tmp5 + %tmp2] ASI_PST8_P
+ ba,pt %xcc, 2f+0x60
+ stda %f28, [%tmp5 + %tmp2] ASI_PST8_P
+ ba,pt %xcc, 4f
+ stda %f30, [%tmp5 + %tmp2] ASI_PST8_P
+2: subcc %tmp4, 8, %tmp4
+ bl,pn %icc, 3f+0x00
+ fnop
+ std %f18, [%dst - 0x38]
+ subcc %tmp4, 8, %tmp4
+ bl,pn %icc, 3f+0x10
+ fnop
+ std %f20, [%dst - 0x30]
+ subcc %tmp4, 8, %tmp4
+ bl,pn %icc, 3f+0x20
+ fnop
+ std %f22, [%dst - 0x28]
+ subcc %tmp4, 8, %tmp4
+ bl,pn %icc, 3f+0x30
+ fnop
+ std %f24, [%dst - 0x20]
+ subcc %tmp4, 8, %tmp4
+ bl,pn %icc, 3f+0x40
+ fnop
+ std %f26, [%dst - 0x18]
+ subcc %tmp4, 8, %tmp4
+ bl,pn %icc, 3f+0x50
+ fnop
+ std %f28, [%dst - 0x10]
+ subcc %tmp4, 8, %tmp4
+ bl,pn %icc, 3f+0x60
+ fnop
+ std %f30, [%dst - 0x08]
+ ba,pt %xcc, 4f
+ nop
+3: cmp %tmp4, -8
+ bg,a,pn %ICC, 4f
+ stda %f18, [%fregset + %srcend] ASI_PST8_P
+ ba,a,pt %xcc, 4f
+ cmp %tmp4, -8
+ bg,a,pn %ICC, 4f
+ stda %f20, [%fregset + %srcend] ASI_PST8_P
+ ba,a,pt %xcc, 4f
+ cmp %tmp4, -8
+ bg,a,pn %ICC, 4f
+ stda %f22, [%fregset + %srcend] ASI_PST8_P
+ ba,a,pt %xcc, 4f
+ cmp %tmp4, -8
+ bg,a,pn %ICC, 4f
+ stda %f24, [%fregset + %srcend] ASI_PST8_P
+ ba,a,pt %xcc, 4f
+ cmp %tmp4, -8
+ bg,a,pn %ICC, 4f
+ stda %f26, [%fregset + %srcend] ASI_PST8_P
+ ba,a,pt %xcc, 4f
+ cmp %tmp4, -8
+ bg,a,pn %ICC, 4f
+ stda %f28, [%fregset + %srcend] ASI_PST8_P
+ ba,a,pt %xcc, 4f
+ cmp %tmp4, -8
+ bg,a,pn %ICC, 4f
+ stda %f30, [%fregset + %srcend] ASI_PST8_P
+4: and %tmp3, 60, %tmp3
+ sub %dst, 64, %dst
+ add %tmp3, 96, %tmp3
+ add %mode, %skind, %mode
+ brz,pn %h, return
+ and %tmp3, 64, %fregset
+narrow_cont:
+ deccc %h
+ blu,pn %ICC, return
+ sub %mode, %dkind, %mode
+ alignaddr %mode, %g0, %g0
+ and %mode, 63, %mode
+ sub %srcnext, %srcn, %tmp4
+ add %dst, %dkind, %dst
+ sub %w, %rightw, %tmp1
+ add %srcstart, %skind, %srcstart
+ sub %dst, %tmp1, %dst
+ add %rightw, %dkind, %rightw
+ sub %leftw, %dkind, %leftw
+ sub %rightw, 1, %rightw
+ and %leftw, 63, %leftw
+ and %rightw, 63, %rightw
+ add %srcstart, %w, %srcend
+ add %rightw, 1, %rightw
+ add %srcstart, %skind, %srcnext
+ add %srcend, 63, %srcend
+ andn %srcnext, 63, %srcnext
+ andn %srcend, 63, %srcend
+ sub %w, %leftw, %prepw
+ mov %srcnext, %srcn
+ add %srcnext, 64, %tmp2
+ sub %srcnext, 64, %tmp3
+ and %srcstart, 63, %tmp1
+ cmp %skind, 0
+ movg %ICC, %srcend, %tmp3
+ sub %prepw, %rightw, %prepw
+ add %tmp1, %w, %tmp1
+ cmp %tmp2, %srcend
+ mov %prepw, %curw
+ move %ICC, %tmp3, %srcnext
+ mov %h, %srcnotdone
+ cmp %tmp1, 128
+ movg %ICC, 64, %prepw
+ andn %dst, 63, %dst
+ cmp %srcnext, %srcstop
+ move %ICC, 0, %srcnotdone
+ brnz,a,pn %tmp4, roll_narrow
+ xor %fregset, 64, %fregset
+ cmp %tmp1, 64
+ bg,pt %ICC, 5f
+ tst %srcnotdone
+ be,a,pn %ICC, roll_narrow
+ membar SYNC
+ mov %srcnext, %src
+5: brnz,a,pn %fregset, 6f
+ ldda [%src] ASI_BLK_P, %f32
+ ldda [%src] ASI_BLK_P, %f48
+6: addcc %src, 64, %src
+roll_narrow:
+ fnop
+ sll %mode, 4, %tmp2
+ and %mode, 7, %rightw2
+ fnop
+ andn %tmp2, 127, %tmp2
+ add %dst, 64, %tmp4
+ fnop
+ add %tmp2, %fregset, %tmp2
+ addcc %rightw2, %rightw, %rightw2
+ fnop
+ srl %tmp2, 1, %tmp3
+ movrnz %leftw, %tmp4, %dst
+ fnop
+ add %tmp3, (prepr0 - BranchBase), %tmp4
+ cmp %tmp1, 64
+ movleu %icc, %tmp4, %tmp2
+ fnop
+ add %tmp3, (prepn0 - BranchBase), %tmp4
+ cmp %mode, %leftw
+ fnop
+ movgeu %icc, %tmp4, %tmp2
+ jmpl %branchbase + %tmp2, %g0
+ and %tmp3, 32, %tmp3
+
+#define VISEND(i,tgt,tgtr,fi,fset) \
+tgt: \
+ brnz,pt %curw, 1f; \
+ cmp %rightw2, (64 - (i&14)*4); \
+ bgu,pn %icc, tgtr - 8; \
+ tst %srcnotdone; \
+ be,a,pn %ICC, tgtr; \
+ membar SYNC; \
+ ba,pt %xcc, tgtr - 8; \
+ mov %srcnext, %src; \
+1: mov ((i & 1) ^ 1) * 64, %fregset; \
+ bleu,pn %icc, rightst; \
+ faligndata %ftmp1, %ftmp2, %fi; \
+ brz,a,pn %srcnotdone, 3f; \
+ membar SYNC; \
+ ldda [%srcnext] ASI_BLK_P, %fset; \
+ add %srcnext, 64, %src; \
+3: mov (i & 1) * 64, %fregset;
+
+VISEND(0,vis0e,vis0r,f30,f32)
+ ba,pt %xcc, rightst
+ faligndata %ftmp1, %f48, %f30
+VISEND(1,vis1e,vis1r,f30,f48)
+ ba,pt %xcc, rightst
+ faligndata %ftmp1, %f32, %f30
+VISEND(2,vis2e,vis2r,f28,f32)
+ faligndata %ftmp1, %f48, %f28
+ ba,pt %xcc, rightst
+ faligndata %f48, %f50, %f30
+VISEND(3,vis3e,vis3r,f28,f48)
+ faligndata %ftmp1, %f32, %f28
+ ba,pt %xcc, rightst
+ faligndata %f32, %f34, %f30
+VISEND(4,vis4e,vis4r,f26,f32)
+ faligndata %ftmp1, %f48, %f26
+ faligndata %f48, %f50, %f28
+ ba,pt %xcc, rightst
+ faligndata %f50, %f52, %f30
+VISEND(5,vis5e,vis5r,f26,f48)
+ faligndata %ftmp1, %f32, %f26
+ faligndata %f32, %f34, %f28
+ ba,pt %xcc, rightst
+ faligndata %f34, %f36, %f30
+VISEND(6,vis6e,vis6r,f24,f32)
+ faligndata %ftmp1, %f48, %f24
+ faligndata %f48, %f50, %f26
+ faligndata %f50, %f52, %f28
+ ba,pt %xcc, rightst
+ faligndata %f52, %f54, %f30
+VISEND(7,vis7e,vis7r,f24,f48)
+ faligndata %ftmp1, %f32, %f24
+ faligndata %f32, %f34, %f26
+ faligndata %f34, %f36, %f28
+ ba,pt %xcc, rightst
+ faligndata %f36, %f38, %f30
+VISEND(8,vis8e,vis8r,f22,f32)
+ faligndata %ftmp1, %f48, %f22
+ faligndata %f48, %f50, %f24
+ faligndata %f50, %f52, %f26
+ faligndata %f52, %f54, %f28
+ ba,pt %xcc, rightst
+ faligndata %f54, %f56, %f30
+VISEND(9,vis9e,vis9r,f22,f48)
+ faligndata %ftmp1, %f32, %f22
+ faligndata %f32, %f34, %f24
+ faligndata %f34, %f36, %f26
+ faligndata %f36, %f38, %f28
+ ba,pt %xcc, rightst
+ faligndata %f38, %f40, %f30
+VISEND(10,vis10e,vis10r,f20,f32)
+ faligndata %ftmp1, %f48, %f20
+ faligndata %f48, %f50, %f22
+ faligndata %f50, %f52, %f24
+ faligndata %f52, %f54, %f26
+ faligndata %f54, %f56, %f28
+ ba,pt %xcc, rightst
+ faligndata %f56, %f58, %f30
+VISEND(11,vis11e,vis11r,f20,f48)
+ faligndata %ftmp1, %f32, %f20
+ faligndata %f32, %f34, %f22
+ faligndata %f34, %f36, %f24
+ faligndata %f36, %f38, %f26
+ faligndata %f38, %f40, %f28
+ ba,pt %xcc, rightst
+ faligndata %f40, %f42, %f30
+VISEND(12,vis12e,vis12r,f18,f32)
+ faligndata %ftmp1, %f48, %f18
+ faligndata %f48, %f50, %f20
+ faligndata %f50, %f52, %f22
+ faligndata %f52, %f54, %f24
+ faligndata %f54, %f56, %f26
+ faligndata %f56, %f58, %f28
+ ba,pt %xcc, rightst
+ faligndata %f58, %f60, %f30
+VISEND(13,vis13e,vis13r,f18,f48)
+ faligndata %ftmp1, %f32, %f18
+ faligndata %f32, %f34, %f20
+ faligndata %f34, %f36, %f22
+ faligndata %f36, %f38, %f24
+ faligndata %f38, %f40, %f26
+ faligndata %f40, %f42, %f28
+ ba,pt %xcc, rightst
+ faligndata %f42, %f44, %f30
+VISEND(14,vis14e,vis14r,f16,f32)
+ faligndata %ftmp1, %f48, %f16
+ faligndata %f48, %f50, %f18
+ faligndata %f50, %f52, %f20
+ faligndata %f52, %f54, %f22
+ faligndata %f54, %f56, %f24
+ faligndata %f56, %f58, %f26
+ faligndata %f58, %f60, %f28
+ ba,pt %xcc, rightst
+ faligndata %f60, %f62, %f30
+VISEND(15,vis15e,vis15r,f16,f48)
+ faligndata %ftmp1, %f32, %f16
+ faligndata %f32, %f34, %f18
+ faligndata %f34, %f36, %f20
+ faligndata %f36, %f38, %f22
+ faligndata %f38, %f40, %f24
+ faligndata %f40, %f42, %f26
+ faligndata %f42, %f44, %f28
+ ba,pt %xcc, rightst
+ faligndata %f44, %f46, %f30
+
+#define PREPEND(tgt,tgtr) \
+tgt: \
+ brnz,pt %srcnotdone, tgtr - 8; \
+ mov %srcnext, %src; \
+ ba,pt %xcc, tgtr; \
+ membar SYNC;
+
+ .align 16
+PREPEND(prep0e,prep0r)
+PREPEND(prep1e,prep1r)
+PREPEND(prep2e,prep2r)
+PREPEND(prep3e,prep3r)
+PREPEND(prep4e,prep4r)
+PREPEND(prep5e,prep5r)
+PREPEND(prep6e,prep6r)
+PREPEND(prep7e,prep7r)
+PREPEND(prep8e,prep8r)
+PREPEND(prep9e,prep9r)
+PREPEND(prep10e,prep10r)
+PREPEND(prep11e,prep11r)
+PREPEND(prep12e,prep12r)
+PREPEND(prep13e,prep13r)
+PREPEND(prep14e,prep14r)
+PREPEND(prep15e,prep15r)
+
+/* The other way is even more complicated, as the hardware prefers
+ * going from lower addresses up. */
+
+#define RLOAD(f32,tgt,tgtr) \
+ subcc %curw, 64, %curw; \
+ bleu,pn %ICC, tgt; \
+ fmovd %f32, %ftmp1; \
+ ldda [%src] ASI_BLK_P, %f32; \
+ sub %src, 64, %src; \
+tgtr:
+
+#if defined(__sparc_v9__) || defined(__sparcv9) || defined(__arch64__) || !defined(SIGNAL_CLOBBERS_OG_REGS)
+
+#define RPREPLOAD(f32,tgt,tgtr) \
+ brlez,pn %prepw, tgt; \
+ fmovd %f32, %ftmp1; \
+ ldda [%src] ASI_BLK_P, %f32; \
+ sub %src, 64, %src; \
+tgtr:
+
+#else
+
+#define RPREPLOAD(f32,tgt,tgtr) \
+ tst %prepw; \
+ ble,pn %ICC, tgt; \
+ fmovd %f32, %ftmp1; \
+ ldda [%src] ASI_BLK_P, %f32; \
+ sub %src, 64, %src; \
+tgtr:
+
+#endif
+
+ .globl VISmoveImageRL
+ .align 32
+VISmoveImageRL:
+ save %sp, -160, %sp ! Group 0
+0: rd %pc, %tmp3 ! Group 1
+ and %dst, 63, %leftw ! Group 7
+ mov 64, %tmp1
+ add %src, %w, %src ! Group 8
+ add %dst, %w, %dst
+ sub %src, %dst, %mode ! Group 9
+ brz,pn %h, rreturn
+ sub %dst, 1, %rightw ! Group 10
+ mov %src, %srcstart
+ dec %src ! Group 11
+ cmp %w, 128
+ blu,pn %ICC, rprepare_narrow
+ and %mode, 63, %mode ! Group 12
+ andn %src, 63, %src
+ ldda [%src] ASI_BLK_P, %f32 ! Group 13
+ sub %src, 64, %src ! Group 14
+ clr %narrow
+ ldda [%src] ASI_BLK_P, %f48 ! Group 15
+ sub %tmp1, %leftw, %leftw ! Group 16
+ and %rightw, 63, %rightw
+ dec %dst ! Group 17
+ add %rightw, 1, %rightw
+ alignaddr %mode, %g0, %g0 ! Group 18
+ andn %dst, 63, %dst ! Group 19
+ clr %fregset
+ sub %src, 64, %src ! Group 20
+ add %tmp3, (BranchBaseR - 0b), %branchbase
+ mov 64, %prepw ! Group 21
+ ba,pt %xcc, rroll_wide
+ sub %h, 1, %srcnotdone
+rprepare_narrow:
+#if defined(__sparc_v9__) || defined(__sparcv9) || defined(__arch64__)
+ brlez,pn %w, rreturn
+#else
+ tst %w
+ ble,pn %icc, rreturn
+#endif
+ andn %src, 63, %src ! Group 12
+ sub %tmp1, %leftw, %leftw
+ ldda [%src] ASI_BLK_P, %f32 ! Group 13
+ and %rightw, 63, %rightw ! Group 14
+ dec %dst
+ add %rightw, 1, %rightw ! Group 15
+ andn %dst, 63, %dst
+ sub %w, %leftw, %tmp2 ! Group 16
+ sub %srcstart, 1, %tmp1
+ subcc %tmp2, %rightw, %curw ! Group 17
+ and %tmp1, 63, %tmp1
+ mov %curw, %prepw ! Group 18
+ sub %tmp1, %w, %tmp1
+ bg,pt %ICC, 1f
+ sub %src, 64, %src ! Group 19
+ cmp %tmp1, -65
+ movl %ICC, 64, %prepw ! Group 20
+1: add %srcstart, %skind, %srcnext
+ sub %h, 1, %srcnotdone ! Group 21
+ sub %srcstart, %w, %tmp4
+ sub %srcnext, 1, %srcnext ! Group 22
+ andn %tmp4, 63, %srcend
+ andn %srcnext, 63, %srcnext ! Group 23
+ cmp %skind, 0
+ add %w, 64, %tmp2 ! Group 24
+ mov %srcnext, %srcn
+ bl,pn %ICC, 1f
+ clr %srcstop ! Group 25
+ cmp %skind, %tmp2
+ bgeu,pt %ICC, 3f
+ add %srcnext, 64, %fregset
+ SMUL %skind, %srcnotdone, %srcstop
+ ba,pt %xcc, 2f
+ add %srcstart, 63, %tmp4
+1: addcc %tmp2, %skind, %g0
+ ble,pt %ICC, 3f
+ sub %srcnext, 64, %fregset
+ SMUL %skind, %srcnotdone, %srcstop
+ sub %tmp4, 64, %tmp4
+2: add %srcstop, %tmp4, %srcstop
+3: cmp %srcnext, %srcend
+ andn %srcstop, 63, %srcstop
+ move %ICC, %fregset, %srcnext
+ cmp %srcnext, %srcstop
+ clr %fregset
+ move %ICC, 0, %srcnotdone
+ alignaddr %mode, %g0, %g0
+ add %tmp3, (BranchBaseR - 0b), %branchbase
+ mov 1, %narrow
+ cmp %tmp1, -1
+ bge,pn %ICC, 1f
+ dec %h
+ ldda [%src] ASI_BLK_P, %f48
+ ba,pt %xcc, rroll_narrow
+ subcc %src, 64, %src
+1: brz,a,pn %srcnotdone, rroll_narrow
+ membar #Sync
+ ldda [%srcnext] ASI_BLK_P, %f48
+ ba,pt %xcc, rroll_narrow
+ subcc %srcnext, 64, %src
+
+ .align 32
+rrepr0: ba,pt %xcc, narrowstr
+ faligndata %ftmp1, %f32, %f30
+ nop
+ nop
+1: ba,pt %xcc, narrowstr
+ faligndata %ftmp1, %f32, %f16
+ .align 32
+rrepr1: ba,pt %xcc, narrowstr
+ faligndata %ftmp1, %f48, %f30
+ nop
+ nop
+2: ba,pt %xcc, narrowstr
+ faligndata %ftmp1, %f48, %f16
+ .align 32
+rrepr2: faligndata %f32, %f34, %f30
+ ba,pt %xcc, narrowstr
+ faligndata %ftmp1, %f32, %f28
+ .align 32
+rrepr3: faligndata %f48, %f50, %f30
+ ba,pt %xcc, narrowstr
+ faligndata %ftmp1, %f48, %f28
+ .align 32
+rrepr4: faligndata %f34, %f36, %f30
+ faligndata %f32, %f34, %f28
+ ba,pt %xcc, narrowstr
+ faligndata %ftmp1, %f32, %f26
+ .align 32
+rrepr5: faligndata %f50, %f52, %f30
+ faligndata %f48, %f50, %f28
+ ba,pt %xcc, narrowstr
+ faligndata %ftmp1, %f48, %f26
+ .align 32
+rrepr6: faligndata %f36, %f38, %f30
+ faligndata %f34, %f36, %f28
+ faligndata %f32, %f34, %f26
+ ba,pt %xcc, narrowstr
+ faligndata %ftmp1, %f32, %f24
+ .align 32
+rrepr7: faligndata %f52, %f54, %f30
+ faligndata %f50, %f52, %f28
+ faligndata %f48, %f50, %f26
+ ba,pt %xcc, narrowstr
+ faligndata %ftmp1, %f48, %f24
+ .align 32
+rrepr8: faligndata %f38, %f40, %f30
+ faligndata %f36, %f38, %f28
+ faligndata %f34, %f36, %f26
+ faligndata %f32, %f34, %f24
+ ba,pt %xcc, narrowstr
+ faligndata %ftmp1, %f32, %f22
+ .align 32
+rrepr9: faligndata %f54, %f56, %f30
+ faligndata %f52, %f54, %f28
+ faligndata %f50, %f52, %f26
+ faligndata %f48, %f50, %f24
+ ba,pt %xcc, narrowstr
+ faligndata %ftmp1, %f48, %f22
+ .align 32
+rrepr10:faligndata %f40, %f42, %f30
+ faligndata %f38, %f40, %f28
+ faligndata %f36, %f38, %f26
+ faligndata %f34, %f36, %f24
+ faligndata %f32, %f34, %f22
+ ba,pt %xcc, narrowstr
+ faligndata %ftmp1, %f32, %f20
+ .align 32
+rrepr11:faligndata %f56, %f58, %f30
+ faligndata %f54, %f56, %f28
+ faligndata %f52, %f54, %f26
+ faligndata %f50, %f52, %f24
+ faligndata %f48, %f50, %f22
+ ba,pt %xcc, narrowstr
+ faligndata %ftmp1, %f48, %f20
+ .align 32
+rrepr12:faligndata %f42, %f44, %f30
+ faligndata %f40, %f42, %f28
+ faligndata %f38, %f40, %f26
+ faligndata %f36, %f38, %f24
+ faligndata %f34, %f36, %f22
+ faligndata %f32, %f34, %f20
+ ba,pt %xcc, narrowstr
+ faligndata %ftmp1, %f32, %f18
+ .align 32
+rrepr13:faligndata %f58, %f60, %f30
+ faligndata %f56, %f58, %f28
+ faligndata %f54, %f56, %f26
+ faligndata %f52, %f54, %f24
+ faligndata %f50, %f52, %f22
+ faligndata %f48, %f50, %f20
+ ba,pt %xcc, narrowstr
+ faligndata %ftmp1, %f48, %f18
+ .align 32
+rrepr14:faligndata %f44, %f46, %f30
+ faligndata %f42, %f44, %f28
+ faligndata %f40, %f42, %f26
+ faligndata %f38, %f40, %f24
+ faligndata %f36, %f38, %f22
+ faligndata %f34, %f36, %f20
+ ba,pt %xcc, 1b
+ faligndata %f32, %f34, %f18
+ .align 32
+rrepr15:faligndata %f60, %f62, %f30
+ faligndata %f58, %f60, %f28
+ faligndata %f56, %f58, %f26
+ faligndata %f54, %f56, %f24
+ faligndata %f52, %f54, %f22
+ faligndata %f50, %f52, %f20
+ ba,pt %xcc, 2b
+ faligndata %f48, %f50, %f18
+
+ .align 32
+rrepn0: faligndata %f46, %ftmp1, %f30
+ faligndata %f44, %f46, %f28
+ faligndata %f42, %f44, %f26
+ faligndata %f40, %f42, %f24
+ faligndata %f38, %f40, %f22
+ faligndata %f36, %f38, %f20
+ ba,pt %xcc, 1f
+ faligndata %f34, %f36, %f18
+ .align 32
+rrepn1: faligndata %f62, %ftmp1, %f30
+ faligndata %f60, %f62, %f28
+ faligndata %f58, %f60, %f26
+ faligndata %f56, %f58, %f24
+ faligndata %f54, %f56, %f22
+ faligndata %f52, %f54, %f20
+ ba,pt %xcc, 2f
+ faligndata %f50, %f52, %f18
+ .align 32
+rrepn2: faligndata %f46, %ftmp1, %f28
+ faligndata %f44, %f46, %f26
+ faligndata %f42, %f44, %f24
+ faligndata %f40, %f42, %f22
+ faligndata %f38, %f40, %f20
+ faligndata %f36, %f38, %f18
+ ba,pt %xcc, 3f
+ faligndata %f34, %f36, %f16
+ .align 32
+rrepn3: faligndata %f62, %ftmp1, %f28
+ faligndata %f60, %f62, %f26
+ faligndata %f58, %f60, %f24
+ faligndata %f56, %f58, %f22
+ faligndata %f54, %f56, %f20
+ faligndata %f52, %f54, %f18
+ ba,pt %xcc, 4f
+ faligndata %f50, %f52, %f16
+ .align 32
+rrepn4: faligndata %f46, %ftmp1, %f26
+ faligndata %f44, %f46, %f24
+ faligndata %f42, %f44, %f22
+ faligndata %f40, %f42, %f20
+ faligndata %f38, %f40, %f18
+ faligndata %f36, %f38, %f16
+ ba,pt %xcc, rightstr
+ mov (rvis4 - BranchBaseR), %tmp3
+ .align 32
+rrepn5: faligndata %f62, %ftmp1, %f26
+ faligndata %f60, %f62, %f24
+ faligndata %f58, %f60, %f22
+ faligndata %f56, %f58, %f20
+ faligndata %f54, %f56, %f18
+ faligndata %f52, %f54, %f16
+ ba,pt %xcc, rightstr
+ mov (rvis5 - BranchBaseR), %tmp3
+ .align 32
+rrepn6: faligndata %f46, %ftmp1, %f24
+ faligndata %f44, %f46, %f22
+ faligndata %f42, %f44, %f20
+ faligndata %f40, %f42, %f18
+ faligndata %f38, %f40, %f16
+ ba,pt %xcc, rightstr
+ mov (rvis6 - BranchBaseR), %tmp3
+ .align 32
+rrepn7: faligndata %f62, %ftmp1, %f24
+ faligndata %f60, %f62, %f22
+ faligndata %f58, %f60, %f20
+ faligndata %f56, %f58, %f18
+ faligndata %f54, %f56, %f16
+ ba,pt %xcc, rightstr
+ mov (rvis7 - BranchBaseR), %tmp3
+ .align 32
+rrepn8: faligndata %f46, %ftmp1, %f22
+ faligndata %f44, %f46, %f20
+ faligndata %f42, %f44, %f18
+ faligndata %f40, %f42, %f16
+ ba,pt %xcc, rightstr
+ mov (rvis8 - BranchBaseR), %tmp3
+ .align 32
+rrepn9: faligndata %f62, %ftmp1, %f22
+ faligndata %f60, %f62, %f20
+ faligndata %f58, %f60, %f18
+ faligndata %f56, %f58, %f16
+ ba,pt %xcc, rightstr
+ mov (rvis9 - BranchBaseR), %tmp3
+ .align 32
+rrepn10:faligndata %f46, %ftmp1, %f20
+ faligndata %f44, %f46, %f18
+ faligndata %f42, %f44, %f16
+ ba,pt %xcc, rightstr
+ mov (rvis10 - BranchBaseR), %tmp3
+ .align 32
+rrepn11:faligndata %f62, %ftmp1, %f20
+ faligndata %f60, %f62, %f18
+ faligndata %f58, %f60, %f16
+ ba,pt %xcc, rightstr
+ mov (rvis11 - BranchBaseR), %tmp3
+ .align 32
+rrepn12:faligndata %f46, %ftmp1, %f18
+ faligndata %f44, %f46, %f16
+ ba,pt %xcc, rightstr
+ mov (rvis12 - BranchBaseR), %tmp3
+ nop
+ nop
+3: ba,pt %xcc, rightstr
+ mov (rvis2 - BranchBaseR), %tmp3
+ .align 32
+rrepn13:faligndata %f62, %ftmp1, %f18
+ faligndata %f60, %f62, %f16
+ ba,pt %xcc, rightstr
+ mov (rvis13 - BranchBaseR), %tmp3
+ nop
+ nop
+4: ba,pt %xcc, rightstr
+ mov (rvis3 - BranchBaseR), %tmp3
+ .align 32
+rrepn14:faligndata %f46, %ftmp1, %f16
+ ba,pt %xcc, rightstr
+ mov (rvis14 - BranchBaseR), %tmp3
+ nop
+1: faligndata %f32, %f34, %f16
+ ba,pt %xcc, rightstr
+ mov (rvis0 - BranchBaseR), %tmp3
+ .align 32
+rrepn15:faligndata %f62, %ftmp1, %f16
+ ba,pt %xcc, rightstr
+ mov (rvis15 - BranchBaseR), %tmp3
+ nop
+2: faligndata %f48, %f50, %f16
+ ba,pt %xcc, rightstr
+ mov (rvis1 - BranchBaseR), %tmp3
+
+ .align 64
+BranchBaseR:
+rrepl0: RPREPLOAD(f32,rrep0e,rrep0r)
+ fnop
+ faligndata %f48, %f50, %f16
+ faligndata %f50, %f52, %f18
+ faligndata %f52, %f54, %f20
+ faligndata %f54, %f56, %f22
+ faligndata %f56, %f58, %f24
+ faligndata %f58, %f60, %f26
+ faligndata %f60, %f62, %f28
+ faligndata %f62, %ftmp1, %f30
+ ba,pt %xcc, rightstr
+ mov (rvis1 - BranchBaseR), %tmp3
+ nop
+ nop
+ .align 32
+rrepl1: RPREPLOAD(f48,rrep1e,rrep1r)
+ fnop
+ faligndata %f32, %f34, %f16
+ faligndata %f34, %f36, %f18
+ faligndata %f36, %f38, %f20
+ faligndata %f38, %f40, %f22
+ faligndata %f40, %f42, %f24
+ faligndata %f42, %f44, %f26
+ faligndata %f44, %f46, %f28
+ faligndata %f46, %ftmp1, %f30
+ ba,pt %xcc, rightstr
+ mov (rvis0 - BranchBaseR), %tmp3
+ nop
+ nop
+ .align 32
+rrepl2: faligndata %f32, %f34, %f30
+ RPREPLOAD(f32,rrep2e,rrep2r)
+ fnop
+ fnop
+ faligndata %f50, %f52, %f16
+ faligndata %f52, %f54, %f18
+ faligndata %f54, %f56, %f20
+ faligndata %f56, %f58, %f22
+ faligndata %f58, %f60, %f24
+ faligndata %f60, %f62, %f26
+ faligndata %f62, %ftmp1, %f28
+ ba,pt %xcc, rightstr
+ mov (rvis3 - BranchBaseR), %tmp3
+ nop
+ .align 32
+rrepl3: faligndata %f48, %f50, %f30
+ RPREPLOAD(f48,rrep3e,rrep3r)
+ fnop
+ fnop
+ faligndata %f34, %f36, %f16
+ faligndata %f36, %f38, %f18
+ faligndata %f38, %f40, %f20
+ faligndata %f40, %f42, %f22
+ faligndata %f42, %f44, %f24
+ faligndata %f44, %f46, %f26
+ faligndata %f46, %ftmp1, %f28
+ ba,pt %xcc, rightstr
+ mov (rvis2 - BranchBaseR), %tmp3
+ nop
+ .align 32
+rrepl4: faligndata %f32, %f34, %f28
+ faligndata %f34, %f36, %f30
+ RPREPLOAD(f32,rrep4e,rrep4r)
+ fnop
+ fnop
+ fnop
+ faligndata %f52, %f54, %f16
+ faligndata %f54, %f56, %f18
+ faligndata %f56, %f58, %f20
+ faligndata %f58, %f60, %f22
+ faligndata %f60, %f62, %f24
+ faligndata %f62, %ftmp1, %f26
+ ba,pt %xcc, rightstr
+ mov (rvis5 - BranchBaseR), %tmp3
+ .align 32
+rrepl5: faligndata %f48, %f50, %f28
+ faligndata %f50, %f52, %f30
+ RPREPLOAD(f48,rrep5e,rrep5r)
+ fnop
+ fnop
+ fnop
+ faligndata %f36, %f38, %f16
+ faligndata %f38, %f40, %f18
+ faligndata %f40, %f42, %f20
+ faligndata %f42, %f44, %f22
+ faligndata %f44, %f46, %f24
+ faligndata %f46, %ftmp1, %f26
+ ba,pt %xcc, rightstr
+ mov (rvis4 - BranchBaseR), %tmp3
+ .align 32
+rrepl6: faligndata %f32, %f34, %f26
+ faligndata %f34, %f36, %f28
+ faligndata %f36, %f38, %f30
+ RPREPLOAD(f32,rrep6e,rrep6r)
+ fnop
+ fnop
+ fnop
+ fnop
+ faligndata %f54, %f56, %f16
+ faligndata %f56, %f58, %f18
+ faligndata %f58, %f60, %f20
+ faligndata %f60, %f62, %f22
+ faligndata %f62, %ftmp1, %f24
+ ba,pt %xcc, rightstr
+ mov (rvis7 - BranchBaseR), %tmp3
+ .align 32
+rrepl7: faligndata %f48, %f50, %f26
+ faligndata %f50, %f52, %f28
+ faligndata %f52, %f54, %f30
+ RPREPLOAD(f48,rrep7e,rrep7r)
+ fnop
+ fnop
+ fnop
+ fnop
+ faligndata %f38, %f40, %f16
+ faligndata %f40, %f42, %f18
+ faligndata %f42, %f44, %f20
+ faligndata %f44, %f46, %f22
+ faligndata %f46, %ftmp1, %f24
+ ba,pt %xcc, rightstr
+ mov (rvis6 - BranchBaseR), %tmp3
+ .align 32
+rrepl8: faligndata %f32, %f34, %f24
+ faligndata %f34, %f36, %f26
+ faligndata %f36, %f38, %f28
+ faligndata %f38, %f40, %f30
+ RPREPLOAD(f32,rrep8e,rrep8r)
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ faligndata %f56, %f58, %f16
+ faligndata %f58, %f60, %f18
+ faligndata %f60, %f62, %f20
+ faligndata %f62, %ftmp1, %f22
+ ba,pt %xcc, rightstr
+ mov (rvis9 - BranchBaseR), %tmp3
+ .align 32
+rrepl9: faligndata %f48, %f50, %f24
+ faligndata %f50, %f52, %f26
+ faligndata %f52, %f54, %f28
+ faligndata %f54, %f56, %f30
+ RPREPLOAD(f48,rrep9e,rrep9r)
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ faligndata %f40, %f42, %f16
+ faligndata %f42, %f44, %f18
+ faligndata %f44, %f46, %f20
+ faligndata %f46, %ftmp1, %f22
+ ba,pt %xcc, rightstr
+ mov (rvis8 - BranchBaseR), %tmp3
+ .align 32
+rrepl10:faligndata %f32, %f34, %f22
+ faligndata %f34, %f36, %f24
+ faligndata %f36, %f38, %f26
+ faligndata %f38, %f40, %f28
+ faligndata %f40, %f42, %f30
+ RPREPLOAD(f32,rrep10e,rrep10r)
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ faligndata %f58, %f60, %f16
+ faligndata %f60, %f62, %f18
+ faligndata %f62, %ftmp1, %f20
+ ba,pt %xcc, rightstr
+ mov (rvis11 - BranchBaseR), %tmp3
+ .align 32
+rrepl11:faligndata %f48, %f50, %f22
+ faligndata %f50, %f52, %f24
+ faligndata %f52, %f54, %f26
+ faligndata %f54, %f56, %f28
+ faligndata %f56, %f58, %f30
+ RPREPLOAD(f48,rrep11e,rrep11r)
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ faligndata %f42, %f44, %f16
+ faligndata %f44, %f46, %f18
+ faligndata %f46, %ftmp1, %f20
+ ba,pt %xcc, rightstr
+ mov (rvis10 - BranchBaseR), %tmp3
+ .align 32
+rrepl12:faligndata %f32, %f34, %f20
+ faligndata %f34, %f36, %f22
+ faligndata %f36, %f38, %f24
+ faligndata %f38, %f40, %f26
+ faligndata %f40, %f42, %f28
+ faligndata %f42, %f44, %f30
+ RPREPLOAD(f32,rrep12e,rrep12r)
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ faligndata %f60, %f62, %f16
+ faligndata %f62, %ftmp1, %f18
+ ba,pt %xcc, rightstr
+ mov (rvis13 - BranchBaseR), %tmp3
+ .align 32
+rrepl13:faligndata %f48, %f50, %f20
+ faligndata %f50, %f52, %f22
+ faligndata %f52, %f54, %f24
+ faligndata %f54, %f56, %f26
+ faligndata %f56, %f58, %f28
+ faligndata %f58, %f60, %f30
+ RPREPLOAD(f48,rrep13e,rrep13r)
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ faligndata %f44, %f46, %f16
+ faligndata %f46, %ftmp1, %f18
+ ba,pt %xcc, rightstr
+ mov (rvis12 - BranchBaseR), %tmp3
+ .align 32
+rrepl14:faligndata %f32, %f34, %f18
+ faligndata %f34, %f36, %f20
+ faligndata %f36, %f38, %f22
+ faligndata %f38, %f40, %f24
+ faligndata %f40, %f42, %f26
+ faligndata %f42, %f44, %f28
+ faligndata %f44, %f46, %f30
+ RPREPLOAD(f32,rrep14e,rrep14r)
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ faligndata %f62, %ftmp1, %f16
+ ba,pt %xcc, rightstr
+ mov (rvis15 - BranchBaseR), %tmp3
+ .align 32
+rrepl15:faligndata %f48, %f50, %f18
+ faligndata %f50, %f52, %f20
+ faligndata %f52, %f54, %f22
+ faligndata %f54, %f56, %f24
+ faligndata %f56, %f58, %f26
+ faligndata %f58, %f60, %f28
+ faligndata %f60, %f62, %f30
+ RPREPLOAD(f48,rrep15e,rrep15r)
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ faligndata %f46, %ftmp1, %f16
+ ba,pt %xcc, rightstr
+ mov (rvis14 - BranchBaseR), %tmp3
+
+ .align 64
+rvis0: nop
+ RLOAD(f32,rvis0e,rvis0r)
+ fnop
+ faligndata %f48, %f50, %f16
+ faligndata %f50, %f52, %f18
+ faligndata %f52, %f54, %f20
+ faligndata %f54, %f56, %f22
+ faligndata %f56, %f58, %f24
+ faligndata %f58, %f60, %f26
+ faligndata %f60, %f62, %f28
+ faligndata %f62, %ftmp1, %f30
+ STORE
+ sub %dst, 64, %dst
+rvis1: RLOAD(f48,rvis1e,rvis1r)
+ fnop
+ faligndata %f32, %f34, %f16
+ faligndata %f34, %f36, %f18
+ faligndata %f36, %f38, %f20
+ faligndata %f38, %f40, %f22
+ faligndata %f40, %f42, %f24
+ faligndata %f42, %f44, %f26
+ faligndata %f44, %f46, %f28
+ faligndata %f46, %ftmp1, %f30
+ STORE
+ ba,pt %xcc, rvis0+0x04
+ sub %dst, 64, %dst
+ .align 64
+rvis2: faligndata %f32, %f34, %ftmp8
+ RLOAD(f32,rvis2e,rvis2r)
+ fnop
+ fnop
+ faligndata %f50, %f52, %f16
+ faligndata %f52, %f54, %f18
+ faligndata %f54, %f56, %f20
+ faligndata %f56, %f58, %f22
+ faligndata %f58, %f60, %f24
+ faligndata %f60, %f62, %f26
+ faligndata %f62, %ftmp1, %f28
+ fmovd %ftmp8, %f30
+ STORE
+ sub %dst, 64, %dst
+rvis3: faligndata %f48, %f50, %ftmp8
+ RLOAD(f48,rvis3e,rvis3r)
+ fnop
+ fnop
+ faligndata %f34, %f36, %f16
+ faligndata %f36, %f38, %f18
+ faligndata %f38, %f40, %f20
+ faligndata %f40, %f42, %f22
+ faligndata %f42, %f44, %f24
+ faligndata %f44, %f46, %f26
+ faligndata %f46, %ftmp1, %f28
+ fmovd %ftmp8, %f30
+ STORE
+ ba,pt %xcc, rvis2
+ sub %dst, 64, %dst
+ .align 64
+rvis4: faligndata %f32, %f34, %ftmp7
+ faligndata %f34, %f36, %ftmp8
+ RLOAD(f32,rvis4e,rvis4r)
+ fnop
+ fnop
+ fnop
+ faligndata %f52, %f54, %f16
+ faligndata %f54, %f56, %f18
+ faligndata %f56, %f58, %f20
+ faligndata %f58, %f60, %f22
+ faligndata %f60, %f62, %f24
+ faligndata %f62, %ftmp1, %f26
+ fmovd %ftmp7, %f28
+ fmovd %ftmp8, %f30
+ STORE
+ sub %dst, 64, %dst
+rvis5: faligndata %f48, %f50, %ftmp7
+ faligndata %f50, %f52, %ftmp8
+ RLOAD(f48,rvis5e,rvis5r)
+ fnop
+ fnop
+ fnop
+ faligndata %f36, %f38, %f16
+ faligndata %f38, %f40, %f18
+ faligndata %f40, %f42, %f20
+ faligndata %f42, %f44, %f22
+ faligndata %f44, %f46, %f24
+ faligndata %f46, %ftmp1, %f26
+ fmovd %ftmp7, %f28
+ fmovd %ftmp8, %f30
+ STORE
+ ba,pt %xcc, rvis4
+ sub %dst, 64, %dst
+ .align 64
+rvis6: faligndata %f32, %f34, %ftmp6
+ faligndata %f34, %f36, %ftmp7
+ faligndata %f36, %f38, %ftmp8
+ RLOAD(f32,rvis6e,rvis6r)
+ fnop
+ fmovd %ftmp6, %f26
+ fmovd %ftmp7, %f28
+ fmovd %ftmp8, %f30
+ faligndata %f54, %f56, %f16
+ faligndata %f56, %f58, %f18
+ faligndata %f58, %f60, %f20
+ faligndata %f60, %f62, %f22
+ faligndata %f62, %ftmp1, %f24
+ STORE
+ sub %dst, 64, %dst
+rvis7: faligndata %f48, %f50, %ftmp6
+ faligndata %f50, %f52, %ftmp7
+ faligndata %f52, %f54, %ftmp8
+ RLOAD(f48,rvis7e,rvis7r)
+ fnop
+ fmovd %ftmp6, %f26
+ fmovd %ftmp7, %f28
+ fmovd %ftmp8, %f30
+ faligndata %f38, %f40, %f16
+ faligndata %f40, %f42, %f18
+ faligndata %f42, %f44, %f20
+ faligndata %f44, %f46, %f22
+ faligndata %f46, %ftmp1, %f24
+ STORE
+ ba,pt %xcc, rvis6
+ sub %dst, 64, %dst
+ .align 64
+rvis8: faligndata %f32, %f34, %ftmp5
+ faligndata %f34, %f36, %ftmp6
+ faligndata %f36, %f38, %ftmp7
+ faligndata %f38, %f40, %ftmp8
+ RLOAD(f32,rvis8e,rvis8r)
+ fnop
+ fmovd %ftmp5, %f24
+ fmovd %ftmp6, %f26
+ fmovd %ftmp7, %f28
+ fmovd %ftmp8, %f30
+ faligndata %f56, %f58, %f16
+ faligndata %f58, %f60, %f18
+ faligndata %f60, %f62, %f20
+ faligndata %f62, %ftmp1, %f22
+ STORE
+ sub %dst, 64, %dst
+rvis9: faligndata %f48, %f50, %ftmp5
+ faligndata %f50, %f52, %ftmp6
+ faligndata %f52, %f54, %ftmp7
+ faligndata %f54, %f56, %ftmp8
+ RLOAD(f48,rvis9e,rvis9r)
+ fnop
+ fmovd %ftmp5, %f24
+ fmovd %ftmp6, %f26
+ fmovd %ftmp7, %f28
+ fmovd %ftmp8, %f30
+ faligndata %f40, %f42, %f16
+ faligndata %f42, %f44, %f18
+ faligndata %f44, %f46, %f20
+ faligndata %f46, %ftmp1, %f22
+ STORE
+ ba,pt %xcc, rvis8
+ sub %dst, 64, %dst
+ .align 64
+rvis10: faligndata %f32, %f34, %ftmp4
+ faligndata %f34, %f36, %ftmp5
+ faligndata %f36, %f38, %ftmp6
+ faligndata %f38, %f40, %ftmp7
+ faligndata %f40, %f42, %ftmp8
+ RLOAD(f32,rvis10e,rvis10r)
+ fnop
+ fmovd %ftmp4, %f22
+ fmovd %ftmp5, %f24
+ fmovd %ftmp6, %f26
+ fmovd %ftmp7, %f28
+ fmovd %ftmp8, %f30
+ faligndata %f58, %f60, %f16
+ faligndata %f60, %f62, %f18
+ faligndata %f62, %ftmp1, %f20
+ STORE
+ sub %dst, 64, %dst
+rvis11: faligndata %f48, %f50, %ftmp4
+ faligndata %f50, %f52, %ftmp5
+ faligndata %f52, %f54, %ftmp6
+ faligndata %f54, %f56, %ftmp7
+ faligndata %f56, %f58, %ftmp8
+ RLOAD(f48,rvis11e,rvis11r)
+ fnop
+ fmovd %ftmp4, %f22
+ fmovd %ftmp5, %f24
+ fmovd %ftmp6, %f26
+ fmovd %ftmp7, %f28
+ fmovd %ftmp8, %f30
+ faligndata %f42, %f44, %f16
+ faligndata %f44, %f46, %f18
+ faligndata %f46, %ftmp1, %f20
+ STORE
+ ba,pt %xcc, rvis10
+ sub %dst, 64, %dst
+ .align 64
+rvis12: faligndata %f32, %f34, %ftmp3
+ faligndata %f34, %f36, %ftmp4
+ faligndata %f36, %f38, %ftmp5
+ faligndata %f38, %f40, %ftmp6
+ faligndata %f40, %f42, %ftmp7
+ faligndata %f42, %f44, %ftmp8
+ RLOAD(f32,rvis12e,rvis12r)
+ fnop
+ fmovd %ftmp3, %f20
+ fmovd %ftmp4, %f22
+ fmovd %ftmp5, %f24
+ fmovd %ftmp6, %f26
+ fmovd %ftmp7, %f28
+ fmovd %ftmp8, %f30
+ faligndata %f60, %f62, %f16
+ faligndata %f62, %ftmp1, %f18
+ STORE
+ sub %dst, 64, %dst
+rvis13: faligndata %f48, %f50, %ftmp3
+ faligndata %f50, %f52, %ftmp4
+ faligndata %f52, %f54, %ftmp5
+ faligndata %f54, %f56, %ftmp6
+ faligndata %f56, %f58, %ftmp7
+ faligndata %f58, %f60, %ftmp8
+ RLOAD(f48,rvis13e,rvis13r)
+ fnop
+ fmovd %ftmp3, %f20
+ fmovd %ftmp4, %f22
+ fmovd %ftmp5, %f24
+ fmovd %ftmp6, %f26
+ fmovd %ftmp7, %f28
+ fmovd %ftmp8, %f30
+ faligndata %f44, %f46, %f16
+ faligndata %f46, %ftmp1, %f18
+ STORE
+ ba,pt %xcc, rvis12
+ sub %dst, 64, %dst
+ .align 64
+rvis14: fnop
+ faligndata %f32, %f34, %f18
+ faligndata %f34, %f36, %f20
+ faligndata %f36, %f38, %f22
+ faligndata %f38, %f40, %f24
+ faligndata %f40, %f42, %f26
+ faligndata %f42, %f44, %f28
+ faligndata %f44, %f46, %f30
+ RLOAD(f32,rvis14e,rvis14r)
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ faligndata %f62, %ftmp1, %f16
+ STORE
+ sub %dst, 64, %dst
+rvis15: fnop
+ faligndata %f48, %f50, %f18
+ faligndata %f50, %f52, %f20
+ faligndata %f52, %f54, %f22
+ faligndata %f54, %f56, %f24
+ faligndata %f56, %f58, %f26
+ faligndata %f58, %f60, %f28
+ faligndata %f60, %f62, %f30
+ RLOAD(f48,rvis15e,rvis15r)
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ faligndata %f46, %ftmp1, %f16
+ STORE
+ ba,pt %xcc, rvis14
+ sub %dst, 64, %dst
+
+rightstr:
+ brlz,pn %curw, narrowstr + 4
+ cmp %rightw, 64
+ be,pn %icc, 2f
+ and %rightw, 0x38, %tmp1
+ andcc %rightw, 7, %g0
+ be,pn %icc, 1f
+ neg %tmp1
+ sub %g0, %rightw, %tmp5
+ add %branchbase, (3f - BranchBaseR - 8), %tmp2
+ edge8l %tmp5, %g0, %tmp5
+ sub %dst, %tmp1, %tmp4
+ jmpl %tmp1 + %tmp2, %g0
+ add %tmp4, 0x40, %tmp4
+1: addcc %branchbase, (4f - BranchBaseR), %tmp2
+ sra %tmp1, 1, %tmp1
+ jmpl %tmp1 + %tmp2, %g0
+2: add %dst, 0x40, %tmp1
+ jmpl %branchbase + %tmp3, %g0
+ stda %f16, [%tmp1] ASI_BLK_P
+ ba,pt %xcc, 3f+0x00
+ stda %f30, [%tmp4 + %tmp5] ASI_PST8_P
+ ba,pt %xcc, 3f+0x04
+ stda %f28, [%tmp4 + %tmp5] ASI_PST8_P
+ ba,pt %xcc, 3f+0x08
+ stda %f26, [%tmp4 + %tmp5] ASI_PST8_P
+ ba,pt %xcc, 3f+0x0c
+ stda %f24, [%tmp4 + %tmp5] ASI_PST8_P
+ ba,pt %xcc, 3f+0x10
+ stda %f22, [%tmp4 + %tmp5] ASI_PST8_P
+ ba,pt %xcc, 3f+0x14
+ stda %f20, [%tmp4 + %tmp5] ASI_PST8_P
+ ba,pt %xcc, 3f+0x18
+ stda %f18, [%tmp4 + %tmp5] ASI_PST8_P
+ jmpl %branchbase + %tmp3, %g0
+ stda %f16, [%tmp4 + %tmp5] ASI_PST8_P
+3: std %f28, [%dst + 0x70]
+ std %f26, [%dst + 0x68]
+ std %f24, [%dst + 0x60]
+ std %f22, [%dst + 0x58]
+ std %f20, [%dst + 0x50]
+ std %f18, [%dst + 0x48]
+ std %f16, [%dst + 0x40]
+4: jmpl %branchbase + %tmp3, %g0
+ nop
+
+leftstr:cmp %leftw, 64
+ be,pn %icc, 2f
+ and %leftw, 0x38, %tmp1
+ andcc %leftw, 7, %g0
+ be,pn %icc, 1f
+ neg %tmp1
+ sub %dst, %leftw, %tmp4
+ add %branchbase, (3f - BranchBaseR - 8), %tmp2
+ edge8 %tmp4, %g0, %tmp5
+ andn %tmp4, 7, %tmp4
+ add %mode, %skind, %mode
+ jmpl %tmp2 + %tmp1, %g0
+ add %tmp4, 0x40, %tmp4
+1: add %branchbase, (4f - BranchBaseR), %tmp2
+ sra %tmp1, 1, %tmp1
+ jmpl %tmp2 + %tmp1, %g0
+2: add %mode, %skind, %mode
+ ba,pt %xcc, 4f
+ stda %f16, [%dst] ASI_BLK_P
+ ba,pt %xcc, 3f+0x00
+ stda %f16, [%tmp4 + %tmp5] ASI_PST8_P
+ ba,pt %xcc, 3f+0x04
+ stda %f18, [%tmp4 + %tmp5] ASI_PST8_P
+ ba,pt %xcc, 3f+0x08
+ stda %f20, [%tmp4 + %tmp5] ASI_PST8_P
+ ba,pt %xcc, 3f+0x0c
+ stda %f22, [%tmp4 + %tmp5] ASI_PST8_P
+ ba,pt %xcc, 3f+0x10
+ stda %f24, [%tmp4 + %tmp5] ASI_PST8_P
+ ba,pt %xcc, 3f+0x14
+ stda %f26, [%tmp4 + %tmp5] ASI_PST8_P
+ ba,pt %xcc, 3f+0x18
+ stda %f28, [%tmp4 + %tmp5] ASI_PST8_P
+ ba,pt %xcc, 3f+0x1c
+ stda %f30, [%tmp4 + %tmp5] ASI_PST8_P
+3: std %f18, [%dst + 0x08]
+ std %f20, [%dst + 0x10]
+ std %f22, [%dst + 0x18]
+ std %f24, [%dst + 0x20]
+ std %f26, [%dst + 0x28]
+ std %f28, [%dst + 0x30]
+ std %f30, [%dst + 0x38]
+4: brnz,pn %narrow, rnarrow_cont
+ deccc %srcnotdone
+ blu,pn %ICC, rreturn
+ sub %mode, %dkind, %mode
+ alignaddr %mode, %g0, %g0
+ and %mode, 63, %mode
+ cmp %srcnext, %srcn
+ bne,a,pn %ICC, 6f
+ xor %fregset, 64, %fregset
+ brnz,a,pn %fregset, 5f
+ ldda [%src] ASI_BLK_P, %f32
+ ldda [%src] ASI_BLK_P, %f48
+5: sub %src, 64, %src
+6: add %dst, %dkind, %dst
+ sub %w, %leftw, %tmp1
+ add %srcstart, %skind, %srcstart
+ add %dst, %tmp1, %dst
+ add %rightw, %dkind, %rightw
+ add %dst, 63, %dst
+ sub %rightw, 1, %rightw
+ sub %dkind, %leftw, %leftw
+ and %rightw, 63, %rightw
+ and %leftw, 63, %leftw
+ add %rightw, 1, %rightw
+ mov 64, %tmp1
+ andn %dst, 63, %dst
+ sub %tmp1, %leftw, %leftw
+rroll_wide:
+ add %srcstart, %skind, %srcnext
+ sub %srcstart, %w, %srcend
+ fnop
+ deccc %srcnext
+ sll %mode, 4, %tmp4
+ fnop
+ andn %srcnext, 63, %srcnext
+ andn %srcend, 63, %srcend
+ fnop
+ mov %srcnext, %srcn
+ and %mode, 7, %leftw2
+ fnop
+ andn %tmp4, 127, %tmp4
+ sub %leftw, %leftw2, %leftw2
+ fnop
+ add %tmp4, %fregset, %tmp4
+ subcc %w, %leftw, %curw
+ fnop
+ srl %tmp4, 1, %tmp3
+ sub %tmp1, %mode, %tmp1
+ fnop
+ add %tmp3, (rrepn0 - BranchBaseR), %tmp2
+ cmp %tmp1, %rightw
+ add %tmp4, %tmp3, %tmp4
+ sub %srcnext, 64, %tmp1
+ movgeu %icc, %tmp2, %tmp4
+ cmp %srcnext, %srcend
+ sub %dst, 64, %dst
+ move %ICC, %tmp1, %srcnext
+ jmpl %branchbase + %tmp4, %g0
+ sub %curw, %rightw, %curw
+
+rreturn:return %i7+8
+ wr %g0, 0, %fprs
+
+narrowstr:
+ cmp %rightw, 64
+ add %dst, 0x80, %fregset
+ and %rightw, 0x38, %tmp1
+ sub %fregset, %leftw, %tmp2
+ mov %w, %tmp4
+ andn %tmp2, 7, %fregset
+ be,pn %icc, 2f
+ edge8 %tmp2, %g0, %srcend
+ andcc %rightw, 7, %g0
+ be,pn %icc, 1f
+ neg %tmp1
+ sub %g0, %rightw, %tmp4
+ add %tmp1, (2f - BranchBaseR - 8), %tmp1
+ add %dst, 0x40, %tmp5
+ sub %leftw, 0x41, %tmp2
+ add %tmp5, %rightw, %tmp5
+ edge8l %tmp4, %tmp2, %tmp2
+ and %rightw, 7, %tmp4
+ andn %tmp5, 7, %tmp5
+ jmpl %branchbase + %tmp1, %g0
+ sub %w, %tmp4, %tmp4
+1: addcc %branchbase, (4f - BranchBaseR - 8), %tmp2
+ sll %tmp1, 1, %tmp1
+ jmpl %tmp2 + %tmp1, %g0
+ nop
+ ba,pt %xcc, 3f+0x00
+ stda %f30, [%tmp5 + %tmp2] ASI_PST8_P
+ ba,pt %xcc, 3f+0x10
+ stda %f28, [%tmp5 + %tmp2] ASI_PST8_P
+ ba,pt %xcc, 3f+0x20
+ stda %f26, [%tmp5 + %tmp2] ASI_PST8_P
+ ba,pt %xcc, 3f+0x30
+ stda %f24, [%tmp5 + %tmp2] ASI_PST8_P
+ ba,pt %xcc, 3f+0x40
+ stda %f22, [%tmp5 + %tmp2] ASI_PST8_P
+ ba,pt %xcc, 3f+0x50
+ stda %f20, [%tmp5 + %tmp2] ASI_PST8_P
+ ba,pt %xcc, 3f+0x60
+ stda %f18, [%tmp5 + %tmp2] ASI_PST8_P
+ ba,pt %xcc, 3f+0x70
+ stda %f16, [%tmp5 + %tmp2] ASI_PST8_P
+2: subcc %tmp4, 8, %tmp4
+ bl,pn %icc, 4f+0x00
+ fnop
+ std %f30, [%dst + 0x78]
+3: subcc %tmp4, 8, %tmp4
+ bl,pn %icc, 4f+0x10
+ fnop
+ std %f28, [%dst + 0x70]
+ subcc %tmp4, 8, %tmp4
+ bl,pn %icc, 4f+0x20
+ fnop
+ std %f26, [%dst + 0x68]
+ subcc %tmp4, 8, %tmp4
+ bl,pn %icc, 4f+0x30
+ fnop
+ std %f24, [%dst + 0x60]
+ subcc %tmp4, 8, %tmp4
+ bl,pn %icc, 4f+0x40
+ fnop
+ std %f22, [%dst + 0x58]
+ subcc %tmp4, 8, %tmp4
+ bl,pn %icc, 4f+0x50
+ fnop
+ std %f20, [%dst + 0x50]
+ subcc %tmp4, 8, %tmp4
+ bl,pn %icc, 4f+0x60
+ fnop
+ std %f18, [%dst + 0x48]
+ subcc %tmp4, 8, %tmp4
+ bl,pn %icc, 4f+0x70
+ fnop
+ std %f16, [%dst + 0x40]
+ ba,pt %xcc, 5f
+ nop
+4: cmp %tmp4, -8
+ bg,a,pn %ICC, 5f
+ stda %f30, [%fregset + %srcend] ASI_PST8_P
+ ba,a,pt %xcc, 5f
+ cmp %tmp4, -8
+ bg,a,pn %ICC, 5f
+ stda %f28, [%fregset + %srcend] ASI_PST8_P
+ ba,a,pt %xcc, 5f
+ cmp %tmp4, -8
+ bg,a,pn %ICC, 5f
+ stda %f26, [%fregset + %srcend] ASI_PST8_P
+ ba,a,pt %xcc, 5f
+ cmp %tmp4, -8
+ bg,a,pn %ICC, 5f
+ stda %f24, [%fregset + %srcend] ASI_PST8_P
+ ba,a,pt %xcc, 5f
+ cmp %tmp4, -8
+ bg,a,pn %ICC, 5f
+ stda %f22, [%fregset + %srcend] ASI_PST8_P
+ ba,a,pt %xcc, 5f
+ cmp %tmp4, -8
+ bg,a,pn %ICC, 5f
+ stda %f20, [%fregset + %srcend] ASI_PST8_P
+ ba,a,pt %xcc, 5f
+ cmp %tmp4, -8
+ bg,a,pn %ICC, 5f
+ stda %f18, [%fregset + %srcend] ASI_PST8_P
+ ba,a,pt %xcc, 5f
+ cmp %tmp4, -8
+ bg,a,pn %ICC, 5f
+ stda %f16, [%fregset + %srcend] ASI_PST8_P
+5: and %tmp3, 60, %tmp3
+ add %dst, 64, %dst
+ xor %tmp3, 60, %tmp3
+ add %mode, %skind, %mode
+ add %tmp3, 4, %tmp3
+ brz,pn %h, rreturn
+ and %tmp3, 64, %fregset
+rnarrow_cont:
+ deccc %h
+ blu,pn %ICC, rreturn
+ sub %mode, %dkind, %mode
+ alignaddr %mode, %g0, %g0
+ and %mode, 63, %mode
+ sub %srcnext, %srcn, %tmp4
+ add %dst, %dkind, %dst
+ sub %w, %leftw, %tmp1
+ add %srcstart, %skind, %srcstart
+ add %dst, %tmp1, %dst
+ add %rightw, %dkind, %rightw
+ sub %dkind, %leftw, %leftw
+ sub %rightw, 1, %rightw
+ and %leftw, 63, %leftw
+ add %dst, 63, %dst
+ mov 64, %tmp1
+ and %rightw, 63, %rightw
+ sub %tmp1, %leftw, %leftw
+ add %srcstart, %skind, %srcnext
+ add %rightw, 1, %rightw
+ sub %srcstart, %w, %srcend
+ dec %srcnext
+ andn %srcend, 63, %srcend
+ andn %srcnext, 63, %srcnext
+ sub %w, %leftw, %prepw
+ mov %srcnext, %srcn
+ sub %srcnext, 64, %tmp3
+ add %srcnext, 64, %tmp2
+ cmp %skind, 0
+ movg %ICC, %tmp2, %tmp3
+ mov %h, %srcnotdone
+ sub %prepw, %rightw, %prepw
+ sub %srcstart, 1, %tmp1
+ cmp %srcnext, %srcend
+ move %ICC, %tmp3, %srcnext
+ and %tmp1, 63, %tmp1
+ sub %srcnext, 64, %tmp3
+ sub %tmp1, %w, %tmp1
+ cmp %srcnext, %srcend
+ move %ICC, %tmp3, %srcnext
+ mov %prepw, %curw
+ cmp %tmp1, -65
+ movl %ICC, 64, %prepw
+ andn %dst, 63, %dst
+ cmp %srcnext, %srcstop
+ move %ICC, 0, %srcnotdone
+ brnz,a,pn %tmp4, rroll_narrow
+ xor %fregset, 64, %fregset
+ cmp %tmp1, -1
+ bl,pt %ICC, 6f
+ tst %srcnotdone
+ be,a,pn %ICC, rroll_narrow
+ membar SYNC
+ mov %srcnext, %src
+6: brnz,a,pn %fregset, 7f
+ ldda [%src] ASI_BLK_P, %f32
+ ldda [%src] ASI_BLK_P, %f48
+7: subcc %src, 64, %src
+rroll_narrow:
+ fnop
+ sll %mode, 4, %tmp2
+ and %mode, 7, %leftw2
+ fnop
+ andn %tmp2, 127, %tmp2
+ sub %dst, 64, %dst
+ fnop
+ add %tmp2, %fregset, %tmp2
+ subcc %leftw, %leftw2, %leftw2
+ fnop
+ srl %tmp2, 1, %tmp3
+ add %tmp3, (rrepr0 - BranchBaseR), %tmp4
+ fnop
+ add %tmp2, %tmp3, %tmp2
+ cmp %tmp1, -1
+ fnop
+ mov 64, %tmp1
+ movge %icc, %tmp4, %tmp2
+ sub %tmp1, %mode, %tmp1
+ add %tmp3, (rrepn0 - BranchBaseR), %tmp4
+ fnop
+ cmp %tmp1, %rightw
+ movgeu %icc, %tmp4, %tmp2
+ jmpl %branchbase + %tmp2, %g0
+ and %tmp3, 32, %tmp3
+
+#define RVISEND1(i,tgt,tgtr) \
+tgt: \
+ brnz,pt %curw, 1f; \
+ cmp %leftw2, ((i&14)*4); \
+ bg,pn %icc, tgtr - 8; \
+ tst %srcnotdone; \
+ be,a,pn %ICC, tgtr; \
+ membar SYNC; \
+ ba,pt %xcc, tgtr - 8; \
+ mov %srcnext, %src; \
+1: mov ((i & 1) ^ 1) * 64, %fregset;
+
+#define RVISEND2(i,fset) \
+ brz,a,pn %srcnotdone, 3f; \
+ membar SYNC; \
+ ldda [%srcnext] ASI_BLK_P, %fset; \
+ sub %srcnext, 64, %src; \
+3: mov (i & 1) * 64, %fregset;
+
+RVISEND1(0,rvis0e,rvis0r)
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ ble,pn %icc, leftstr
+ faligndata %ftmp2, %ftmp1, %f30
+RVISEND2(0,f32)
+ fnop
+ faligndata %f48, %f50, %f16
+ faligndata %f50, %f52, %f18
+ faligndata %f52, %f54, %f20
+ faligndata %f54, %f56, %f22
+ faligndata %f56, %f58, %f24
+ faligndata %f58, %f60, %f26
+ faligndata %f60, %f62, %f28
+ ba,pt %xcc, leftstr
+ faligndata %f62, %ftmp1, %f30
+RVISEND1(1,rvis1e,rvis1r)
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ ble,pn %icc, leftstr
+ faligndata %ftmp2, %ftmp1, %f30
+RVISEND2(1,f48)
+ fnop
+ faligndata %f32, %f34, %f16
+ faligndata %f34, %f36, %f18
+ faligndata %f36, %f38, %f20
+ faligndata %f38, %f40, %f22
+ faligndata %f40, %f42, %f24
+ faligndata %f42, %f44, %f26
+ faligndata %f44, %f46, %f28
+ ba,pt %xcc, leftstr
+ faligndata %f46, %ftmp1, %f30
+RVISEND1(2,rvis2e,rvis2r)
+ fnop
+ fnop
+ fnop
+ fnop
+ faligndata %ftmp2, %ftmp1, %f28
+ ble,pn %icc, leftstr
+ fmovd %ftmp8, %f30
+RVISEND2(2,f32)
+ fnop
+ fnop
+ faligndata %f50, %f52, %f16
+ faligndata %f52, %f54, %f18
+ faligndata %f54, %f56, %f20
+ faligndata %f56, %f58, %f22
+ faligndata %f58, %f60, %f24
+ faligndata %f60, %f62, %f26
+ ba,pt %xcc, leftstr
+ faligndata %f62, %ftmp1, %f28
+RVISEND1(3,rvis3e,rvis3r)
+ fnop
+ fnop
+ fnop
+ fnop
+ faligndata %ftmp2, %ftmp1, %f28
+ ble,pn %icc, leftstr
+ fmovd %ftmp8, %f30
+RVISEND2(3,f48)
+ fnop
+ fnop
+ faligndata %f34, %f36, %f16
+ faligndata %f36, %f38, %f18
+ faligndata %f38, %f40, %f20
+ faligndata %f40, %f42, %f22
+ faligndata %f42, %f44, %f24
+ faligndata %f44, %f46, %f26
+ ba,pt %xcc, leftstr
+ faligndata %f46, %ftmp1, %f28
+RVISEND1(4,rvis4e,rvis4r)
+ fnop
+ fnop
+ faligndata %ftmp2, %ftmp1, %f26
+ fmovd %ftmp7, %f28
+ ble,pn %icc, leftstr
+ fmovd %ftmp8, %f30
+RVISEND2(4,f32)
+ fnop
+ fnop
+ fnop
+ faligndata %f52, %f54, %f16
+ faligndata %f54, %f56, %f18
+ faligndata %f56, %f58, %f20
+ faligndata %f58, %f60, %f22
+ faligndata %f60, %f62, %f24
+ ba,pt %xcc, leftstr
+ faligndata %f62, %ftmp1, %f26
+RVISEND1(5,rvis5e,rvis5r)
+ fnop
+ fnop
+ faligndata %ftmp2, %ftmp1, %f26
+ fmovd %ftmp7, %f28
+ ble,pn %icc, leftstr
+ fmovd %ftmp8, %f30
+RVISEND2(5,f48)
+ fnop
+ fnop
+ fnop
+ faligndata %f36, %f38, %f16
+ faligndata %f38, %f40, %f18
+ faligndata %f40, %f42, %f20
+ faligndata %f42, %f44, %f22
+ faligndata %f44, %f46, %f24
+ ba,pt %xcc, leftstr
+ faligndata %f46, %ftmp1, %f26
+RVISEND1(6,rvis6e,rvis6r)
+ faligndata %ftmp2, %ftmp1, %f24
+ fmovd %ftmp6, %f26
+ fmovd %ftmp7, %f28
+ ble,pn %icc, leftstr
+ fmovd %ftmp8, %f30
+RVISEND2(6,f32)
+ fnop
+ fnop
+ fnop
+ fnop
+ faligndata %f54, %f56, %f16
+ faligndata %f56, %f58, %f18
+ faligndata %f58, %f60, %f20
+ faligndata %f60, %f62, %f22
+ ba,pt %xcc, leftstr
+ faligndata %f62, %ftmp1, %f24
+RVISEND1(7,rvis7e,rvis7r)
+ faligndata %ftmp2, %ftmp1, %f24
+ fmovd %ftmp6, %f26
+ fmovd %ftmp7, %f28
+ ble,pn %icc, leftstr
+ fmovd %ftmp8, %f30
+RVISEND2(7,f48)
+ fnop
+ fnop
+ fnop
+ fnop
+ faligndata %f38, %f40, %f16
+ faligndata %f40, %f42, %f18
+ faligndata %f42, %f44, %f20
+ faligndata %f44, %f46, %f22
+ ba,pt %xcc, leftstr
+ faligndata %f46, %ftmp1, %f24
+RVISEND1(8,rvis8e,rvis8r)
+ faligndata %ftmp2, %ftmp1, %f22
+ fmovd %ftmp5, %f24
+ fmovd %ftmp6, %f26
+ fmovd %ftmp7, %f28
+ ble,pn %icc, leftstr
+ fmovd %ftmp8, %f30
+RVISEND2(8,f32)
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ faligndata %f56, %f58, %f16
+ faligndata %f58, %f60, %f18
+ faligndata %f60, %f62, %f20
+ ba,pt %xcc, leftstr
+ faligndata %f62, %ftmp1, %f22
+RVISEND1(9,rvis9e,rvis9r)
+ faligndata %ftmp2, %ftmp1, %f22
+ fmovd %ftmp5, %f24
+ fmovd %ftmp6, %f26
+ fmovd %ftmp7, %f28
+ ble,pn %icc, leftstr
+ fmovd %ftmp8, %f30
+RVISEND2(9,f48)
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ faligndata %f40, %f42, %f16
+ faligndata %f42, %f44, %f18
+ faligndata %f44, %f46, %f20
+ ba,pt %xcc, leftstr
+ faligndata %f46, %ftmp1, %f22
+RVISEND1(10,rvis10e,rvis10r)
+ faligndata %ftmp2, %ftmp1, %f20
+ fmovd %ftmp4, %f22
+ fmovd %ftmp5, %f24
+ fmovd %ftmp6, %f26
+ fmovd %ftmp7, %f28
+ ble,pn %icc, leftstr
+ fmovd %ftmp8, %f30
+RVISEND2(10,f32)
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ faligndata %f58, %f60, %f16
+ faligndata %f60, %f62, %f18
+ ba,pt %xcc, leftstr
+ faligndata %f62, %ftmp1, %f20
+RVISEND1(11,rvis11e,rvis11r)
+ faligndata %ftmp2, %ftmp1, %f20
+ fmovd %ftmp4, %f22
+ fmovd %ftmp5, %f24
+ fmovd %ftmp6, %f26
+ fmovd %ftmp7, %f28
+ ble,pn %icc, leftstr
+ fmovd %ftmp8, %f30
+RVISEND2(11,f48)
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ faligndata %f42, %f44, %f16
+ faligndata %f44, %f46, %f18
+ ba,pt %xcc, leftstr
+ faligndata %f46, %ftmp1, %f20
+RVISEND1(12,rvis12e,rvis12r)
+ faligndata %ftmp2, %ftmp1, %f18
+ fmovd %ftmp3, %f20
+ fmovd %ftmp4, %f22
+ fmovd %ftmp5, %f24
+ fmovd %ftmp6, %f26
+ fmovd %ftmp7, %f28
+ ble,pn %icc, leftstr
+ fmovd %ftmp8, %f30
+RVISEND2(12,f32)
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ faligndata %f60, %f62, %f16
+ ba,pt %xcc, leftstr
+ faligndata %f62, %ftmp1, %f18
+RVISEND1(13,rvis13e,rvis13r)
+ faligndata %ftmp2, %ftmp1, %f18
+ fmovd %ftmp3, %f20
+ fmovd %ftmp4, %f22
+ fmovd %ftmp5, %f24
+ fmovd %ftmp6, %f26
+ fmovd %ftmp7, %f28
+ ble,pn %icc, leftstr
+ fmovd %ftmp8, %f30
+RVISEND2(13,f48)
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ faligndata %f44, %f46, %f16
+ ba,pt %xcc, leftstr
+ faligndata %f46, %ftmp1, %f18
+RVISEND1(14,rvis14e,rvis14r)
+ ble,pn %icc, leftstr
+ faligndata %ftmp2, %ftmp1, %f16
+RVISEND2(14,f32)
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ ba,pt %xcc, leftstr
+ faligndata %f62, %ftmp1, %f16
+RVISEND1(15,rvis15e,rvis15r)
+ ble,pn %icc, leftstr
+ faligndata %ftmp2, %ftmp1, %f16
+RVISEND2(15,f48)
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ fnop
+ ba,pt %xcc, leftstr
+ faligndata %f46, %ftmp1, %f16
+
+#define RREPEND(tgt,tgtr) \
+tgt: \
+ brnz,pt %srcnotdone, tgtr - 8; \
+ mov %srcnext, %src; \
+ ba,pt %xcc, tgtr; \
+ membar SYNC;
+
+ .align 16
+RREPEND(rrep0e,rrep0r)
+RREPEND(rrep1e,rrep1r)
+RREPEND(rrep2e,rrep2r)
+RREPEND(rrep3e,rrep3r)
+RREPEND(rrep4e,rrep4r)
+RREPEND(rrep5e,rrep5r)
+RREPEND(rrep6e,rrep6r)
+RREPEND(rrep7e,rrep7r)
+RREPEND(rrep8e,rrep8r)
+RREPEND(rrep9e,rrep9r)
+RREPEND(rrep10e,rrep10r)
+RREPEND(rrep11e,rrep11r)
+RREPEND(rrep12e,rrep12r)
+RREPEND(rrep13e,rrep13r)
+RREPEND(rrep14e,rrep14r)
+RREPEND(rrep15e,rrep15r)
diff --git a/src/ffb.h b/src/ffb.h
new file mode 100644
index 0000000..af54db2
--- /dev/null
+++ b/src/ffb.h
@@ -0,0 +1,325 @@
+/*
+ * Acceleration for the Creator and Creator3D framebuffer - defines.
+ *
+ * Copyright (C) 1998,1999,2000 Jakub Jelinek (jakub@redhat.com)
+ * Copyright (C) 1998 Michal Rehacek (majkl@iname.com)
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * JAKUB JELINEK, MICHAL REHACEK, OR DAVID MILLER BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb.h,v 1.8 2002/12/06 02:44:03 tsi Exp $ */
+
+#ifndef FFB_H
+#define FFB_H
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+#include "xf86RamDac.h"
+#include "Xmd.h"
+#include "gcstruct.h"
+#include "windowstr.h"
+#include "ffb_regs.h"
+#include "xf86sbusBus.h"
+#include "ffb_dac.h"
+#ifdef XF86DRI
+#include "xf86drm.h"
+#include "ffb_drishare.h"
+#endif
+#ifndef DPMS_SERVER
+#define DPMS_SERVER
+#endif /* DPMS_SERVER */
+#include "extensions/dpms.h"
+
+
+/* Various offsets in virtual (ie. mmap()) spaces Linux and Solaris support. */
+/* Note: do not mmap FFB_DFB8R_VOFF and following mappings using one mmap together
+ with any previous SFB mapping, otherwise the OS won't be able to use 4M pages
+ for the DFB mappings. -jj */
+#define FFB_SFB8R_VOFF 0x00000000
+#define FFB_SFB8G_VOFF 0x00400000
+#define FFB_SFB8B_VOFF 0x00800000
+#define FFB_SFB8X_VOFF 0x00c00000
+#define FFB_SFB32_VOFF 0x01000000
+#define FFB_SFB64_VOFF 0x02000000
+#define FFB_FBC_REGS_VOFF 0x04000000
+#define FFB_BM_FBC_REGS_VOFF 0x04002000
+#define FFB_DFB8R_VOFF 0x04004000
+#define FFB_DFB8G_VOFF 0x04404000
+#define FFB_DFB8B_VOFF 0x04804000
+#define FFB_DFB8X_VOFF 0x04c04000
+#define FFB_DFB24_VOFF 0x05004000
+#define FFB_DFB32_VOFF 0x06004000
+#define FFB_DFB422A_VOFF 0x07004000 /* DFB 422 mode write to A */
+#define FFB_DFB422AD_VOFF 0x07804000 /* DFB 422 mode with line doubling */
+#define FFB_DFB24B_VOFF 0x08004000 /* DFB 24bit mode write to B */
+#define FFB_DFB422B_VOFF 0x09004000 /* DFB 422 mode write to B */
+#define FFB_DFB422BD_VOFF 0x09804000 /* DFB 422 mode with line doubling */
+#define FFB_SFB16Z_VOFF 0x0a004000 /* 16bit mode Z planes */
+#define FFB_SFB8Z_VOFF 0x0a404000 /* 8bit mode Z planes */
+#define FFB_SFB422_VOFF 0x0ac04000 /* SFB 422 mode write to A/B */
+#define FFB_SFB422D_VOFF 0x0b404000 /* SFB 422 mode with line doubling */
+#define FFB_FBC_KREGS_VOFF 0x0bc04000
+#define FFB_DAC_VOFF 0x0bc06000
+#define FFB_PROM_VOFF 0x0bc08000
+#define FFB_EXP_VOFF 0x0bc18000
+
+#if defined(__GNUC__) && defined(USE_VIS)
+#define FFB_ALIGN64 __attribute__((aligned(8)))
+#else
+#define FFB_ALIGN64
+#endif
+
+typedef struct {
+ unsigned int fg FFB_ALIGN64, bg; /* FG/BG colors for stipple */
+ unsigned int patalign; /* X/Y alignment of bits */
+ unsigned char alu; /* ALU operation */
+ unsigned char inhw; /* Cached in FFB */
+ unsigned char pagable; /* Can be used in a pagefill */
+ unsigned char ph; /* Page buffer height */
+ unsigned int bits[32]; /* The stipple bits themselves */
+} CreatorStippleRec, *CreatorStipplePtr;
+
+typedef struct {
+ int type;
+ unsigned int linepat;
+ CreatorStipplePtr stipple;
+ void (*PolySegment)(DrawablePtr, GCPtr, int, xSegment *);
+ void (*Polylines)(DrawablePtr, GCPtr, int, int, DDXPointPtr);
+} CreatorPrivGCRec, *CreatorPrivGCPtr;
+
+/* WID and framebuffer controls are a property of the
+ * window.
+ */
+typedef struct {
+ CreatorStipplePtr Stipple;
+ unsigned int fbc_base;
+ unsigned int wid;
+} CreatorPrivWinRec, *CreatorPrivWinPtr;
+
+enum ffb_resolution {
+ ffb_res_standard = 0, /* 1280 x 1024 */
+ ffb_res_high, /* 1920 x 1360 */
+ ffb_res_stereo, /* 960 x 580 */
+ ffb_res_portrait /* 1280 x 2048 */
+};
+
+enum ffb_chip_type {
+ ffb1_prototype = 0, /* Early pre-FCS FFB */
+ ffb1_standard, /* First FCS FFB, 100Mhz UPA, 66MHz gclk */
+ ffb1_speedsort, /* Second FCS FFB, 100Mhz UPA, 75MHz gclk */
+ ffb2_prototype, /* Early pre-FCS vertical FFB2 */
+ ffb2_vertical, /* First FCS FFB2/vertical, 100Mhz UPA, 100MHZ gclk,
+ 75(SingleBuffer)/83(DoubleBuffer) MHz fclk */
+ ffb2_vertical_plus, /* Second FCS FFB2/vertical, same timings */
+ ffb2_horizontal, /* First FCS FFB2/horizontal, same timings as FFB2/vert */
+ ffb2_horizontal_plus, /* Second FCS FFB2/horizontal, same timings */
+ afb_m3, /* FCS Elite3D, 3 float chips */
+ afb_m6 /* FCS Elite3D, 6 float chips */
+};
+
+#ifdef XF86DRI
+typedef struct {
+ int index;
+} FFBConfigPrivRec, *FFBConfigPrivPtr;
+#endif
+
+typedef struct {
+ unsigned short fifo_cache;
+ unsigned short rp_active;
+ ffb_fbcPtr regs;
+ unsigned int ppc_cache;
+ unsigned int pmask_cache;
+ unsigned int rop_cache;
+ unsigned int drawop_cache;
+ unsigned int fg_cache;
+ unsigned int bg_cache;
+ unsigned int fontw_cache;
+ unsigned int fontinc_cache;
+ unsigned int fbc_cache;
+ unsigned int wid_cache;
+ enum ffb_chip_type ffb_type;
+ CreatorStipplePtr laststipple;
+ unsigned *fb;
+ unsigned *sfb32;
+ unsigned *sfb8r;
+ unsigned *sfb8x;
+ unsigned *dfb24;
+ unsigned *dfb8r;
+ unsigned *dfb8x;
+
+ /* Slot offset 0x0200000, used to probe board type. */
+ volatile unsigned int *strapping_bits;
+
+ /* Needed for some 3DRAM revisions and ffb1 in hires */
+ unsigned char disable_pagefill;
+
+ /* Needed for FFB2/AFB when in stereo or hires */
+ unsigned char disable_fastfill_ap;
+
+ /* Needed for FFB1 in highres mode */
+ unsigned char disable_vscroll;
+
+ /* Needed on all FFB1 boards. */
+ unsigned char has_brline_bug;
+
+ /* Available on FFB2 and AFB */
+ unsigned char use_blkread_prefetch;
+
+ /* Framebuffer configuration */
+ unsigned char has_double_res;
+ unsigned char has_z_buffer;
+ unsigned char has_double_buffer;
+
+ enum ffb_resolution ffb_res;
+ BoxRec ClippedBoxBuf[64];
+ xRectangle Pf_Fixups[4];
+ short Pf_AlignTab[0x800];
+
+ ffb_dacPtr dac;
+ sbusDevicePtr psdp;
+ Bool HWCursor;
+ Bool NoAccel;
+ Bool vtSema;
+ CloseScreenProcPtr CloseScreen;
+ xf86CursorInfoPtr CursorInfoRec;
+ unsigned char CursorShiftX, CursorShiftY;
+ unsigned char *CursorData;
+
+ PixmapPtr pix32, pix8;
+
+ void *I2C;
+ struct ffb_dac_info dac_info;
+
+#ifdef XF86DRI
+ void *pDRIInfo;
+ int numVisualConfigs;
+ void *pVisualConfigs;
+ FFBConfigPrivPtr pVisualConfigsPriv;
+ int drmSubFD;
+ Bool dri_enabled;
+ ffb_dri_state_t *pFfbSarea;
+#endif
+
+ OptionInfoPtr Options;
+} FFBRec, *FFBPtr;
+
+/* Acceleration */
+extern Bool FFBAccelInit(ScreenPtr, FFBPtr);
+extern void CreatorVtChange (ScreenPtr pScreen, int enter);
+
+/* HW cursor support */
+extern Bool FFBHWCursorInit(ScreenPtr);
+
+/* Exported DAC layer routines. */
+extern void FFBDacLoadCursorPos(FFBPtr, int, int);
+extern void FFBDacLoadCursorColor(FFBPtr, int, int);
+extern void FFBDacCursorEnableDisable(FFBPtr, int);
+extern void FFBDacCursorLoadBitmap(FFBPtr, int, int, unsigned int *);
+extern void FFBDacLoadPalette(ScrnInfoPtr, int, int *, LOCO *, VisualPtr);
+extern Bool FFBDacInit(FFBPtr);
+extern void FFBDacFini(FFBPtr);
+extern void FFBDacEnterVT(FFBPtr);
+extern void FFBDacLeaveVT(FFBPtr);
+extern Bool FFBDacSaveScreen(FFBPtr, int);
+extern void FFBDacDPMSMode(FFBPtr, int, int);
+
+/* Exported WID layer routines. */
+extern void FFBWidPoolInit(FFBPtr);
+extern unsigned int FFBWidAlloc(FFBPtr, int, int, Bool);
+extern void FFBWidFree(FFBPtr, unsigned int);
+extern unsigned int FFBWidUnshare(FFBPtr, unsigned int);
+extern unsigned int FFBWidReshare(FFBPtr, unsigned int);
+extern void FFBWidChangeBuffer(FFBPtr, unsigned int, int);
+extern Bool FFBWidIsShared(FFBPtr pFfb, unsigned int wid);
+
+/* Accelerated double-buffering. */
+extern Bool FFBDbePreInit(ScreenPtr);
+
+#ifdef XF86DRI
+/* DRI support */
+extern Bool FFBDRIScreenInit(ScreenPtr);
+extern Bool FFBDRIFinishScreenInit(ScreenPtr);
+extern void FFBDRICloseScreen(ScreenPtr);
+#endif
+
+/* The fastfill and pagefill buffer sizes change based upon
+ * the resolution.
+ */
+struct fastfill_parms {
+ int fastfill_small_area;
+ int pagefill_small_area;
+
+ int fastfill_height;
+ int fastfill_width;
+ int pagefill_height;
+ int pagefill_width;
+};
+
+extern struct fastfill_parms ffb_fastfill_parms[];
+
+#define FFB_FFPARMS(__fpriv) (ffb_fastfill_parms[(__fpriv)->ffb_res])
+
+extern int CreatorScreenPrivateIndex;
+extern int CreatorGCPrivateIndex;
+extern int CreatorWindowPrivateIndex;
+
+#define GET_FFB_FROM_SCRN(p) ((FFBPtr)((p)->driverPrivate))
+
+#define GET_FFB_FROM_SCREEN(s) \
+((FFBPtr)(s)->devPrivates[CreatorScreenPrivateIndex].ptr)
+
+#define CreatorGetGCPrivate(g) \
+((CreatorPrivGCPtr) (g)->devPrivates [CreatorGCPrivateIndex].ptr)
+
+#define CreatorGetWindowPrivate(w) \
+((CreatorPrivWinPtr) (w)->devPrivates[CreatorWindowPrivateIndex].ptr)
+
+#define CreatorSetWindowPrivate(w,p) \
+((w)->devPrivates[CreatorWindowPrivateIndex].ptr = (pointer) p)
+
+#undef DEBUG_FFB
+
+#ifdef DEBUG_FFB
+
+extern FILE *FDEBUG_FD;
+
+static __inline__ void FFB_DEBUG_init(void)
+{
+ FDEBUG_FD = fopen("/tmp/FFB.DEBUG", "a");
+}
+#define FDEBUG(__x) \
+do { fprintf __x; \
+ fflush(FDEBUG_FD); \
+} while(0)
+#else
+#define FFB_DEBUG_init() do { } while(0)
+#define FDEBUG(__x) do { } while(0)
+#endif
+
+/* Enable this to get very verbose tracing of the driver onto stderr. */
+#undef TRACE_FFB
+#ifdef TRACE_FFB
+#define FFBLOG(__x) ErrorF __x
+#else
+#define FFBLOG(__x) do { } while(0)
+#endif
+
+#endif /* FFB_H */
diff --git a/src/ffb_accel.c b/src/ffb_accel.c
new file mode 100644
index 0000000..b8ce88b
--- /dev/null
+++ b/src/ffb_accel.c
@@ -0,0 +1,961 @@
+/*
+ * Acceleration for the Creator and Creator3D framebuffer.
+ *
+ * Copyright (C) 1998,1999,2000 Jakub Jelinek (jakub@redhat.com)
+ * Copyright (C) 1998 Michal Rehacek (majkl@iname.com)
+ * Copyright (C) 1999,2000 David S. Miller (davem@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * JAKUB JELINEK, MICHAL REHACEK, OR DAVID MILLER BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_accel.c,v 1.5 2001/03/03 22:41:34 tsi Exp $ */
+
+#include "scrnintstr.h"
+#include "pixmapstr.h"
+#include "regionstr.h"
+#include "mistruct.h"
+#include "fontstruct.h"
+#include "dixfontstr.h"
+#define PSZ 8
+#include "cfb.h"
+#undef PSZ
+#include "cfb32.h"
+#include "mibstore.h"
+#include "mifillarc.h"
+#include "miwideline.h"
+#include "miline.h"
+#include "fastblt.h"
+#include "mergerop.h"
+#include "migc.h"
+#include "mi.h"
+
+#include "cfb8_32wid.h"
+
+#include "ffb.h"
+#include "ffb_fifo.h"
+#include "ffb_rcache.h"
+#include "ffb_loops.h"
+#include "ffb_regs.h"
+#include "ffb_stip.h"
+#include "ffb_gc.h"
+
+int CreatorScreenPrivateIndex;
+int CreatorGCPrivateIndex;
+int CreatorWindowPrivateIndex;
+int CreatorGeneration;
+
+/* Indexed by ffb resolution enum. */
+struct fastfill_parms ffb_fastfill_parms[] = {
+ /* fsmall, psmall, ffh, ffw, pfh, pfw */
+ { 0x00c0, 0x1400, 0x04, 0x08, 0x10, 0x50 }, /* Standard: 1280 x 1024 */
+ { 0x0140, 0x2800, 0x04, 0x10, 0x10, 0xa0 }, /* High: 1920 x 1360 */
+ { 0x0080, 0x0a00, 0x02, 0x08, 0x08, 0x50 }, /* Stereo: 960 x 580 */
+/*XXX*/ { 0x00c0, 0x0a00, 0x04, 0x08, 0x08, 0x50 }, /* Portrait: 1280 x 2048 XXX */
+};
+
+static Bool
+CreatorCreateWindow (WindowPtr pWin)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN(pScreen);
+ CreatorPrivWinPtr pFfbPrivWin;
+ unsigned int fbc;
+ int depth = (pWin->drawable.depth == 8) ? 8 : 24;
+ int i, visual, visclass;
+
+ if (depth == 8) {
+ if (!cfbCreateWindow (pWin))
+ return FALSE;
+ } else {
+ if (!cfb32CreateWindow (pWin))
+ return FALSE;
+ }
+
+ pFfbPrivWin = xalloc(sizeof(CreatorPrivWinRec));
+ if (!pFfbPrivWin)
+ return FALSE;
+
+ fbc = FFB_FBC_WB_A | FFB_FBC_WM_COMBINED | FFB_FBC_RB_A;
+ fbc |= FFB_FBC_WE_FORCEON;
+ fbc |= FFB_FBC_SB_BOTH;
+ fbc |= FFB_FBC_ZE_OFF | FFB_FBC_YE_OFF;
+ if (depth == 8)
+ fbc |= (FFB_FBC_RE_MASK | FFB_FBC_GE_OFF | FFB_FBC_BE_OFF);
+ else
+ fbc |= FFB_FBC_RGBE_MASK;
+ fbc |= FFB_FBC_XE_ON;
+ pFfbPrivWin->fbc_base = fbc;
+
+ visual = wVisual(pWin);
+ visclass = 0;
+ for (i = 0; i < pScreen->numVisuals; i++) {
+ if (pScreen->visuals[i].vid == visual) {
+ visclass = pScreen->visuals[i].class;
+ break;
+ }
+ }
+
+ pFfbPrivWin->wid = FFBWidAlloc(pFfb, visclass, wColormap(pWin), TRUE);
+ if (pFfbPrivWin->wid == (unsigned int) -1) {
+ xfree(pFfbPrivWin);
+ return FALSE;
+ }
+ FFBLOG(("CreatorCreateWindow: pWin %p depth %d wid %x fbc_base %x\n",
+ pWin, depth, pFfbPrivWin->wid, pFfbPrivWin->fbc_base));
+
+ pFfbPrivWin->Stipple = NULL;
+ CreatorSetWindowPrivate(pWin, pFfbPrivWin);
+
+ return TRUE;
+}
+
+static Bool
+CreatorDestroyWindow (WindowPtr pWin)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN(pWin->drawable.pScreen);
+ CreatorPrivWinPtr pFfbPrivWin;
+ int depth = (pWin->drawable.depth == 8) ? 8 : 24;
+
+ FFBLOG(("CreatorDestroyWindow: pWin %p depth %d\n", pWin, depth));
+ pFfbPrivWin = CreatorGetWindowPrivate(pWin);
+ if (pFfbPrivWin->Stipple)
+ xfree(pFfbPrivWin->Stipple);
+ FFBWidFree(pFfb, pFfbPrivWin->wid);
+ xfree(pFfbPrivWin);
+
+ if (depth == 8)
+ return cfbDestroyWindow (pWin);
+ else
+ return cfb32DestroyWindow (pWin);
+}
+
+extern CreatorStipplePtr FFB_tmpStipple;
+
+static int
+CreatorChangeWindowAttributes (WindowPtr pWin, Mask mask)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN(pWin->drawable.pScreen);
+ CreatorPrivWinPtr pFfbPrivWin;
+ CreatorStipplePtr stipple;
+ Mask index;
+ WindowPtr pBgWin;
+ register cfbPrivWin *pPrivWin;
+ int width, depth;
+
+ FFBLOG(("CreatorChangeWindowAttributes: WIN(%p) mask(%08x)\n", pWin, mask));
+ pPrivWin = (cfbPrivWin *)(pWin->devPrivates[cfbWindowPrivateIndex].ptr);
+ pFfbPrivWin = CreatorGetWindowPrivate(pWin);
+ depth = pWin->drawable.depth;
+
+ /*
+ * When background state changes from ParentRelative and
+ * we had previously rotated the fast border pixmap to match
+ * the parent relative origin, rerotate to match window
+ */
+ if (mask & (CWBackPixmap | CWBackPixel) &&
+ pWin->backgroundState != ParentRelative &&
+ pPrivWin->fastBorder &&
+ (pPrivWin->oldRotate.x != pWin->drawable.x ||
+ pPrivWin->oldRotate.y != pWin->drawable.y)) {
+ if (depth == 8) {
+ cfbXRotatePixmap(pPrivWin->pRotatedBorder,
+ pWin->drawable.x - pPrivWin->oldRotate.x);
+ cfbYRotatePixmap(pPrivWin->pRotatedBorder,
+ pWin->drawable.y - pPrivWin->oldRotate.y);
+ } else {
+ cfb32XRotatePixmap(pPrivWin->pRotatedBorder,
+ pWin->drawable.x - pPrivWin->oldRotate.x);
+ cfb32YRotatePixmap(pPrivWin->pRotatedBorder,
+ pWin->drawable.y - pPrivWin->oldRotate.y);
+ }
+ pPrivWin->oldRotate.x = pWin->drawable.x;
+ pPrivWin->oldRotate.y = pWin->drawable.y;
+ }
+ while (mask) {
+ index = lowbit(mask);
+ mask &= ~index;
+ switch (index) {
+ case CWBackPixmap:
+ stipple = pFfbPrivWin->Stipple;
+ if (pWin->backgroundState == None ||
+ pWin->backgroundState == ParentRelative) {
+ pPrivWin->fastBackground = FALSE;
+ if (stipple) {
+ xfree (stipple);
+ pFfbPrivWin->Stipple = NULL;
+ }
+ /* Rotate border to match parent origin */
+ if (pWin->backgroundState == ParentRelative &&
+ pPrivWin->pRotatedBorder) {
+ for (pBgWin = pWin->parent;
+ pBgWin->backgroundState == ParentRelative;
+ pBgWin = pBgWin->parent);
+ if (depth == 8) {
+ cfbXRotatePixmap(pPrivWin->pRotatedBorder,
+ pBgWin->drawable.x - pPrivWin->oldRotate.x);
+ cfbYRotatePixmap(pPrivWin->pRotatedBorder,
+ pBgWin->drawable.y - pPrivWin->oldRotate.y);
+ } else {
+ cfb32XRotatePixmap(pPrivWin->pRotatedBorder,
+ pBgWin->drawable.x - pPrivWin->oldRotate.x);
+ cfb32YRotatePixmap(pPrivWin->pRotatedBorder,
+ pBgWin->drawable.y - pPrivWin->oldRotate.y);
+ }
+ pPrivWin->oldRotate.x = pBgWin->drawable.x;
+ pPrivWin->oldRotate.y = pBgWin->drawable.y;
+ }
+ break;
+ }
+ if (!stipple) {
+ if (!FFB_tmpStipple)
+ FFB_tmpStipple = (CreatorStipplePtr)
+ xalloc (sizeof *FFB_tmpStipple);
+ stipple = FFB_tmpStipple;
+ }
+ if (stipple) {
+ int ph = FFB_FFPARMS(pFfb).pagefill_height;
+
+ if (CreatorCheckTile (pWin->background.pixmap, stipple,
+ ((DrawablePtr)pWin)->x & 31,
+ ((DrawablePtr)pWin)->y & 31, ph)) {
+ stipple->alu = GXcopy;
+ pPrivWin->fastBackground = FALSE;
+ if (stipple == FFB_tmpStipple) {
+ pFfbPrivWin->Stipple = stipple;
+ FFB_tmpStipple = 0;
+ }
+ break;
+ }
+ }
+ if ((stipple = pFfbPrivWin->Stipple) != NULL) {
+ xfree (stipple);
+ pFfbPrivWin->Stipple = NULL;
+ }
+ if (((width = (pWin->background.pixmap->drawable.width *
+ pWin->background.pixmap->drawable.bitsPerPixel)) <= 32) &&
+ !(width & (width - 1))) {
+ if (depth == 8) {
+ cfbCopyRotatePixmap(pWin->background.pixmap,
+ &pPrivWin->pRotatedBackground,
+ pWin->drawable.x,
+ pWin->drawable.y);
+ } else {
+ cfb32CopyRotatePixmap(pWin->background.pixmap,
+ &pPrivWin->pRotatedBackground,
+ pWin->drawable.x,
+ pWin->drawable.y);
+ }
+ if (pPrivWin->pRotatedBackground) {
+ pPrivWin->fastBackground = TRUE;
+ pPrivWin->oldRotate.x = pWin->drawable.x;
+ pPrivWin->oldRotate.y = pWin->drawable.y;
+ } else
+ pPrivWin->fastBackground = FALSE;
+ break;
+ }
+ pPrivWin->fastBackground = FALSE;
+ break;
+
+ case CWBackPixel:
+ pPrivWin->fastBackground = FALSE;
+ break;
+
+ case CWBorderPixmap:
+ /* don't bother with accelerator for border tiles (just lazy) */
+ if (((width = (pWin->border.pixmap->drawable.width *
+ pWin->border.pixmap->drawable.bitsPerPixel)) <= 32) &&
+ !(width & (width - 1))) {
+ for (pBgWin = pWin;
+ pBgWin->backgroundState == ParentRelative;
+ pBgWin = pBgWin->parent)
+ ;
+ if (depth == 8) {
+ cfbCopyRotatePixmap(pWin->border.pixmap,
+ &pPrivWin->pRotatedBorder,
+ pBgWin->drawable.x,
+ pBgWin->drawable.y);
+ } else {
+ cfb32CopyRotatePixmap(pWin->border.pixmap,
+ &pPrivWin->pRotatedBorder,
+ pBgWin->drawable.x,
+ pBgWin->drawable.y);
+ }
+ if (pPrivWin->pRotatedBorder) {
+ pPrivWin->fastBorder = TRUE;
+ pPrivWin->oldRotate.x = pBgWin->drawable.x;
+ pPrivWin->oldRotate.y = pBgWin->drawable.y;
+ } else
+ pPrivWin->fastBorder = FALSE;
+ } else
+ pPrivWin->fastBorder = FALSE;
+ break;
+
+ case CWBorderPixel:
+ pPrivWin->fastBorder = FALSE;
+ break;
+ }
+ }
+ return (TRUE);
+}
+
+static void
+CreatorPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pWin->drawable.pScreen);
+ ffb_fbcPtr ffb = pFfb->regs;
+ register cfbPrivWin *pPrivWin;
+ CreatorPrivWinPtr pFfbPrivWin;
+ CreatorStipplePtr stipple;
+ WindowPtr pBgWin;
+ int depth = pWin->drawable.depth;
+
+ if (pFfb->vtSema)
+ return;
+
+ FFBLOG(("CreatorPaintWindow: WIN(%p) what(%d)\n", pWin, what));
+ pPrivWin = cfbGetWindowPrivate(pWin);
+ pFfbPrivWin = CreatorGetWindowPrivate(pWin);
+ switch (what) {
+ case PW_BACKGROUND:
+ stipple = pFfbPrivWin->Stipple;
+ switch (pWin->backgroundState) {
+ case None:
+ return;
+ case ParentRelative:
+ do {
+ pWin = pWin->parent;
+ } while (pWin->backgroundState == ParentRelative);
+ (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, pRegion, what);
+ return;
+ case BackgroundPixmap:
+ if (stipple) {
+ CreatorFillBoxStipple ((DrawablePtr)pWin,
+ (int)REGION_NUM_RECTS(pRegion),
+ REGION_RECTS(pRegion),
+ stipple);
+ return;
+ }
+ FFB_ATTR_SFB_VAR_WIN(pFfb, 0x00ffffff, GXcopy, pWin);
+ FFBWait(pFfb, ffb);
+ if (pPrivWin->fastBackground) {
+ if (depth == 8) {
+ cfbFillBoxTile32 ((DrawablePtr)pWin,
+ (int)REGION_NUM_RECTS(pRegion),
+ REGION_RECTS(pRegion),
+ pPrivWin->pRotatedBackground);
+ } else {
+ cfb32FillBoxTile32 ((DrawablePtr)pWin,
+ (int)REGION_NUM_RECTS(pRegion),
+ REGION_RECTS(pRegion),
+ pPrivWin->pRotatedBackground);
+ }
+ } else {
+ if (depth == 8) {
+ cfbFillBoxTileOdd ((DrawablePtr)pWin,
+ (int)REGION_NUM_RECTS(pRegion),
+ REGION_RECTS(pRegion),
+ pWin->background.pixmap,
+ (int) pWin->drawable.x,
+ (int) pWin->drawable.y);
+ } else {
+ cfb32FillBoxTileOdd ((DrawablePtr)pWin,
+ (int)REGION_NUM_RECTS(pRegion),
+ REGION_RECTS(pRegion),
+ pWin->background.pixmap,
+ (int) pWin->drawable.x,
+ (int) pWin->drawable.y);
+ }
+ }
+ return;
+ case BackgroundPixel:
+ CreatorFillBoxSolid ((DrawablePtr)pWin,
+ (int)REGION_NUM_RECTS(pRegion),
+ REGION_RECTS(pRegion),
+ pWin->background.pixel);
+ return;
+ }
+ break;
+ case PW_BORDER:
+ if (pWin->borderIsPixel) {
+ CreatorFillBoxSolid ((DrawablePtr)pWin,
+ (int)REGION_NUM_RECTS(pRegion),
+ REGION_RECTS(pRegion),
+ pWin->border.pixel);
+ return;
+ }
+ FFB_ATTR_SFB_VAR_WIN(pFfb, 0x00ffffff, GXcopy, pWin);
+ FFBWait(pFfb, ffb);
+ if (pPrivWin->fastBorder) {
+ if (depth == 8) {
+ cfbFillBoxTile32 ((DrawablePtr)pWin,
+ (int)REGION_NUM_RECTS(pRegion),
+ REGION_RECTS(pRegion),
+ pPrivWin->pRotatedBorder);
+ } else {
+ cfb32FillBoxTile32 ((DrawablePtr)pWin,
+ (int)REGION_NUM_RECTS(pRegion),
+ REGION_RECTS(pRegion),
+ pPrivWin->pRotatedBorder);
+ }
+ } else {
+ for (pBgWin = pWin;
+ pBgWin->backgroundState == ParentRelative;
+ pBgWin = pBgWin->parent)
+ ;
+
+ if (depth == 8) {
+ cfbFillBoxTileOdd ((DrawablePtr)pWin,
+ (int)REGION_NUM_RECTS(pRegion),
+ REGION_RECTS(pRegion),
+ pWin->border.pixmap,
+ (int) pBgWin->drawable.x,
+ (int) pBgWin->drawable.y);
+ } else {
+ cfb32FillBoxTileOdd ((DrawablePtr)pWin,
+ (int)REGION_NUM_RECTS(pRegion),
+ REGION_RECTS(pRegion),
+ pWin->border.pixmap,
+ (int) pBgWin->drawable.x,
+ (int) pBgWin->drawable.y);
+ }
+ }
+ return;
+ }
+}
+
+static void
+CreatorCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pScreen);
+ DDXPointPtr pptSrc;
+ DDXPointPtr ppt;
+ RegionRec rgnDst;
+ BoxPtr pbox;
+ int dx, dy;
+ int i, nbox;
+ WindowPtr pwinRoot;
+
+ if (pFfb->vtSema)
+ return;
+
+ FFBLOG(("CreatorCopyWindow: WIN(%p)\n", pWin));
+
+ REGION_INIT(pScreen, &rgnDst, NullBox, 0);
+
+ dx = ptOldOrg.x - pWin->drawable.x;
+ dy = ptOldOrg.y - pWin->drawable.y;
+ REGION_TRANSLATE(pScreen, prgnSrc, -dx, -dy);
+ REGION_INTERSECT(pScreen, &rgnDst, &pWin->borderClip, prgnSrc);
+
+ pbox = REGION_RECTS(&rgnDst);
+ nbox = REGION_NUM_RECTS(&rgnDst);
+ if(!(pptSrc = (DDXPointPtr )ALLOCATE_LOCAL(nbox * sizeof(DDXPointRec))))
+ return;
+
+ ppt = pptSrc;
+ for (i = nbox; --i >= 0; ppt++, pbox++) {
+ ppt->x = pbox->x1 + dx;
+ ppt->y = pbox->y1 + dy;
+ }
+
+ /* XXX Optimize this later to only gcopy/vcopy the 8bpp+WID plane
+ * XXX when possible. -DaveM
+ */
+
+ pwinRoot = WindowTable[pScreen->myNum];
+
+ if (!pFfb->disable_vscroll && (!dx && dy)) {
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN(pScreen);
+
+ FFB_ATTR_VSCROLL_WINCOPY(pFfb);
+ CreatorDoVertBitblt ((DrawablePtr)pwinRoot, (DrawablePtr)pwinRoot,
+ GXcopy, &rgnDst, pptSrc, ~0L);
+ } else {
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN(pScreen);
+ ffb_fbcPtr ffb = pFfb->regs;
+
+ FFB_ATTR_SFB_VAR_WINCOPY(pFfb);
+ FFBWait(pFfb, ffb);
+ CreatorDoBitblt ((DrawablePtr)pwinRoot, (DrawablePtr)pwinRoot,
+ GXcopy, &rgnDst, pptSrc, ~0L);
+ }
+ DEALLOCATE_LOCAL(pptSrc);
+ REGION_UNINIT(pScreen, &rgnDst);
+}
+
+static void
+CreatorSaveAreas(PixmapPtr pPixmap, RegionPtr prgnSave, int xorg, int yorg, WindowPtr pWin)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN(pScreen);
+ cfb8_32WidScreenPtr pScreenPriv =
+ CFB8_32WID_GET_SCREEN_PRIVATE(pScreen);
+ ffb_fbcPtr ffb = pFfb->regs;
+ register DDXPointPtr pPt;
+ DDXPointPtr pPtsInit;
+ register BoxPtr pBox;
+ register int i;
+ PixmapPtr pScrPix;
+
+ if (pFfb->vtSema)
+ return;
+
+ FFBLOG(("CreatorSaveAreas: WIN(%p)\n", pWin));
+ i = REGION_NUM_RECTS(prgnSave);
+ pPtsInit = (DDXPointPtr)ALLOCATE_LOCAL(i * sizeof(DDXPointRec));
+ if (!pPtsInit)
+ return;
+
+ pBox = REGION_RECTS(prgnSave);
+ pPt = pPtsInit;
+ while (--i >= 0) {
+ pPt->x = pBox->x1 + xorg;
+ pPt->y = pBox->y1 + yorg;
+ pPt++;
+ pBox++;
+ }
+
+ if (pWin->drawable.bitsPerPixel == 8)
+ pScrPix = (PixmapPtr) pScreenPriv->pix8;
+ else
+ pScrPix = (PixmapPtr) pScreenPriv->pix32;
+
+ /* SRC is the framebuffer, DST is a pixmap. The SFB_VAR attributes may
+ * seem silly, but they are needed even in this case to handle
+ * double-buffered windows properly.
+ */
+ FFB_ATTR_SFB_VAR_WIN(pFfb, 0x00ffffff, GXcopy, pWin);
+ FFBWait(pFfb, ffb);
+ CreatorDoBitblt((DrawablePtr) pScrPix, (DrawablePtr)pPixmap,
+ GXcopy, prgnSave, pPtsInit, ~0L);
+
+ DEALLOCATE_LOCAL (pPtsInit);
+}
+
+static void
+CreatorRestoreAreas(PixmapPtr pPixmap, RegionPtr prgnRestore, int xorg, int yorg, WindowPtr pWin)
+{
+ FFBPtr pFfb;
+ ffb_fbcPtr ffb;
+ register DDXPointPtr pPt;
+ DDXPointPtr pPtsInit;
+ register BoxPtr pBox;
+ register int i;
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ cfb8_32WidScreenPtr pScreenPriv =
+ CFB8_32WID_GET_SCREEN_PRIVATE(pScreen);
+ PixmapPtr pScrPix;
+
+ pFfb = GET_FFB_FROM_SCREEN(pScreen);
+ if (pFfb->vtSema)
+ return;
+
+ FFBLOG(("CreatorRestoreAreas: WIN(%p)\n", pWin));
+ i = REGION_NUM_RECTS(prgnRestore);
+ pPtsInit = (DDXPointPtr)ALLOCATE_LOCAL(i*sizeof(DDXPointRec));
+ if (!pPtsInit)
+ return;
+
+ pBox = REGION_RECTS(prgnRestore);
+ pPt = pPtsInit;
+ while (--i >= 0) {
+ pPt->x = pBox->x1 - xorg;
+ pPt->y = pBox->y1 - yorg;
+ pPt++;
+ pBox++;
+ }
+
+ if (pWin->drawable.bitsPerPixel == 8)
+ pScrPix = (PixmapPtr) pScreenPriv->pix8;
+ else
+ pScrPix = (PixmapPtr) pScreenPriv->pix32;
+
+ pFfb = GET_FFB_FROM_SCREEN(pScreen);
+ ffb = pFfb->regs;
+
+ /* SRC is a pixmap, DST is the framebuffer */
+ FFB_ATTR_SFB_VAR_WIN(pFfb, 0x00ffffff, GXcopy, pWin);
+ FFBWait(pFfb, ffb);
+ CreatorDoBitblt((DrawablePtr)pPixmap, (DrawablePtr) pScrPix,
+ GXcopy, prgnRestore, pPtsInit, ~0L);
+
+ DEALLOCATE_LOCAL (pPtsInit);
+}
+
+static void
+CreatorGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h, unsigned int format, unsigned long planeMask, char* pdstLine)
+{
+ BoxRec box;
+ DDXPointRec ptSrc;
+ RegionRec rgnDst;
+ ScreenPtr pScreen;
+ PixmapPtr pPixmap;
+
+ FFBLOG(("CreatorGetImage: s[%08x:%08x] wh[%08x:%08x]\n", sx, sy, w, h));
+ if ((w == 0) || (h == 0))
+ return;
+ if (pDrawable->bitsPerPixel == 1) {
+ mfbGetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine);
+ return;
+ }
+ pScreen = pDrawable->pScreen;
+ /*
+ * XFree86 DDX empties the root borderClip when the VT is
+ * switched away; this checks for that case
+ */
+ if (!cfbDrawableEnabled (pDrawable))
+ return;
+ if(format == ZPixmap) {
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pScreen);
+ ffb_fbcPtr ffb = pFfb->regs;
+
+ /* We have to have the full planemask. */
+ if (pDrawable->type == DRAWABLE_WINDOW) {
+ WindowPtr pWin = (WindowPtr) pDrawable;
+
+ FFB_ATTR_SFB_VAR_WIN(pFfb, 0x00ffffff, GXcopy, pWin);
+ FFBWait(pFfb, ffb);
+ }
+
+ if (pDrawable->bitsPerPixel == 8) {
+ if((planeMask & 0x000000ff) != 0x000000ff) {
+ cfbGetImage(pDrawable, sx, sy, w, h,
+ format, planeMask, pdstLine);
+ return;
+ }
+ } else {
+ if((planeMask & 0x00ffffff) != 0x00ffffff) {
+ cfb32GetImage(pDrawable, sx, sy, w, h,
+ format, planeMask, pdstLine);
+ return;
+ }
+ }
+
+ /* SRC is the framebuffer, DST is a pixmap */
+ if (pDrawable->type == DRAWABLE_WINDOW && w == 1 && h == 1) {
+ /* Benchmarks do this make sure the acceleration hardware
+ * has completed all of it's operations, therefore I feel
+ * it is not cheating to special case this because if
+ * anything it gives the benchmarks more accurate results.
+ */
+ if (pDrawable->bitsPerPixel == 32) {
+ unsigned char *sfb = (unsigned char *)pFfb->sfb32;
+ unsigned int *dstPixel = (unsigned int *)pdstLine;
+ unsigned int tmp;
+
+ tmp = *((unsigned int *)(sfb +
+ ((sy + pDrawable->y) << 13) +
+ ((sx + pDrawable->x) << 2)));
+ *dstPixel = (tmp & 0x00ffffff);
+ } else {
+ unsigned char *sfb = (unsigned char *)pFfb->sfb8r;
+ unsigned char *dstPixel = (unsigned char *)pdstLine;
+
+ *dstPixel = *((unsigned char *)(sfb +
+ ((sy + pDrawable->y) << 11) +
+ ((sx + pDrawable->x) << 0)));
+ }
+ return;
+ }
+ pPixmap = GetScratchPixmapHeader(pScreen, w, h,
+ pDrawable->depth, pDrawable->bitsPerPixel,
+ PixmapBytePad(w,pDrawable->depth), (pointer)pdstLine);
+ if (!pPixmap)
+ return;
+ ptSrc.x = sx + pDrawable->x;
+ ptSrc.y = sy + pDrawable->y;
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = w;
+ box.y2 = h;
+ REGION_INIT(pScreen, &rgnDst, &box, 1);
+ CreatorDoBitblt(pDrawable, (DrawablePtr)pPixmap, GXcopy, &rgnDst,
+ &ptSrc, planeMask);
+ REGION_UNINIT(pScreen, &rgnDst);
+ FreeScratchPixmapHeader(pPixmap);
+ } else
+ miGetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine);
+}
+
+extern void
+CreatorGetSpans(DrawablePtr pDrawable, int wMax, DDXPointPtr ppt,
+ int *pwidth, int nspans, char *pchardstStart);
+
+void
+CreatorVtChange (ScreenPtr pScreen, int enter)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pScreen);
+ ffb_fbcPtr ffb = pFfb->regs;
+
+ pFfb->rp_active = 1;
+ FFBWait(pFfb, ffb);
+ pFfb->fifo_cache = -1;
+ pFfb->fbc_cache = (FFB_FBC_WB_A | FFB_FBC_WM_COMBINED |
+ FFB_FBC_RB_A | FFB_FBC_SB_BOTH| FFB_FBC_XE_OFF |
+ FFB_FBC_ZE_OFF | FFB_FBC_YE_OFF | FFB_FBC_RGBE_MASK);
+ pFfb->ppc_cache = (FFB_PPC_FW_DISABLE |
+ FFB_PPC_VCE_DISABLE | FFB_PPC_APE_DISABLE | FFB_PPC_CS_CONST |
+ FFB_PPC_XS_CONST | FFB_PPC_YS_CONST | FFB_PPC_ZS_CONST|
+ FFB_PPC_DCE_DISABLE | FFB_PPC_ABE_DISABLE | FFB_PPC_TBE_OPAQUE);
+
+ pFfb->pmask_cache = ~0;
+ pFfb->rop_cache = FFB_ROP_EDIT_BIT;
+ pFfb->drawop_cache = FFB_DRAWOP_RECTANGLE;
+ pFfb->fg_cache = pFfb->bg_cache = 0;
+ pFfb->fontw_cache = 32;
+ pFfb->fontinc_cache = (1 << 16) | 0;
+ pFfb->laststipple = NULL;
+ FFBFifo(pFfb, 9);
+ ffb->fbc = pFfb->fbc_cache;
+ ffb->ppc = pFfb->ppc_cache;
+ ffb->pmask = pFfb->pmask_cache;
+ ffb->rop = pFfb->rop_cache;
+ ffb->drawop = pFfb->drawop_cache;
+ ffb->fg = pFfb->fg_cache;
+ ffb->bg = pFfb->bg_cache;
+ ffb->fontw = pFfb->fontw_cache;
+ ffb->fontinc = pFfb->fontinc_cache;
+ pFfb->rp_active = 1;
+ FFBWait(pFfb, ffb);
+
+ /* Fixup the FBC/PPC caches to deal with actually using
+ * a WID for every ROP.
+ */
+ pFfb->fbc_cache = (FFB_FBC_WB_A | FFB_FBC_WM_COMBINED |
+ FFB_FBC_RB_A | FFB_FBC_SB_BOTH | FFB_FBC_XE_ON |
+ FFB_FBC_ZE_OFF | FFB_FBC_YE_OFF | FFB_FBC_RGBE_ON);
+ pFfb->ppc_cache &= ~FFB_PPC_XS_MASK;
+ pFfb->ppc_cache |= FFB_PPC_XS_WID;
+ pFfb->wid_cache = 0xff;
+ FFBFifo(pFfb, 8);
+ ffb->fbc = pFfb->fbc_cache;
+ ffb->ppc = FFB_PPC_XS_WID;
+ ffb->wid = pFfb->wid_cache;
+ ffb->xpmask = 0xff;
+ ffb->xclip = FFB_XCLIP_TEST_ALWAYS;
+ ffb->cmp = 0x80808080;
+ ffb->matchab = 0x80808080;
+ ffb->magnab = 0x80808080;
+ FFBWait(pFfb, ffb);
+}
+
+/* Multiplies and divides suck... */
+static void CreatorAlignTabInit(FFBPtr pFfb)
+{
+ struct fastfill_parms *ffp = &FFB_FFPARMS(pFfb);
+ short *tab = pFfb->Pf_AlignTab;
+ int i;
+
+ for(i = 0; i < 0x800; i++) {
+ int alignval;
+
+ alignval = (i / ffp->pagefill_width) * ffp->pagefill_width;
+ *tab++ = alignval;
+ }
+}
+
+static Bool
+CreatorPositionWindow(WindowPtr pWin, int x, int y)
+{
+ if (pWin->drawable.bitsPerPixel == 8)
+ return cfbPositionWindow(pWin, x, y);
+ else
+ return cfb32PositionWindow(pWin, x, y);
+}
+
+extern Bool CreatorCreateGC (GCPtr pGC);
+
+#ifdef DEBUG_FFB
+FILE *FDEBUG_FD = NULL;
+#endif
+
+BSFuncRec CreatorBSFuncRec = {
+ CreatorSaveAreas,
+ CreatorRestoreAreas,
+ (BackingStoreSetClipmaskRgnProcPtr) 0,
+ (BackingStoreGetImagePixmapProcPtr) 0,
+ (BackingStoreGetSpansPixmapProcPtr) 0,
+};
+
+Bool FFBAccelInit (ScreenPtr pScreen, FFBPtr pFfb)
+{
+ ffb_fbcPtr ffb;
+
+ if (serverGeneration != CreatorGeneration) {
+ CreatorScreenPrivateIndex = AllocateScreenPrivateIndex ();
+ if (CreatorScreenPrivateIndex == -1) return FALSE;
+ CreatorGCPrivateIndex = AllocateGCPrivateIndex ();
+ CreatorWindowPrivateIndex = AllocateWindowPrivateIndex ();
+ CreatorGeneration = serverGeneration;
+ }
+
+ if (!AllocateGCPrivate(pScreen, CreatorGCPrivateIndex, sizeof(CreatorPrivGCRec)))
+ return FALSE;
+ if (!AllocateWindowPrivate(pScreen, CreatorWindowPrivateIndex, 0))
+ return FALSE;
+ pScreen->devPrivates[CreatorScreenPrivateIndex].ptr = pFfb;
+
+ pFfb->fifo_cache = 0;
+ ffb = pFfb->regs;
+
+ /* Replace various screen functions. */
+ pScreen->CreateGC = CreatorCreateGC;
+ pScreen->CreateWindow = CreatorCreateWindow;
+ pScreen->DestroyWindow = CreatorDestroyWindow;
+ pScreen->PositionWindow = CreatorPositionWindow;
+ pScreen->ChangeWindowAttributes = CreatorChangeWindowAttributes;
+ pScreen->PaintWindowBackground = CreatorPaintWindow;
+ pScreen->PaintWindowBorder = CreatorPaintWindow;
+ pScreen->GetSpans = CreatorGetSpans;
+ pScreen->CopyWindow = CreatorCopyWindow;
+ pScreen->GetImage = CreatorGetImage;
+ pScreen->BackingStoreFuncs = CreatorBSFuncRec;
+
+ /* cfb8_32wid took over this to init the WID plane,
+ * and with how our code works that is not necessary.
+ */
+ pScreen->WindowExposures = miWindowExposures;
+
+ /* Set FFB line-bias for clipping. */
+ miSetZeroLineBias(pScreen, OCTANT3 | OCTANT4 | OCTANT6 | OCTANT1);
+
+ FFB_DEBUG_init();
+ FDEBUG((FDEBUG_FD,
+ "FFB: cfg0(%08x) cfg1(%08x) cfg2(%08x) cfg3(%08x) ppcfg(%08x)\n",
+ ffb->fbcfg0, ffb->fbcfg1, ffb->fbcfg2, ffb->fbcfg3, ffb->ppcfg));
+
+ /* Determine the current screen resolution type. This is
+ * needed to figure out the fastfill/pagefill parameters.
+ */
+ switch(ffb->fbcfg0 & FFB_FBCFG0_RES_MASK) {
+ default:
+ case FFB_FBCFG0_RES_STD:
+ pFfb->ffb_res = ffb_res_standard;
+ break;
+ case FFB_FBCFG0_RES_HIGH:
+ pFfb->ffb_res = ffb_res_high;
+ break;
+ case FFB_FBCFG0_RES_STEREO:
+ pFfb->ffb_res = ffb_res_stereo;
+ break;
+ case FFB_FBCFG0_RES_PRTRAIT:
+ pFfb->ffb_res = ffb_res_portrait;
+ break;
+ };
+ CreatorAlignTabInit(pFfb);
+
+ /* Next, determine the hwbug workarounds and feature enables
+ * we should be using on this board.
+ */
+ pFfb->disable_pagefill = 0;
+ pFfb->disable_vscroll = 0;
+ pFfb->has_brline_bug = 0;
+ pFfb->use_blkread_prefetch = 0;
+ if (pFfb->ffb_type == ffb1_prototype ||
+ pFfb->ffb_type == ffb1_standard ||
+ pFfb->ffb_type == ffb1_speedsort) {
+ pFfb->has_brline_bug = 1;
+ if (pFfb->ffb_res == ffb_res_high)
+ pFfb->disable_vscroll = 1;
+ if (pFfb->ffb_res == ffb_res_high ||
+ pFfb->ffb_res == ffb_res_stereo)
+ pFfb->disable_pagefill = 1;
+
+ } else {
+ /* FFB2 has blkread prefetch. AFB supposedly does too
+ * but the chip locks up on me when I try to use it. -DaveM
+ */
+#define AFB_PREFETCH_IS_BUGGY 1
+ if (!AFB_PREFETCH_IS_BUGGY ||
+ (pFfb->ffb_type != afb_m3 &&
+ pFfb->ffb_type != afb_m6)) {
+ pFfb->use_blkread_prefetch = 1;
+ }
+ /* XXX I still cannot get page/block fast fills
+ * XXX to work reliably on any of my AFB boards. -DaveM
+ */
+#define AFB_FASTFILL_IS_BUGGY 1
+ if (AFB_FASTFILL_IS_BUGGY &&
+ (pFfb->ffb_type == afb_m3 ||
+ pFfb->ffb_type == afb_m6))
+ pFfb->disable_pagefill = 1;
+ }
+ pFfb->disable_fastfill_ap = 0;
+ if (pFfb->ffb_res == ffb_res_stereo ||
+ pFfb->ffb_res == ffb_res_high)
+ pFfb->disable_fastfill_ap = 1;
+
+ pFfb->ppc_cache = (FFB_PPC_FW_DISABLE |
+ FFB_PPC_VCE_DISABLE | FFB_PPC_APE_DISABLE | FFB_PPC_CS_CONST |
+ FFB_PPC_XS_CONST | FFB_PPC_YS_CONST | FFB_PPC_ZS_CONST |
+ FFB_PPC_DCE_DISABLE | FFB_PPC_ABE_DISABLE | FFB_PPC_TBE_OPAQUE);
+
+ pFfb->pmask_cache = ~0;
+ pFfb->rop_cache = (FFB_ROP_ZERO | (FFB_ROP_NEW << 8));
+ pFfb->drawop_cache = FFB_DRAWOP_RECTANGLE;
+ pFfb->fg_cache = pFfb->bg_cache = 0;
+ pFfb->fontw_cache = 32;
+ pFfb->fontinc_cache = (1 << 16) | 0;
+ pFfb->fbc_cache = (FFB_FBC_WB_A | FFB_FBC_WM_COMBINED |
+ FFB_FBC_RB_A | FFB_FBC_SB_BOTH | FFB_FBC_XE_OFF |
+ FFB_FBC_ZE_OFF | FFB_FBC_YE_OFF | FFB_FBC_RGBE_MASK);
+ pFfb->laststipple = NULL;
+
+ /* We will now clear the screen: we'll draw a rectangle covering all the
+ * viewscreen, using a 'blackness' ROP.
+ */
+ FFBFifo(pFfb, 13);
+ ffb->fbc = pFfb->fbc_cache;
+ ffb->ppc = pFfb->ppc_cache;
+ ffb->pmask = pFfb->pmask_cache;
+ ffb->rop = pFfb->rop_cache;
+ ffb->drawop = pFfb->drawop_cache;
+ ffb->fg = pFfb->fg_cache;
+ ffb->bg = pFfb->bg_cache;
+ ffb->fontw = pFfb->fontw_cache;
+ ffb->fontinc = pFfb->fontinc_cache;
+ FFB_WRITE64(&ffb->by, 0, 0);
+ FFB_WRITE64_2(&ffb->bh, pFfb->psdp->height, pFfb->psdp->width);
+ pFfb->rp_active = 1;
+ FFBWait(pFfb, ffb);
+
+ /* Fixup the FBC/PPC caches to deal with actually using
+ * a WID for every ROP.
+ */
+ pFfb->fbc_cache = (FFB_FBC_WB_A | FFB_FBC_WM_COMBINED |
+ FFB_FBC_RB_A | FFB_FBC_SB_BOTH | FFB_FBC_XE_ON |
+ FFB_FBC_ZE_OFF | FFB_FBC_YE_OFF | FFB_FBC_RGBE_ON);
+ pFfb->ppc_cache &= ~FFB_PPC_XS_MASK;
+ pFfb->ppc_cache |= FFB_PPC_XS_WID;
+ pFfb->wid_cache = 0xff;
+ FFBFifo(pFfb, 8);
+ ffb->fbc = pFfb->fbc_cache;
+ ffb->ppc = FFB_PPC_XS_WID;
+ ffb->wid = pFfb->wid_cache;
+ ffb->xpmask = 0xff;
+ ffb->xclip = FFB_XCLIP_TEST_ALWAYS;
+ ffb->cmp = 0x80808080;
+ ffb->matchab = 0x80808080;
+ ffb->magnab = 0x80808080;
+ FFBWait(pFfb, ffb);
+
+ /* Success */
+ return TRUE;
+}
diff --git a/src/ffb_asm.s b/src/ffb_asm.s
new file mode 100644
index 0000000..37ca92e
--- /dev/null
+++ b/src/ffb_asm.s
@@ -0,0 +1,349 @@
+/*
+ * ffb_asm.s: Fast Creator raster op inner loops.
+ *
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * JAKUB JELINEK OR DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_asm.s,v 1.1 2000/05/18 23:21:35 dawes Exp $ */
+
+/* Hardware register offsets */
+#define FFB_BY 0x0060
+#define FFB_DY 0x0068
+#define FFB_BH 0x0070
+#define FFB_PPC 0x0200
+#define FFB_DRAWOP 0x0300
+#define FFB_UCSR 0x0900
+
+#define FFB_DRAWOP_VSCROLL 0x0b
+
+#define FIFO_CACHE 0x00
+
+#define BOX_X1 0x00
+#define BOX_Y1 0x02
+#define BOX_X2 0x04
+#define BOX_Y2 0x06
+
+#define POINT_X 0x00
+#define POINT_Y 0x02
+
+#define RECT_X 0x00
+#define RECT_Y 0x02
+#define RECT_W 0x04
+#define RECT_H 0x06
+
+#define SEG_X1 0x00
+#define SEG_Y1 0x02
+#define SEG_X2 0x04
+#define SEG_Y2 0x06
+
+ .text
+
+ .align 32
+ .globl FFB_STIPPLE_LOAD
+ /* %o0 = &ffbregs->pattern[0]
+ * %o1 = &stipple->bits[0]
+ */
+FFB_STIPPLE_LOAD:
+ cmp %g0, 0
+1: ldx [%o1 + 0x00], %g1
+ ldx [%o1 + 0x08], %g2
+ ldx [%o1 + 0x10], %g3
+
+ ldx [%o1 + 0x18], %g4
+ add %o0, 0x40, %o0
+ ldx [%o1 + 0x20], %g5
+ ldx [%o1 + 0x28], %o2
+
+ ldx [%o1 + 0x30], %o3
+ ldx [%o1 + 0x38], %o4
+ stx %g1, [%o0 - 0x40]
+ stx %g2, [%o0 - 0x38]
+
+ stx %g3, [%o0 - 0x30]
+ stx %g4, [%o0 - 0x28]
+ add %o1, 0x40, %o1
+ stx %g5, [%o0 - 0x20]
+
+ stx %o2, [%o0 - 0x18]
+ stx %o3, [%o0 - 0x10]
+ stx %o4, [%o0 - 0x08]
+ be,pt %icc, 1b
+
+ cmp %g0, 1
+ retl
+ nop
+
+#define FIFO_WAIT(ffbregs, goal, this_label, done_label) \
+this_label: \
+ lduw [ffbregs + FFB_UCSR], %g1; \
+ and %g1, 0xfff, %g1; \
+ subcc %g1, (4 + goal), %g1; \
+ bge,pt %icc, done_label; \
+ nop; \
+ ba,a,pt %xcc, this_label
+
+ .align 32
+ .globl FFB_PPT_BOX_LOOP
+ /* This is only used (currently) by vscroll, so we put
+ * the creator hwbug workaround in here (writing
+ * the drawop each iteration).
+ *
+ * %o0 = ffbpriv, %o1 = ffbregs,
+ * %o2 = pbox, %o3 = pbox_last, %o4 = ppt
+ */
+FFB_PPT_BOX_LOOP:
+ lduh [%o0 + FIFO_CACHE], %g1 /* Load Group */
+ sethi %hi(FFB_DRAWOP), %g2 /* IEU0 */
+ cmp %o2, %o3 /* IEU1 */
+ bgu,pn %icc, 2f /* CTI */
+
+ or %g2,%lo(FFB_DRAWOP),%g2 /* IEU0 Group */
+1: lduh [%o4 + POINT_X], %g3 /* Load Group */
+ lduh [%o4 + POINT_Y], %g4 /* Load Group */
+ lduh [%o2 + BOX_Y2], %g5 /* Load Group */
+
+ lduh [%o2 + BOX_Y1], %o5 /* Load Group */
+ sllx %g4, 32, %g4 /* IEU0 */
+ or %g3, %g4, %g3 /* IEU0 Group */
+ sub %g5, %o5, %g5 /* IEU1 */
+
+ sllx %o5, 32, %g4 /* IEU0 Group */
+ sllx %g5, 32, %g5 /* IEU0 Group */
+ lduh [%o2 + BOX_X2], %o5 /* Load */
+ add %o4, 0x4, %o4 /* IEU1 */
+
+ lduh [%o2 + BOX_X1], %g7 /* Load Group */
+ add %o2, 0x8, %o2 /* IEU0 */
+ sub %o5, %g7, %o5 /* IEU0 Group */
+ or %g4, %g7, %g4 /* IEU1 */
+
+ or %g5, %o5, %g5 /* IEU0 Group */
+ subcc %g1, 7, %g1 /* IEU1 */
+ bl,pn %icc, FFB_PPT_BOX_WAIT /* CTI */
+9: cmp %o2, %o3 /* IEU1 Group */
+
+ /* This works around BUG ID 1189858 -DaveM */
+ mov FFB_DRAWOP_VSCROLL, %o5 /* IEU0 */
+ stw %o5, [%o1 + %g2] /* STORE */
+ stx %g3, [%o1 + FFB_BY] /* STORE Group */
+ stx %g4, [%o1 + FFB_DY] /* STORE Group */
+
+ bleu,pt %icc, 1b /* CTI */
+ stx %g5, [%o1 + FFB_BH] /* STORE Group */
+2: retl /* CTI Group */
+ sth %g1, [%o0 + FIFO_CACHE] /* STORE */
+
+ FIFO_WAIT(%o1, 7, FFB_PPT_BOX_WAIT, 9b)
+
+ .align 32
+ .globl FFB_BOX_LOOP
+ /* %o0 = ffbpriv, %o1 = ffbregs,
+ * %o2 = pbox, %o3 = pbox_last
+ */
+FFB_BOX_LOOP:
+ lduh [%o0 + FIFO_CACHE], %g1 /* Load Group */
+ cmp %o2, %o3 /* IEU0 */
+ bgu,pn %icc, 2f /* CTI */
+ nop /* IEU0 Group */
+
+1: lduw [%o2 + BOX_X1], %g4 /* Load Group */
+ lduw [%o2 + BOX_X2], %g3 /* Load Group */
+ sllx %g4, 32, %o5 /* IEU0 */
+ srl %g4, 16, %g7 /* IEU0 Group */
+
+ add %o2, 8, %o2 /* IEU1 */
+ sllx %g3, 32, %g5 /* IEU0 Group */
+ subcc %g1, 4, %g1 /* IEU1 */
+ srl %g3, 16, %o4 /* IEU0 Group */
+
+ or %o5, %g7, %o5 /* IEU1 */
+ or %g5, %o4, %g5 /* IEU0 Group */
+ bl,pn %icc, FFB_BOX_WAIT /* CTI */
+ sub %g5, %o5, %g5 /* IEU0 Group */
+
+9: cmp %o2, %o3 /* IEU1 */
+ stx %o5, [%o1 + FFB_BY] /* Store */
+ bleu,pt %icc, 1b /* CTI Group */
+ stx %g5, [%o1 + FFB_BH] /* Store */
+2: retl /* CTI Group */
+ sth %g1, [%o0 + FIFO_CACHE] /* Store */
+
+ FIFO_WAIT(%o1, 4, FFB_BOX_WAIT, 9b)
+
+ .align 32
+ .globl FFB_RECT_LOOP
+ /* %o0 = ffbpriv, %o1 = ffbregs,
+ * %o2 = prect, %o3 = prect_last,
+ * %o4 = xOrg, %o5 = yOrg
+ */
+FFB_RECT_LOOP:
+ lduh [%o0 + FIFO_CACHE], %g1 /* Load Group */
+ sllx %o5, 32, %o5 /* IEU0 */
+ cmp %o2, %o3 /* IEU1 */
+ bgu,pn %icc, 2f /* CTI */
+
+ or %o4, %o5, %o4 /* IEU0 Group */
+1: lduh [%o2 + RECT_X], %g4 /* Load Group */
+ lduh [%o2 + RECT_Y], %o5 /* Load Group */
+ lduh [%o2 + RECT_W], %g3 /* Load Group */
+
+ lduh [%o2 + RECT_H], %g2 /* Load Group */
+ sllx %o5, 32, %g7 /* IEU0 */
+ add %o2, 8, %o2 /* IEU1 */
+ orcc %g7, %g4, %g7 /* IEU1 Group */
+
+ sllx %g2, 32, %g5 /* IEU0 */
+ or %g5, %g3, %g5 /* IEU0 Group */
+ add %g7, %o4, %g7 /* IEU1 */
+ subcc %g1, 4, %g1 /* IEU1 Group */
+
+ bl,pn %icc, FFB_RECT_WAIT /* CTI */
+9: cmp %o2, %o3 /* IEU1 Group */
+ stx %g7, [%o1 + FFB_BY] /* Store */
+ bleu,pt %icc, 1b /* CTI */
+
+ stx %g5, [%o1 + FFB_BH] /* Store Group */
+2: retl /* CTI Group */
+ sth %g1, [%o0 + FIFO_CACHE] /* Store */
+
+ FIFO_WAIT(%o1, 4, FFB_RECT_WAIT, 9b)
+
+ .align 32
+ .globl FFB_PPT_WIDTH_LOOP
+ /* %o0 = ffbpriv, %o1 = ffbregs,
+ * %o2 = ppt, %o3 = ppt_last,
+ * %o4 = pwidth
+ */
+FFB_PPT_WIDTH_LOOP:
+ lduh [%o0 + FIFO_CACHE], %g1 /* Load Group */
+ cmp %o2, %o3 /* IEU1 */
+ bgu,pn %icc, 2f /* CTI */
+ nop
+
+8: lduw [%o2 + POINT_X], %g4 /* Load Group */
+ lduw [%o4], %g2 /* Load Group */
+ sllx %g4, 32, %g7
+1: srl %g4, 16, %g5 /* IEU0 Group */
+
+ add %o2, 4, %o2 /* IEU1 */
+ brz,pn %g2, 8b /* CTI+IEU1 Group */
+ add %o4, 4, %o4 /* IEU0 */
+ or %g5, %g7, %g7 /* IEU0 Group */
+
+ subcc %g1, 5, %g1 /* IEU1 */
+ bl,pn %icc, FFB_PPT_WIDTH_WAIT/* CTI */
+ add %g7, %g2, %o5 /* IEU0 Group */
+9: stw %g0, [%o1 + FFB_PPC] /* Store Group */
+
+ cmp %o2, %o3 /* IEU1 */
+ stx %g7, [%o1 + FFB_BY] /* Store Group */
+ bleu,pt %icc, 8b /* CTI */
+ stx %o5, [%o1 + FFB_BH] /* Store Group */
+
+2: retl /* CTI Group */
+ sth %g1, [%o0 + FIFO_CACHE] /* Store */
+
+ FIFO_WAIT(%o1, 5, FFB_PPT_WIDTH_WAIT, 9b)
+
+ .align 32
+ .globl FFB_LINE_LOOP1
+ /* %o0 = ffbpriv, %o1 = ffbregs,
+ * %o2 = ppt, %o3 = ppt_last,
+ * %o4 = xOrg, %o5 = yOrg
+ *
+ * We return ppt_last + 1.
+ */
+FFB_LINE_LOOP1:
+ lduh [%o0 + FIFO_CACHE], %g1
+ sllx %o5, 32, %o5
+ and %o4, 0x7ff, %o4
+ cmp %o2, %o3
+
+ bgu,pn %icc, 2f
+ or %o4, %o5, %o4
+1: lduw [%o2 + POINT_X], %g4
+ sllx %g4, 32, %g7
+
+ srl %g4, 16, %g3
+ add %o2, 4, %o2
+ or %g7, %g3, %g7
+ subcc %g1, 3, %g1
+
+ bl,pn %icc, FFB_LINE1_WAIT
+ add %g7, %o4, %g7
+9: cmp %o2, %o3
+ stw %g0, [%o1 + FFB_PPC]
+
+ bleu,pt %icc, 1b
+ stx %g7, [%o1 + FFB_BH]
+2: nop
+ sth %g1, [%o0 + FIFO_CACHE]
+
+ retl
+ mov %o2, %o0
+
+ FIFO_WAIT(%o1, 3, FFB_LINE1_WAIT, 9b)
+
+ .align 32
+ .globl FFB_LINE_LOOP2
+ /* %o0 = ffbpriv, %o1 = ffbregs,
+ * %o2 = ppt, %o3 = ppt_last,
+ * %o4 = &xOrg, %o5 = &yOrg
+ *
+ * We return ppt_last + 1.
+ * The only difference between the previous routine
+ * is that here we accumulate the origin values.
+ */
+FFB_LINE_LOOP2:
+ lduw [%o5], %g5
+ lduw [%o4], %g2
+ lduh [%o0 + FIFO_CACHE], %g1
+ sllx %g5, 32, %g5
+
+ and %g2, 0x7ff, %g2
+ cmp %o2, %o3
+ bgu,pn %icc, 2f
+ or %g5, %g2, %g5
+
+1: lduw [%o2 + POINT_X], %g4
+ sllx %g4, 32, %g7
+ srl %g4, 16, %g3
+ add %o2, 4, %o2
+
+ or %g7, %g3, %g7
+ subcc %g1, 3, %g1
+ bl,pn %icc, FFB_LINE2_WAIT
+ add %g7, %g5, %g5
+
+9: cmp %o2, %o3
+ stw %g0, [%o1 + FFB_PPC]
+ bleu,pt %icc, 1b
+ stx %g5, [%o1 + FFB_BH]
+
+2: sth %g1, [%o0 + FIFO_CACHE]
+ srlx %g5, 32, %g4
+ stw %g5, [%o4]
+ stw %g4, [%o5]
+
+ retl
+ mov %o2, %o0
+
+ FIFO_WAIT(%o1, 3, FFB_LINE2_WAIT, 9b)
diff --git a/src/ffb_attr.c b/src/ffb_attr.c
new file mode 100644
index 0000000..c3baf31
--- /dev/null
+++ b/src/ffb_attr.c
@@ -0,0 +1,256 @@
+/*
+ * Attribute setting for the Creator and Creator3D framebuffer.
+ *
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * JAKUB JELINEK OR DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_attr.c,v 1.2 2000/05/23 04:47:44 dawes Exp $ */
+
+#include "ffb.h"
+#include "ffb_fifo.h"
+#include "ffb_rcache.h"
+
+/* If we're going to write any attributes, write them all. */
+void __FFB_Attr_Raw(FFBPtr pFfb, unsigned int ppc, unsigned int ppc_mask,
+ unsigned int pmask, unsigned int rop,
+ int drawop, int fg, unsigned int fbc, unsigned int wid)
+{
+ ffb_fbcPtr ffb = pFfb->regs;
+
+ FFBLOG(("WRATTRS_RAW: PPC[%08x:%08x] PMSK[%08x] ROP[%08x] DOP[%08x] FG[%08x] FBC[%08x] WID[%02x]\n",
+ ppc, ppc_mask, pmask, rop, drawop, fg, fbc, wid));
+ pFfb->ppc_cache &= ~ppc_mask;
+ pFfb->ppc_cache |= ppc;
+ pFfb->fg_cache = fg;
+ pFfb->fbc_cache = fbc;
+ pFfb->wid_cache = wid;
+ pFfb->rop_cache = rop;
+ pFfb->pmask_cache = pmask;
+ pFfb->drawop_cache = drawop;
+ pFfb->rp_active = 1;
+ FFBFifo(pFfb, 7);
+ ffb->ppc = ppc;
+ ffb->fg = fg;
+ ffb->fbc = fbc;
+ ffb->wid = wid;
+ ffb->rop = rop;
+ ffb->pmask = pmask;
+ ffb->drawop = drawop;
+}
+
+void __FFB_Attr_SFB_VAR(FFBPtr pFfb, unsigned int ppc, unsigned int ppc_mask, unsigned int fbc,
+ unsigned int wid, unsigned int rop, unsigned int pmask)
+{
+ ffb_fbcPtr ffb = pFfb->regs;
+
+ FFBLOG(("WRATTRS_SFBVAR: PPC[%08x:%08x] PMSK[%08x] ROP[%08x] FBC[%08x] WID[%02x]\n",
+ ppc, ppc_mask, pmask, rop, fbc, wid));
+ pFfb->ppc_cache &= ~ppc_mask;
+ pFfb->ppc_cache |= ppc;
+ pFfb->fbc_cache = fbc;
+ pFfb->wid_cache = wid;
+ pFfb->rop_cache = rop;
+ pFfb->pmask_cache = pmask;
+ pFfb->rp_active = 1;
+ FFBFifo(pFfb, 5);
+ ffb->ppc = ppc;
+ ffb->fbc = fbc;
+ ffb->wid = wid;
+ ffb->rop = rop;
+ ffb->pmask = pmask;
+}
+
+#define NEED_PPC 0x00000001
+#define NEED_PMASK 0x00000002
+#define NEED_ROP 0x00000004
+#define NEED_DRAWOP 0x00000008
+#define NEED_FG 0x00000010
+#define NEED_BG 0x00000020
+#define NEED_FBC 0x00000040
+#define NEED_WID 0x00000080
+
+void __FFB_Attr_GC(FFBPtr pFfb, GCPtr pGC, WindowPtr pWin, unsigned int ppc, int drawop)
+{
+ ffb_fbcPtr ffb = pFfb->regs;
+ unsigned int rop, need_mask, need_count;
+
+ need_mask = need_count = 0;
+ if ((pFfb->ppc_cache & FFB_PPC_GCMASK) != ppc) {
+ unsigned int newppc = pFfb->ppc_cache & ~FFB_PPC_GCMASK;
+
+ newppc |= (ppc & FFB_PPC_GCMASK);
+ pFfb->ppc_cache = newppc;
+ need_mask |= NEED_PPC;
+ need_count++;
+ }
+
+ if (pFfb->pmask_cache != pGC->planemask) {
+ pFfb->pmask_cache = pGC->planemask;
+ need_mask |= NEED_PMASK;
+ need_count++;
+ }
+
+ rop = (pGC->alu | FFB_ROP_EDIT_BIT)|(FFB_ROP_NEW<<8);
+ if (pFfb->rop_cache != rop) {
+ pFfb->rop_cache = rop;
+ need_mask |= NEED_ROP;
+ need_count++;
+ }
+
+ if (pFfb->drawop_cache != drawop) {
+ pFfb->drawop_cache = drawop;
+ need_mask |= NEED_DRAWOP;
+ need_count++;
+ }
+
+ if (pFfb->fg_cache != pGC->fgPixel) {
+ pFfb->fg_cache = pGC->fgPixel;
+ need_mask |= NEED_FG;
+ need_count++;
+ }
+
+ {
+ CreatorPrivWinPtr WinPriv = CreatorGetWindowPrivate(pWin);
+ unsigned int fbc = WinPriv->fbc_base;
+
+ fbc &= ~FFB_FBC_XE_MASK;
+ fbc |= FFB_FBC_XE_OFF;
+
+ if (pFfb->fbc_cache != fbc) {
+ pFfb->fbc_cache = fbc;
+ need_mask |= NEED_FBC;
+ need_count++;
+ }
+
+ }
+ pFfb->rp_active = 1;
+
+ FFBLOG(("WRATTRS_GC: PPC[%08x:%08x] PMSK[%08x] ROP[%08x] "
+ "DOP[%08x] FG[%08x] FBC[%08x]\n",
+ pFfb->ppc_cache & FFB_PPC_GCMASK, FFB_PPC_GCMASK,
+ pFfb->pmask_cache, pFfb->rop_cache,
+ pFfb->drawop_cache, pFfb->fg_cache, pFfb->fbc_cache));
+
+ FFBFifo(pFfb, need_count);
+ if (need_mask & NEED_PPC)
+ ffb->ppc = (pFfb->ppc_cache & FFB_PPC_GCMASK);
+ if (need_mask & NEED_PMASK)
+ ffb->pmask = pFfb->pmask_cache;
+ if (need_mask & NEED_ROP)
+ ffb->rop = pFfb->rop_cache;
+ if (need_mask & NEED_DRAWOP)
+ ffb->drawop = pFfb->drawop_cache;
+ if (need_mask & NEED_FG)
+ ffb->fg = pFfb->fg_cache;
+ if (need_mask & NEED_FBC)
+ ffb->fbc = pFfb->fbc_cache;
+}
+
+void __FFB_Attr_FastfillWin(FFBPtr pFfb, WindowPtr pWin,
+ unsigned int ppc, unsigned int pixel)
+{
+ ffb_fbcPtr ffb = pFfb->regs;
+ unsigned int rop, need_mask, need_count;
+
+ need_mask = need_count = 0;
+ if ((pFfb->ppc_cache & FFB_PPC_WINMASK) != ppc) {
+ unsigned int newppc = pFfb->ppc_cache & ~FFB_PPC_WINMASK;
+
+ newppc |= (ppc & FFB_PPC_WINMASK);
+ pFfb->ppc_cache = newppc;
+ need_mask |= NEED_PPC;
+ need_count++;
+ }
+
+ if (pFfb->pmask_cache != 0x00ffffff) {
+ pFfb->pmask_cache = 0x00ffffff;
+ need_mask |= NEED_PMASK;
+ need_count++;
+ }
+
+ rop = FFB_ROP_NEW | (FFB_ROP_NEW<<8);
+ if (pFfb->rop_cache != rop) {
+ pFfb->rop_cache = rop;
+ need_mask |= NEED_ROP;
+ need_count++;
+ }
+
+ if (pFfb->drawop_cache != FFB_DRAWOP_FASTFILL) {
+ pFfb->drawop_cache = FFB_DRAWOP_FASTFILL;
+ need_mask |= NEED_DRAWOP;
+ need_count++;
+ }
+
+ if (pFfb->fg_cache != pixel) {
+ pFfb->fg_cache = pixel;
+ need_mask |= NEED_FG;
+ need_count++;
+ }
+
+ {
+ CreatorPrivWinPtr pWinPriv = CreatorGetWindowPrivate(pWin);
+ unsigned int fbc = pWinPriv->fbc_base;
+
+ if (pFfb->has_double_buffer) {
+ fbc &= ~FFB_FBC_WB_MASK;
+ fbc |= FFB_FBC_WB_AB;
+ }
+ fbc &= ~(FFB_FBC_XE_MASK | FFB_FBC_RGBE_MASK);
+ fbc |= FFB_FBC_XE_ON | FFB_FBC_RGBE_ON;
+ if (pFfb->ffb_res == ffb_res_high)
+ fbc |= FFB_FBC_WB_B;
+
+ if (pFfb->fbc_cache != fbc) {
+ pFfb->fbc_cache = fbc;
+ need_mask |= NEED_FBC;
+ need_count++;
+ }
+
+ if (pFfb->wid_cache != pWinPriv->wid) {
+ pFfb->wid_cache = pWinPriv->wid;
+ need_mask |= NEED_WID;
+ need_count++;
+ }
+ }
+
+ pFfb->rp_active = 1;
+
+ FFBLOG(("WRATTRS_GC: PPC[%08x:%08x] PMSK[%08x] ROP[%08x] DOP[%08x] FG[%08x] FBC[%08x] WID[%02x]\n",
+ pFfb->ppc_cache & FFB_PPC_WINMASK, FFB_PPC_WINMASK,
+ pFfb->pmask_cache, pFfb->rop_cache,
+ pFfb->drawop_cache, pFfb->fg_cache, pFfb->fbc_cache, pFfb->wid_cache));
+
+ FFBFifo(pFfb, need_count);
+ if (need_mask & NEED_PPC)
+ ffb->ppc = (pFfb->ppc_cache & FFB_PPC_WINMASK);
+ if (need_mask & NEED_PMASK)
+ ffb->pmask = pFfb->pmask_cache;
+ if (need_mask & NEED_ROP)
+ ffb->rop = pFfb->rop_cache;
+ if (need_mask & NEED_DRAWOP)
+ ffb->drawop = pFfb->drawop_cache;
+ if (need_mask & NEED_FG)
+ ffb->fg = pFfb->fg_cache;
+ if (need_mask & NEED_FBC)
+ ffb->fbc = pFfb->fbc_cache;
+ if (need_mask & NEED_WID)
+ ffb->wid = pFfb->wid_cache;
+}
diff --git a/src/ffb_bcopy.c b/src/ffb_bcopy.c
new file mode 100644
index 0000000..6de0eac
--- /dev/null
+++ b/src/ffb_bcopy.c
@@ -0,0 +1,561 @@
+/*
+ * Acceleration for the Creator and Creator3D framebuffer - Bit-blit copies.
+ *
+ * Copyright (C) 1998,1999 Jakub Jelinek (jakub@redhat.com)
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * JAKUB JELINEK OR DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_bcopy.c,v 1.2 2000/05/23 04:47:44 dawes Exp $ */
+
+#include "ffb.h"
+#include "ffb_regs.h"
+#include "ffb_rcache.h"
+#include "ffb_fifo.h"
+#include "ffb_loops.h"
+
+#include "pixmapstr.h"
+#include "scrnintstr.h"
+
+#define PSZ 8
+#include "cfb.h"
+#undef PSZ
+#include "cfb32.h"
+#include "cfb8_32wid.h"
+
+#ifdef FFB_BLOCKCOPY_IMPLEMENTED
+/* Due to VIS based copyarea and ffb rop vertscroll being significantly faster
+ * than the blockcopy rop, blockcopy was not implemented at all in the final
+ * FFB hardware design. This code is left here for hack value. -DaveM
+ */
+#error To use it, we would need to fix this to use WIDs in FFB attributes -DaveM
+void
+CreatorDoHWBitblt(DrawablePtr pSrc, DrawablePtr pDst, int alu, RegionPtr prgnDst,
+ DDXPointPtr pptSrc, unsigned long planemask)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pSrc->pScreen);
+ ffb_fbcPtr ffb = pFfb->regs;
+ BoxPtr pboxTmp;
+ DDXPointPtr pptTmp;
+ int nbox;
+ BoxPtr pboxNext, pboxBase, pbox;
+
+ nbox = REGION_NUM_RECTS(prgnDst);
+ pbox = REGION_RECTS(prgnDst);
+
+ FFB_WRITE_ATTRIBUTES(pFfb,
+ FFB_PPC_ACE_DISABLE|FFB_PPC_APE_DISABLE|FFB_PPC_CS_CONST,
+ FFB_PPC_ACE_MASK|FFB_PPC_APE_MASK|FFB_PPC_CS_MASK,
+ planemask,
+ FFB_ROP_NEW,
+ FFB_DRAWOP_BCOPY, pFfb->fg_cache,
+ FFB_FBC_DEFAULT);
+
+ /* need to blit rectangles in different orders, depending on the direction of copy
+ so that an area isnt overwritten before it is blitted */
+ if (pptSrc->y < pbox->y1 && nbox > 1) {
+ if (pptSrc->x < pbox->x1) {
+ pboxTmp = pbox + nbox;
+ pptTmp = pptSrc + nbox;
+ while(nbox--) {
+ pboxTmp--;
+ pptTmp--;
+ FFBFifo(pFfb, 6);
+ FFB_WRITE64(&ffb->by, pptTmp->y, pptTmp->x);
+ FFB_WRITE64_2(&ffb->dy, pboxTmp->y1, pboxTmp->x1);
+ FFB_WRITE64_3(&ffb->bh,
+ (pboxTmp->y2 - pboxTmp->y1),
+ (pboxTmp->x2 - pboxTmp->x1));
+ }
+ } else {
+ /* keep ordering in each band, reverse order of bands */
+ pboxBase = pboxNext = pbox+nbox-1;
+
+ while (pboxBase >= pbox) { /* for each band */
+ /* find first box in band */
+ while (pboxNext >= pbox && pboxBase->y1 == pboxNext->y1)
+ pboxNext--;
+
+ pboxTmp = pboxNext + 1; /* first box in band */
+ pptTmp = pptSrc + (pboxTmp - pbox); /* first point in band */
+
+ while (pboxTmp <= pboxBase) { /* for each box in band */
+ FFBFifo(pFfb, 6);
+ FFB_WRITE64(&ffb->by, pptTmp->y, pptTmp->x);
+ FFB_WRITE64_2(&ffb->dy, pboxTmp->y1, pboxTmp->x1);
+ FFB_WRITE64_3(&ffb->bh,
+ (pboxTmp->y2 - pboxTmp->y1),
+ (pboxTmp->x2 - pboxTmp->x1));
+ ++pboxTmp;
+ ++pptTmp;
+ }
+ pboxBase = pboxNext;
+ }
+ }
+ } else {
+ if((pptSrc->x < pbox->x1) && (nbox > 1)) {
+ pboxBase = pboxNext = pbox;
+ while(pboxBase < pbox+nbox) {
+ while((pboxNext<pbox+nbox) &&
+ (pboxNext->y1 == pboxBase->y1))
+ pboxNext++;
+ pboxTmp = pboxNext;
+ pptTmp = pptSrc + (pboxTmp - pbox);
+ while(pboxTmp != pboxBase) {
+ --pboxTmp;
+ --pptTmp;
+ FFBFifo(pFfb, 6);
+ FFB_WRITE64(&ffb->by, pptTmp->y, pptTmp->x);
+ FFB_WRITE64_2(&ffb->dy, pboxTmp->y1, pboxTmp->x1);
+ FFB_WRITE64_3(&ffb->bh,
+ (pboxTmp->y2 - pboxTmp->y1),
+ (pboxTmp->x2 - pboxTmp->x1));
+ }
+ pboxBase = pboxNext;
+ }
+ } else {
+ /* dont need to change order of anything */
+ pptTmp = pptSrc;
+ pboxTmp = pbox;
+
+ while (nbox--) {
+ FFBFifo(pFfb, 6);
+ FFB_WRITE64(&ffb->by, pptTmp->y, pptTmp->x);
+ FFB_WRITE64_2(&ffb->dy, pboxTmp->y1, pboxTmp->x1);
+ FFB_WRITE64_3(&ffb->bh,
+ (pboxTmp->y2 - pboxTmp->y1),
+ (pboxTmp->x2 - pboxTmp->x1));
+ pboxTmp++;
+ pptTmp++;
+ }
+ }
+ }
+ pFfb->rp_active = 1;
+ FFBSync(pFfb, ffb);
+}
+#endif /* FFB_BLOCKCOPY_IMPLEMENTED */
+
+/* We know here that only y is changing and that the hw attributes
+ * have been set higher up in the call chain.
+ */
+void
+CreatorDoVertBitblt(DrawablePtr pSrc, DrawablePtr pDst, int alu, RegionPtr prgnDst,
+ DDXPointPtr pptSrc, unsigned long planemask)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pSrc->pScreen);
+ ffb_fbcPtr ffb = pFfb->regs;
+ BoxPtr pbox;
+ int nbox;
+
+ pbox = REGION_RECTS(prgnDst);
+ nbox = REGION_NUM_RECTS(prgnDst);
+
+ /* No garbage please. */
+ if(nbox <= 0)
+ return;
+
+ FFBLOG(("VSCROLL(%d): ", nbox));
+
+ /* Need to blit rectangles in different orders, depending
+ * on the direction of copy so that an area isnt overwritten
+ * before it is blitted.
+ */
+ if (nbox > 1 && pptSrc->y < pbox->y1) {
+ BoxPtr pboxBase = pbox + nbox - 1;
+ BoxPtr pboxNext = pboxBase;
+
+ /* Keep ordering in each band, reverse order of bands. */
+ while (pboxBase >= pbox) { /* for each band */
+ BoxPtr pboxTmp;
+ DDXPointPtr pptTmp;
+
+ /* find first box in band */
+ while (pboxNext >= pbox && pboxBase->y1 == pboxNext->y1)
+ pboxNext--;
+
+ pboxTmp = pboxNext + 1; /* first box in band */
+ pptTmp = pptSrc + (pboxTmp - pbox); /* first point in band */
+ while (pboxTmp <= pboxBase) {
+ FFBLOG(("1[%08x:%08x:%08x:%08x:%08x:%08x] ",
+ pptTmp->x, pptTmp->y, pboxTmp->x1, pboxTmp->y1,
+ pboxTmp->x2, pboxTmp->y2));
+ FFBFifo(pFfb, 7);
+ ffb->drawop = FFB_DRAWOP_VSCROLL;
+ FFB_WRITE64(&ffb->by, pptTmp->y, pptTmp->x);
+ FFB_WRITE64_2(&ffb->dy, pboxTmp->y1, pboxTmp->x1);
+ FFB_WRITE64_3(&ffb->bh, (pboxTmp->y2 - pboxTmp->y1),
+ (pboxTmp->x2 - pboxTmp->x1));
+ pboxTmp++;
+ pptTmp++;
+ }
+ pboxBase = pboxNext;
+ }
+ } else {
+ /* Dont need to change order of anything. */
+ while (nbox--) {
+ FFBLOG(("2[%08x:%08x:%08x:%08x:%08x:%08x] ",
+ pptSrc->x, pptSrc->y, pbox->x1, pbox->y1,
+ pbox->x2, pbox->y2));
+ FFBFifo(pFfb, 7);
+ ffb->drawop = FFB_DRAWOP_VSCROLL;
+ FFB_WRITE64(&ffb->by, pptSrc->y, pptSrc->x);
+ FFB_WRITE64_2(&ffb->dy, pbox->y1, pbox->x1);
+ FFB_WRITE64_3(&ffb->bh, (pbox->y2 - pbox->y1),
+ (pbox->x2 - pbox->x1));
+ pbox++;
+ pptSrc++;
+ }
+ }
+ pFfb->rp_active = 1;
+ FFBLOG(("done\n"));
+ FFBSync(pFfb, ffb);
+}
+
+extern void VISmoveImageLR(unsigned char *, unsigned char *, long, long, long, long);
+extern void VISmoveImageRL(unsigned char *, unsigned char *, long, long, long, long);
+
+/* The hw attributes have been set by someone higher up in the call
+ * chain.
+ */
+void
+CreatorDoBitblt(DrawablePtr pSrc, DrawablePtr pDst, int alu, RegionPtr prgnDst,
+ DDXPointPtr pptSrc, unsigned long planemask)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pDst->pScreen);
+ BoxPtr pboxTmp, pboxNext, pboxBase, pbox;
+ DDXPointPtr pptTmp;
+ unsigned char *psrcBase, *pdstBase;
+ int nbox, widthSrc, widthDst, careful, use_prefetch;
+ int psz_shift;
+
+ cfbGetByteWidthAndPointer (pSrc, widthSrc, psrcBase)
+ cfbGetByteWidthAndPointer (pDst, widthDst, pdstBase)
+
+ careful = ((pSrc == pDst) ||
+ ((pSrc->type == DRAWABLE_WINDOW) &&
+ (pDst->type == DRAWABLE_WINDOW)));
+ use_prefetch = (pFfb->use_blkread_prefetch &&
+ (psrcBase == (unsigned char *)pFfb->sfb32 ||
+ psrcBase == (unsigned char *)pFfb->sfb8r));
+
+ pbox = REGION_RECTS(prgnDst);
+ nbox = REGION_NUM_RECTS(prgnDst);
+
+ pptTmp = pptSrc;
+ pboxTmp = pbox;
+
+ FFBLOG(("GCOPY(%d): ", nbox));
+
+ if (pSrc->bitsPerPixel == 8)
+ psz_shift = 0;
+ else
+ psz_shift = 2;
+
+ if (careful && pptSrc->y < pbox->y1) {
+ if (pptSrc->x < pbox->x1) {
+ /* reverse order of bands and rects in each band */
+ pboxTmp=pbox+nbox;
+ pptTmp=pptSrc+nbox;
+
+ while (nbox--){
+ pboxTmp--;
+ pptTmp--;
+ FFBLOG(("[%08x:%08x:%08x:%08x:%08x:%08x] ",
+ pptTmp->x, pptTmp->y, pboxTmp->x1, pboxTmp->y1,
+ pboxTmp->x2, pboxTmp->y2));
+ if (pptTmp->x < pbox->x2) {
+ if (use_prefetch) {
+ FFBFifo(pFfb, 1);
+ pFfb->regs->mer = FFB_MER_EDRA;
+ pFfb->rp_active = 1;
+ FFBWait(pFfb, pFfb->regs);
+ }
+ VISmoveImageRL ((psrcBase +
+ ((pptTmp->y + pboxTmp->y2 - pboxTmp->y1 - 1) *
+ widthSrc) +
+ (pptTmp->x << psz_shift)),
+ (pdstBase +
+ ((pboxTmp->y2 - 1) * widthDst) +
+ (pboxTmp->x1 << psz_shift)),
+ (pboxTmp->x2 - pboxTmp->x1) << psz_shift,
+ (pboxTmp->y2 - pboxTmp->y1),
+ -widthSrc, -widthDst);
+ } else {
+ if (use_prefetch) {
+ FFBFifo(pFfb, 1);
+ pFfb->regs->mer = FFB_MER_EIRA;
+ pFfb->rp_active = 1;
+ FFBWait(pFfb, pFfb->regs);
+ }
+ VISmoveImageLR ((psrcBase +
+ ((pptTmp->y + pboxTmp->y2 - pboxTmp->y1 - 1) *
+ widthSrc) +
+ (pptTmp->x << psz_shift)),
+ (pdstBase +
+ ((pboxTmp->y2 - 1) * widthDst) +
+ (pboxTmp->x1 << psz_shift)),
+ (pboxTmp->x2 - pboxTmp->x1) << psz_shift,
+ (pboxTmp->y2 - pboxTmp->y1),
+ -widthSrc, -widthDst);
+ }
+ }
+ } else {
+ /* keep ordering in each band, reverse order of bands */
+ pboxBase = pboxNext = pbox+nbox-1;
+
+ while (pboxBase >= pbox) { /* for each band */
+
+ /* find first box in band */
+ while (pboxNext >= pbox &&
+ pboxBase->y1 == pboxNext->y1)
+ pboxNext--;
+
+ pboxTmp = pboxNext+1; /* first box in band */
+ pptTmp = pptSrc + (pboxTmp - pbox); /* first point in band */
+
+ FFBLOG(("[%08x:%08x:%08x:%08x:%08x:%08x] ",
+ pptTmp->x, pptTmp->y, pboxTmp->x1, pboxTmp->y1,
+ pboxTmp->x2, pboxTmp->y2));
+ while (pboxTmp <= pboxBase) { /* for each box in band */
+ if (use_prefetch) {
+ FFBFifo(pFfb, 1);
+ pFfb->regs->mer = FFB_MER_EIRA;
+ pFfb->rp_active = 1;
+ FFBWait(pFfb, pFfb->regs);
+ }
+ VISmoveImageLR ((psrcBase +
+ ((pptTmp->y + pboxTmp->y2 - pboxTmp->y1 - 1) *
+ widthSrc) +
+ (pptTmp->x << psz_shift)),
+ (pdstBase +
+ ((pboxTmp->y2 - 1) * widthDst) +
+ (pboxTmp->x1 << psz_shift)),
+ (pboxTmp->x2 - pboxTmp->x1) << psz_shift,
+ (pboxTmp->y2 - pboxTmp->y1),
+ -widthSrc, -widthDst);
+ ++pboxTmp;
+ ++pptTmp;
+ }
+ pboxBase = pboxNext;
+
+ }
+ }
+ } else {
+ if (careful && pptSrc->x < pbox->x1) {
+ /* reverse order of rects in each band */
+
+ pboxBase = pboxNext = pbox;
+
+ while (pboxBase < pbox+nbox) { /* for each band */
+
+ /* find last box in band */
+ while (pboxNext < pbox+nbox &&
+ pboxNext->y1 == pboxBase->y1)
+ pboxNext++;
+
+ pboxTmp = pboxNext; /* last box in band */
+ pptTmp = pptSrc + (pboxTmp - pbox); /* last point in band */
+
+ while (pboxTmp != pboxBase) { /* for each box in band */
+ --pboxTmp;
+ --pptTmp;
+ FFBLOG(("[%08x:%08x:%08x:%08x:%08x:%08x] ",
+ pptTmp->x, pptTmp->y, pboxTmp->x1, pboxTmp->y1,
+ pboxTmp->x2, pboxTmp->y2));
+ if (pptTmp->x < pbox->x2) {
+ if (use_prefetch) {
+ FFBFifo(pFfb, 1);
+ pFfb->regs->mer = FFB_MER_EDRA;
+ pFfb->regs->mer = FFB_MER_EIRA;
+ pFfb->rp_active = 1;
+ }
+ VISmoveImageRL ((psrcBase +
+ (pptTmp->y * widthSrc) +
+ (pptTmp->x << psz_shift)),
+ (pdstBase +
+ (pboxTmp->y1 * widthDst) +
+ (pboxTmp->x1 << psz_shift)),
+ (pboxTmp->x2 - pboxTmp->x1) << psz_shift,
+ (pboxTmp->y2 - pboxTmp->y1),
+ widthSrc, widthDst);
+ } else {
+ if (use_prefetch) {
+ FFBFifo(pFfb, 1);
+ pFfb->regs->mer = FFB_MER_EIRA;
+ pFfb->rp_active = 1;
+ FFBWait(pFfb, pFfb->regs);
+ }
+ VISmoveImageLR ((psrcBase +
+ (pptTmp->y * widthSrc) +
+ (pptTmp->x << psz_shift)),
+ (pdstBase +
+ (pboxTmp->y1 * widthDst) +
+ (pboxTmp->x1 << psz_shift)),
+ (pboxTmp->x2 - pboxTmp->x1) << psz_shift,
+ (pboxTmp->y2 - pboxTmp->y1),
+ widthSrc, widthDst);
+ }
+ }
+ pboxBase = pboxNext;
+ }
+ } else {
+ while (nbox--) {
+ FFBLOG(("[%08x:%08x:%08x:%08x:%08x:%08x] ",
+ pptTmp->x, pptTmp->y, pboxTmp->x1, pboxTmp->y1,
+ pboxTmp->x2, pboxTmp->y2));
+ if (use_prefetch) {
+ FFBFifo(pFfb, 1);
+ pFfb->regs->mer = FFB_MER_EIRA;
+ pFfb->rp_active = 1;
+ FFBWait(pFfb, pFfb->regs);
+ }
+ VISmoveImageLR ((psrcBase +
+ (pptTmp->y * widthSrc) +
+ (pptTmp->x << psz_shift)),
+ (pdstBase +
+ (pboxTmp->y1 * widthDst) +
+ (pboxTmp->x1 << psz_shift)),
+ (pboxTmp->x2 - pboxTmp->x1) << psz_shift,
+ (pboxTmp->y2 - pboxTmp->y1),
+ widthSrc, widthDst);
+ pboxTmp++;
+ pptTmp++;
+ }
+ }
+ }
+ if (use_prefetch) {
+ FFBFifo(pFfb, 1);
+ pFfb->regs->mer = FFB_MER_DRA;
+ pFfb->rp_active = 1;
+ FFBWait(pFfb, pFfb->regs);
+ }
+ FFBLOG(("done\n"));
+}
+
+RegionPtr
+CreatorCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
+ GCPtr pGC, int srcx, int srcy, int width, int height, int dstx, int dsty)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pDstDrawable->pScreen);
+ ffb_fbcPtr ffb = pFfb->regs;
+ RegionPtr ret;
+ unsigned char *dptr, *sptr, *sfb;
+ int garbage, all_planes;
+
+ cfbGetByteWidthAndPointer (pDstDrawable, garbage, dptr);
+ cfbGetByteWidthAndPointer (pSrcDrawable, garbage, sptr);
+ if (pSrcDrawable->bitsPerPixel == 8) {
+ sfb = (unsigned char *) pFfb->sfb8r;
+ all_planes = 0xff;
+ } else {
+ sfb = (unsigned char *) pFfb->sfb32;
+ all_planes = 0xffffff;
+ }
+
+ FFBLOG(("CreatorCopyArea: SFB(%p) s(%p) d(%p) alu(%x) pmsk(%08x) "
+ "src(%08x:%08x) dst(%08x:%08x)\n",
+ sfb, sptr, dptr, pGC->alu, pGC->planemask,
+ srcx, srcy, dstx, dsty));
+ if (((pGC->planemask & all_planes) != all_planes || pGC->alu != GXcopy) &&
+ dptr != sfb) {
+ if(sptr == sfb) {
+ WindowPtr pWin = (WindowPtr) pSrcDrawable;
+
+ FFB_ATTR_SFB_VAR_WIN(pFfb, pGC->planemask, pGC->alu, pWin);
+ FFBWait(pFfb, ffb);
+ }
+ if (pSrcDrawable->bitsPerPixel == 8)
+ return cfbCopyArea (pSrcDrawable, pDstDrawable,
+ pGC, srcx, srcy, width, height, dstx, dsty);
+ else
+ return cfb32CopyArea (pSrcDrawable, pDstDrawable,
+ pGC, srcx, srcy, width, height, dstx, dsty);
+ }
+
+ /* Try to use hw VSCROLL if possible */
+ if (!pFfb->disable_vscroll && /* must not be ffb1 in hires */
+ pGC->alu == GXcopy && /* it must be a copy */
+ dstx == srcx && /* X must be unchanging */
+ dsty != srcy && /* Y must be changing */
+ sptr == dptr && /* src and dst must be the framebuffer */
+ dptr == sfb) {
+ WindowPtr pWin = (WindowPtr) pSrcDrawable;
+ CreatorPrivWinPtr pFfbPrivWin = CreatorGetWindowPrivate(pWin);
+ unsigned int fbc = pFfbPrivWin->fbc_base;
+ int same_buffer;
+
+ /* One last check, the read buffer and the write buffer
+ * must be the same. VSCROLL only allows to move pixels
+ * within the same buffer.
+ */
+ if (!pFfb->has_double_buffer) {
+ same_buffer = 1;
+ } else {
+ same_buffer = 0;
+ if ((((fbc & FFB_FBC_WB_MASK) == FFB_FBC_WB_A) &&
+ ((fbc & FFB_FBC_RB_MASK) == FFB_FBC_RB_A)) ||
+ (((fbc & FFB_FBC_WB_MASK) == FFB_FBC_WB_B) &&
+ ((fbc & FFB_FBC_RB_MASK) == FFB_FBC_RB_B)))
+ same_buffer = 1;
+ }
+
+ if (same_buffer != 0) {
+ FFB_ATTR_VSCROLL_WIN(pFfb, pGC->planemask, pWin);
+ if (pSrcDrawable->bitsPerPixel == 8)
+ ret = cfbBitBlt (pSrcDrawable, pDstDrawable,
+ pGC, srcx, srcy, width, height,
+ dstx, dsty,
+ (void (*)())CreatorDoVertBitblt, 0);
+ else
+ ret = cfb32BitBlt (pSrcDrawable, pDstDrawable,
+ pGC, srcx, srcy, width, height,
+ dstx, dsty,
+ (void (*)())CreatorDoVertBitblt, 0);
+ FFBLOG(("CreatorCopyArea: Done, returning %p\n", ret));
+ return ret;
+ }
+ }
+
+ /* OK, we have to use GCOPY. */
+
+ /* Even when we are only reading from the framebuffer, we must
+ * set the SFB_VAR attributes to handle double-buffering correctly.
+ */
+ if(dptr == sfb || sptr == sfb) {
+ WindowPtr pWin;
+
+ if (dptr == sfb)
+ pWin = (WindowPtr) pDstDrawable;
+ else
+ pWin = (WindowPtr) pSrcDrawable;
+ FFB_ATTR_SFB_VAR_WIN(pFfb, pGC->planemask, pGC->alu, pWin);
+ FFBWait(pFfb, ffb);
+ }
+ if (pSrcDrawable->bitsPerPixel == 8)
+ ret = cfbBitBlt (pSrcDrawable, pDstDrawable,
+ pGC, srcx, srcy, width, height,
+ dstx, dsty, (void (*)())CreatorDoBitblt, 0);
+ else
+ ret = cfb32BitBlt (pSrcDrawable, pDstDrawable,
+ pGC, srcx, srcy, width, height,
+ dstx, dsty, (void (*)())CreatorDoBitblt, 0);
+
+ FFBLOG(("CreatorCopyArea: Done, returning %p\n", ret));
+ return ret;
+}
diff --git a/src/ffb_checks.c b/src/ffb_checks.c
new file mode 100644
index 0000000..d809aa6
--- /dev/null
+++ b/src/ffb_checks.c
@@ -0,0 +1,288 @@
+/*
+ * Acceleration for the Creator and Creator3D framebuffer - stipple/tile/line-pattern
+ * verification.
+ *
+ * Copyright (C) 1998,1999 Jakub Jelinek (jakub@redhat.com)
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * JAKUB JELINEK OR DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_checks.c,v 1.2 2000/05/23 04:47:44 dawes Exp $ */
+
+#include "ffb.h"
+#include "ffb_regs.h"
+#include "ffb_rcache.h"
+#include "ffb_fifo.h"
+
+#include "pixmapstr.h"
+#include "scrnintstr.h"
+
+#define PSZ 8
+#include "cfb.h"
+#undef PSZ
+#include "cfb32.h"
+
+int
+CreatorCheckTile (PixmapPtr pPixmap, CreatorStipplePtr stipple, int ox, int oy, int ph)
+{
+ unsigned int *sbits;
+ unsigned int fg = 0, bg = 0;
+ int fgset = 0, bgset = 0;
+ unsigned int *tilebitsLine, *tilebits, tilebit;
+ unsigned int sbit, mask;
+ int nbwidth;
+ int h, w;
+ int x, y;
+ int s_y, s_x;
+
+ h = pPixmap->drawable.height;
+ if (h > 32 || (h & (h - 1)))
+ return FALSE;
+
+ w = pPixmap->drawable.width;
+ if (w > 32 || (w & (w - 1)))
+ return FALSE;
+
+ stipple->patalign = (oy << 16) | ox;
+ sbits = stipple->bits;
+ tilebitsLine = (unsigned int *) pPixmap->devPrivate.ptr;
+ nbwidth = pPixmap->devKind / sizeof(unsigned int);
+
+ for (y = 0; y < h; y++) {
+ tilebits = tilebitsLine;
+ tilebitsLine += nbwidth;
+ sbit = 0;
+ mask = 1 << 31;
+ for (x = 0; x < w; x++) {
+ tilebit = *tilebits++;
+ if (fgset && tilebit == fg)
+ sbit |= mask;
+ else if (!bgset || tilebit != bg) {
+ if (!fgset) {
+ fgset = 1;
+ fg = tilebit;
+ sbit |= mask;
+ } else if (!bgset) {
+ bgset = 1;
+ bg = tilebit;
+ } else {
+ return FALSE;
+ }
+ }
+ mask >>= 1;
+ }
+ for (s_x = w; s_x < 32; s_x <<= 1)
+ sbit = sbit | (sbit >> s_x);
+ sbit = (sbit >> ox) | (sbit << (32 - ox));
+ for (s_y = y; s_y < 32; s_y += h)
+ sbits[(s_y + oy) & 31] = sbit;
+ }
+ stipple->pagable = 1;
+ for(y = 0; y < (32 - ph); y++) {
+ if(sbits[y] != sbits[(y+ph) & (32 - 1)]) {
+ stipple->pagable = 0;
+ break;
+ }
+ }
+ stipple->fg = fg;
+ stipple->bg = bg;
+ stipple->inhw = 0;
+ return TRUE;
+}
+
+int
+CreatorCheckStipple (PixmapPtr pPixmap, CreatorStipplePtr stipple, int ox, int oy, int ph)
+{
+ unsigned int *sbits;
+ unsigned int *stippleBits;
+ unsigned int sbit, mask, nbwidth;
+ int h, w;
+ int y;
+ int s_y, s_x;
+
+ h = pPixmap->drawable.height;
+ if (h > 32 || (h & (h - 1)))
+ return FALSE;
+
+ w = pPixmap->drawable.width;
+ if (w > 32 || (w & (w - 1)))
+ return FALSE;
+
+ stipple->patalign = (oy << 16) | ox;
+ sbits = stipple->bits;
+ stippleBits = (unsigned int *) pPixmap->devPrivate.ptr;
+ nbwidth = pPixmap->devKind / sizeof(unsigned int);
+ mask = ~0 << (32 - w);
+ for (y = 0; y < h; y++) {
+ sbit = (*stippleBits) & mask;
+ stippleBits += nbwidth;
+ for (s_x = w; s_x < 32; s_x <<= 1)
+ sbit = sbit | (sbit >> s_x);
+ sbit = (sbit >> ox) | (sbit << (32 - ox));
+ for (s_y = y; s_y < 32; s_y += h)
+ sbits[(s_y + oy) & 31] = sbit;
+ }
+ stipple->pagable = 1;
+ for(y = 0; y < (32 - ph); y++) {
+ if(sbits[y] != sbits[(y+ph) & (32 - 1)]) {
+ stipple->pagable = 0;
+ break;
+ }
+ }
+ stipple->inhw = 0;
+ return TRUE;
+}
+
+int
+CreatorCheckLinePattern(GCPtr pGC, CreatorPrivGCPtr gcPriv)
+{
+ unsigned int linepat = 0;
+ unsigned char *dashp = (unsigned char *)pGC->dash;
+ int ndash = pGC->numInDashList;
+ int doff = (int) pGC->dashOffset;
+ int smallest_dashlen;
+ int i, nbits = 0;
+
+ for(i = 0; i < ndash; i++)
+ nbits += dashp[i];
+ if(nbits <= 16) {
+ /* We can do it simply, so don't try to use all of
+ * the hair below.
+ */
+ nbits = 0;
+ for(i = 0; i < ndash; i++) {
+ int this_bits = dashp[i];
+ if((i & 1) == 0) {
+ int x;
+
+ for(x = 0; x < this_bits; x++)
+ linepat |= (1<<(nbits + x));
+ }
+ nbits += this_bits;
+ }
+ smallest_dashlen = 1;
+ } else {
+ /* Iteratively find a usable line pattern bitmap and
+ * assosciated scale. This is slow, but it works.
+ * Feel free to come up with something more efficient. -DaveM
+ */
+ smallest_dashlen = 0;
+ while(smallest_dashlen++ < 16) {
+ int bits_so_far = 0;
+
+ for(i = 0; i < ndash; i++) {
+ if((dashp[i] % smallest_dashlen) != 0)
+ break;
+ bits_so_far += dashp[i] / smallest_dashlen;
+ if(bits_so_far >= 16)
+ return FALSE;
+ }
+ if(i == ndash)
+ break;
+ }
+ if(smallest_dashlen == 16)
+ return FALSE;
+
+ /* Compute the final scaled line pattern. */
+ nbits = 0;
+ for(i = 0; i < ndash; i++) {
+ int this_bits = dashp[i] / smallest_dashlen;
+
+ nbits += this_bits;
+ if((i & 1) != 0)
+ continue;
+ while(this_bits--)
+ linepat |= (1<<(nbits - this_bits - 1));
+ }
+ }
+
+ /* We're golden... */
+ linepat = ((linepat << FFB_LPAT_PATTERN_SHIFT) |
+ (smallest_dashlen << FFB_LPAT_SCALEVAL_SHIFT) |
+ ((nbits & 0xf) << FFB_LPAT_PATLEN_SHIFT) |
+ (((doff / smallest_dashlen) & 0xf) << FFB_LPAT_PATPTR_SHIFT) |
+ (((doff % smallest_dashlen) & 0xf) << FFB_LPAT_SCALEPTR_SHIFT));
+ gcPriv->linepat = linepat;
+ return TRUE;
+}
+
+/* cache one stipple; figuring out if we can use the stipple is as hard as
+ * computing it, so we just use this one and leave it here if it
+ * can't be used this time
+ */
+
+CreatorStipplePtr FFB_tmpStipple;
+
+int
+CreatorCheckFill (GCPtr pGC, DrawablePtr pDrawable)
+{
+ CreatorPrivGCPtr gcPriv = CreatorGetGCPrivate (pGC);
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN(pDrawable->pScreen);
+ CreatorStipplePtr stipple;
+ unsigned int alu;
+ int xrot, yrot, ph = FFB_FFPARMS(pFfb).pagefill_height;
+
+ if (pGC->fillStyle == FillSolid) {
+ if (gcPriv->stipple) {
+ xfree (gcPriv->stipple);
+ gcPriv->stipple = 0;
+ }
+ return TRUE;
+ }
+ if (!(stipple = gcPriv->stipple)) {
+ if (!FFB_tmpStipple) {
+ FFB_tmpStipple = (CreatorStipplePtr) xalloc (sizeof *FFB_tmpStipple);
+ if (!FFB_tmpStipple)
+ return FALSE;
+ }
+ stipple = FFB_tmpStipple;
+ }
+ xrot = (pGC->patOrg.x + pDrawable->x) & 31;
+ yrot = (pGC->patOrg.y + pDrawable->y) & 31;
+ alu = pGC->alu;
+ switch (pGC->fillStyle) {
+ case FillTiled:
+ if (!CreatorCheckTile (pGC->tile.pixmap, stipple, xrot, yrot, ph)) {
+ if (gcPriv->stipple) {
+ xfree (gcPriv->stipple);
+ gcPriv->stipple = 0;
+ }
+ return FALSE;
+ }
+ break;
+ case FillStippled:
+ alu |= FFB_ROP_EDIT_BIT;
+ case FillOpaqueStippled:
+ if (!CreatorCheckStipple (pGC->stipple, stipple, xrot, yrot, ph)) {
+ if (gcPriv->stipple) {
+ xfree (gcPriv->stipple);
+ gcPriv->stipple = 0;
+ }
+ return FALSE;
+ }
+ stipple->fg = pGC->fgPixel;
+ stipple->bg = pGC->bgPixel;
+ break;
+ }
+ stipple->alu = alu;
+ gcPriv->stipple = stipple;
+ if (stipple == FFB_tmpStipple)
+ FFB_tmpStipple = 0;
+ return TRUE;
+}
diff --git a/src/ffb_circle.c b/src/ffb_circle.c
new file mode 100644
index 0000000..5c46b01
--- /dev/null
+++ b/src/ffb_circle.c
@@ -0,0 +1,210 @@
+/*
+ * Acceleration for the Creator and Creator3D framebuffer - Circle rops.
+ *
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * JAKUB JELINEK OR DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_circle.c,v 1.2 2000/05/23 04:47:44 dawes Exp $ */
+
+#include "ffb.h"
+#include "ffb_regs.h"
+#include "ffb_rcache.h"
+#include "ffb_fifo.h"
+#include "ffb_stip.h"
+
+#include "pixmapstr.h"
+#include "scrnintstr.h"
+
+#define PSZ 8
+#include "cfb.h"
+#undef PSZ
+#include "cfb32.h"
+#include "cfb8_32wid.h"
+
+#include "mi.h"
+#include "mifillarc.h"
+
+/* Wheee, circles... */
+static void
+CreatorFillEllipseSolid(DrawablePtr pDrawable, GCPtr pGC, xArc *arc)
+{
+ WindowPtr pWin = (WindowPtr) pDrawable;
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN(pDrawable->pScreen);
+ CreatorPrivGCPtr gcPriv = CreatorGetGCPrivate (pGC);
+ ffb_fbcPtr ffb = pFfb->regs;
+ miFillArcRec info;
+ int x, y, e, yk, xk, ym, xm, dx, dy, xorg, yorg, slw;
+
+ /* Get the RP ready. */
+ if(gcPriv->stipple == NULL) {
+ FFB_ATTR_GC(pFfb, pGC, pWin,
+ FFB_PPC_APE_DISABLE | FFB_PPC_CS_CONST,
+ FFB_DRAWOP_RECTANGLE);
+ } else {
+ unsigned int fbc;
+
+ FFBSetStipple(pFfb, ffb, gcPriv->stipple,
+ FFB_PPC_CS_CONST, FFB_PPC_CS_MASK);
+ FFB_WRITE_PMASK(pFfb, ffb, pGC->planemask);
+ FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_RECTANGLE);
+ fbc = FFB_FBC_WIN(pWin);
+ fbc = (fbc & ~FFB_FBC_XE_MASK) | FFB_FBC_XE_OFF;
+ FFB_WRITE_FBC(pFfb, ffb, fbc);
+ }
+
+ /* Start computing the rects. */
+ miFillArcSetup(arc, &info);
+ MIFILLARCSETUP();
+ if(pGC->miTranslate) {
+ xorg += pDrawable->x;
+ yorg += pDrawable->y;
+ }
+ while(y > 0) {
+ MIFILLARCSTEP(slw);
+ if(slw > 0) {
+ /* Render. */
+ FFBFifo(pFfb, 4);
+ FFB_WRITE64(&ffb->by, yorg - y, xorg - x);
+ FFB_WRITE64_2(&ffb->bh, 1, slw);
+ if(miFillArcLower(slw)) {
+ FFBFifo(pFfb, 4);
+ FFB_WRITE64(&ffb->by, yorg + y + dy, xorg - x);
+ FFB_WRITE64_2(&ffb->bh, 1, slw);
+ }
+ }
+ }
+ pFfb->rp_active = 1;
+ FFBSync(pFfb, ffb);
+}
+
+#define ADDSPAN(l,r) \
+ if (r >= l) { \
+ FFBFifo(pFfb, 4); \
+ FFB_WRITE64(&ffb->by, ya, l); \
+ FFB_WRITE64_2(&ffb->bh, 1, r - l + 1); \
+ }
+
+#define ADDSLICESPANS(flip) \
+ if (!flip) \
+ { \
+ ADDSPAN(xl, xr); \
+ } \
+ else \
+ { \
+ xc = xorg - x; \
+ ADDSPAN(xc, xr); \
+ xc += slw - 1; \
+ ADDSPAN(xl, xc); \
+ }
+
+static void
+CreatorFillArcSliceSolid(DrawablePtr pDrawable, GCPtr pGC, xArc *arc)
+{
+ WindowPtr pWin = (WindowPtr) pDrawable;
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN(pDrawable->pScreen);
+ CreatorPrivGCPtr gcPriv = CreatorGetGCPrivate (pGC);
+ ffb_fbcPtr ffb = pFfb->regs;
+ miFillArcRec info;
+ miArcSliceRec slice;
+ int x, y, e, yk, xk, ym, xm, dx, dy, xorg, yorg, slw;
+ int ya, xl, xr, xc;
+
+ /* Get the RP ready. */
+ if(gcPriv->stipple == NULL) {
+ FFB_ATTR_GC(pFfb, pGC, pWin,
+ FFB_PPC_APE_DISABLE | FFB_PPC_CS_CONST,
+ FFB_DRAWOP_RECTANGLE);
+ } else {
+ unsigned int fbc;
+
+ FFBSetStipple(pFfb, ffb, gcPriv->stipple,
+ FFB_PPC_CS_CONST, FFB_PPC_CS_MASK);
+ FFB_WRITE_PMASK(pFfb, ffb, pGC->planemask);
+ FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_RECTANGLE);
+ fbc = FFB_FBC_WIN(pWin);
+ fbc = (fbc & ~FFB_FBC_XE_MASK) | FFB_FBC_XE_OFF;
+ FFB_WRITE_FBC(pFfb, ffb, fbc);
+ FFB_WRITE_FBC(pFfb, ffb, FFB_FBC_WIN(pWin));
+ }
+ miFillArcSetup(arc, &info);
+ miFillArcSliceSetup(arc, &slice, pGC);
+ MIFILLARCSETUP();
+ slw = arc->height;
+ if (slice.flip_top || slice.flip_bot)
+ slw += (arc->height >> 1) + 1;
+ if (pGC->miTranslate) {
+ xorg += pDrawable->x;
+ yorg += pDrawable->y;
+ slice.edge1.x += pDrawable->x;
+ slice.edge2.x += pDrawable->x;
+ }
+ while (y > 0) {
+ MIFILLARCSTEP(slw);
+ MIARCSLICESTEP(slice.edge1);
+ MIARCSLICESTEP(slice.edge2);
+ if (miFillSliceUpper(slice)) {
+ ya = yorg - y;
+ MIARCSLICEUPPER(xl, xr, slice, slw);
+ ADDSLICESPANS(slice.flip_top);
+ }
+ if (miFillSliceLower(slice)) {
+ ya = yorg + y + dy;
+ MIARCSLICELOWER(xl, xr, slice, slw);
+ ADDSLICESPANS(slice.flip_bot);
+ }
+ }
+ pFfb->rp_active = 1;
+ FFBSync(pFfb, ffb);
+}
+
+void
+CreatorPolyFillArcSolid (DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc *parcs)
+{
+ RegionPtr cclip;
+ xArc *arc;
+ BoxRec box;
+ int i, x2, y2;
+
+ FFBLOG(("CreatorPolyFillArcSolid: narcs(%d)\n", narcs));
+ cclip = cfbGetCompositeClip(pGC);
+ for(arc = parcs, i = narcs; --i >= 0; arc++) {
+ if(miFillArcEmpty(arc))
+ continue;
+ if(miCanFillArc(arc)) {
+ box.x1 = arc->x + pDrawable->x;
+ box.y1 = arc->y + pDrawable->y;
+ box.x2 = x2 = box.x1 + (int)arc->width + 1;
+ box.y2 = y2 = box.y1 + (int)arc->height + 1;
+ if((x2 & ~0x7ff) == 0 &&
+ (y2 & ~0x7ff) == 0 &&
+ (RECT_IN_REGION(pDrawable->pScreen, cclip, &box) == rgnIN)) {
+ if(arc->angle2 >= FULLCIRCLE ||
+ arc->angle2 <= -FULLCIRCLE)
+ CreatorFillEllipseSolid(pDrawable, pGC, arc);
+ else
+ CreatorFillArcSliceSolid(pDrawable, pGC, arc);
+ continue;
+ }
+ }
+ /* Use slow mi code if we can't handle it simply. */
+ miPolyFillArc(pDrawable, pGC, 1, arc);
+ }
+}
diff --git a/src/ffb_clip.c b/src/ffb_clip.c
new file mode 100644
index 0000000..2369381
--- /dev/null
+++ b/src/ffb_clip.c
@@ -0,0 +1,103 @@
+/*
+ * Acceleration for the Creator and Creator3D framebuffer - clip setting.
+ *
+ * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com)
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * JAKUB JELINEK OR DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_clip.c,v 1.1 2000/05/18 23:21:36 dawes Exp $ */
+
+#include "ffb.h"
+#include "ffb_regs.h"
+#include "ffb_rcache.h"
+#include "ffb_fifo.h"
+#include "ffb_clip.h"
+
+unsigned int
+FFBSetClip(FFBPtr pFfb, ffb_fbcPtr ffb, RegionPtr pClip, int numRects)
+{
+ unsigned int xy1, xy2;
+
+ if (numRects == 1) {
+ xy1 = (pClip->extents.y1 << 16) | pClip->extents.x1;
+ xy2 = ((pClip->extents.y2 - 1) << 16) | (pClip->extents.x2 - 1);
+ if (pFfb->clips[0] == xy1 && pFfb->clips[1] == xy2)
+ return FFB_PPC_VCE_2D|FFB_PPC_ACE_DISABLE;
+ FFBFifo(pFfb, 2);
+ FFB_WRITE64(&ffb->vclipmin, xy1, xy2);
+ pFfb->clips[0] = xy1;
+ pFfb->clips[1] = xy2;
+ return FFB_PPC_VCE_2D|FFB_PPC_ACE_DISABLE;
+ } else if (numRects <= 5) {
+ ffb_auxclipPtr auxclip;
+ BoxPtr pBox = REGION_RECTS(pClip);
+ int i, j;
+ unsigned int xy3, xy4;
+
+ xy1 = (pBox->y1 << 16) | pBox->x1;
+ xy2 = ((pBox->y2 - 1) << 16) | (pBox->x2 - 1);
+ if (pFfb->clips[0] == xy1 && pFfb->clips[1] == xy2) {
+ j = 0;
+ for (i = 1; i < numRects; i++) {
+ xy3 = (pBox[i].y1 << 16) | pBox[i].x1;
+ xy4 = ((pBox[i].y2 - 1) << 16) | (pBox[i].x2 - 1);
+ if (j || xy3 != pFfb->clips[2*i] || xy4 != pFfb->clips[2*i+1]) {
+ j = 1;
+ pFfb->clips[2*i] = xy3;
+ pFfb->clips[2*i+1] = xy4;
+ }
+ }
+ for (; i < 5; i++) {
+ if (j || pFfb->clips[2*i] != 1 || pFfb->clips[2*i+1]) {
+ j = 1;
+ pFfb->clips[2*i] = 1;
+ pFfb->clips[2*i+1] = 0;
+ }
+ }
+ if (!j)
+ return FFB_PPC_VCE_2D|FFB_PPC_ACE_AUX_ADD;
+ FFBFifo(pFfb, 8);
+ auxclip = ffb->auxclip;
+ for (i = 1; i < 5; i++, auxclip++)
+ FFB_WRITE64P(&auxclip->min, &pFfb->clips[2*i]);
+ return FFB_PPC_VCE_2D|FFB_PPC_ACE_AUX_ADD;
+ }
+ FFBFifo(pFfb, 10);
+ FFB_WRITE64(&ffb->vclipmin, xy1, xy2);
+ pFfb->clips[0] = xy1;
+ pFfb->clips[1] = xy2;
+ auxclip = ffb->auxclip;
+ pBox++;
+ for (i = 1; i < numRects; i++, auxclip++, pBox++) {
+ xy3 = (pBox->y1 << 16) | pBox->x1;
+ xy4 = ((pBox->y2 - 1) << 16) | (pBox->x2 - 1);
+ FFB_WRITE64(&auxclip->min, xy3, xy4);
+ pFfb->clips[2*i] = xy3;
+ pFfb->clips[2*i+1] = xy4;
+ }
+ for (; i < 5; i++, auxclip++) {
+ FFB_WRITE64(&auxclip->min, 1, 0);
+ pFfb->clips[2*i] = 1;
+ pFfb->clips[2*i+1] = 0;
+ }
+ return FFB_PPC_VCE_2D|FFB_PPC_ACE_AUX_ADD;
+ }
+ return 0;
+}
diff --git a/src/ffb_clip.h b/src/ffb_clip.h
new file mode 100644
index 0000000..b90655b
--- /dev/null
+++ b/src/ffb_clip.h
@@ -0,0 +1,49 @@
+/*
+ * Acceleration for the Creator and Creator3D framebuffer - clipping defines.
+ *
+ * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com)
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * JAKUB JELINEK OR DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_clip.h,v 1.1 2000/05/18 23:21:36 dawes Exp $ */
+
+#ifndef FFBCLIP_H
+#define FFBCLIP_H
+
+extern unsigned int FFBSetClip(FFBPtr pFfb,
+ ffb_fbcPtr ffb,
+ RegionPtr pClip,
+ int numRects);
+static __inline__ void
+FFBSet1Clip(FFBPtr pFfb, ffb_fbcPtr ffb, BoxPtr extents)
+{
+ unsigned int xy1, xy2;
+
+ xy1 = (extents->y1 << 16) | extents->x1;
+ xy2 = ((extents->y2 - 1) << 16) | (extents->x2 - 1);
+ if (pFfb->clips[0] == xy1 && pFfb->clips[1] == xy2)
+ return;
+ FFBFifo(pFfb, 2);
+ FFB_WRITE64(&ffb->vclipmin, xy1, xy2);
+ pFfb->clips[0] = xy1;
+ pFfb->clips[1] = xy2;
+}
+
+#endif /* FFBCLIP_H */
diff --git a/src/ffb_cplane.c b/src/ffb_cplane.c
new file mode 100644
index 0000000..a94b373
--- /dev/null
+++ b/src/ffb_cplane.c
@@ -0,0 +1,393 @@
+/*
+ * Acceleration for the Creator and Creator3D framebuffer - Plane copies.
+ *
+ * Copyright (C) 1998,1999 Jakub Jelinek (jakub@redhat.com)
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * JAKUB JELINEK OR DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_cplane.c,v 1.2 2000/05/23 04:47:44 dawes Exp $ */
+
+#include "ffb.h"
+#include "ffb_regs.h"
+#include "ffb_rcache.h"
+#include "ffb_fifo.h"
+
+#include "pixmapstr.h"
+#include "scrnintstr.h"
+
+#define PSZ 8
+#include "cfb.h"
+#undef PSZ
+#include "cfb32.h"
+
+#include "cfbmskbits.h"
+#include "mi.h"
+
+/* Blatantly stolen from mach64 driver. */
+#define mfbmaskbits(x, w, startmask, endmask, nlw) \
+ startmask = starttab[(x)&0x1f]; \
+ endmask = endtab[((x)+(w)) & 0x1f]; \
+ if (startmask) \
+ nlw = (((w) - (32 - ((x)&0x1f))) >> 5); \
+ else \
+ nlw = (w) >> 5;
+
+#define mfbmaskpartialbits(x, w, mask) \
+ mask = partmasks[(x)&0x1f][(w)&0x1f];
+
+#define LeftMost 0
+#define StepBit(bit, inc) ((bit) += (inc))
+
+
+#define GetBits(psrc, nBits, curBit, bitPos, bits) {\
+ bits = 0; \
+ while (nBits--) { \
+ bits |= ((*psrc++ >> bitPos) & 1) << curBit; \
+ StepBit (curBit, 1); \
+ } \
+}
+
+static void
+CreatorCopyPlane32to1 (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, int rop, RegionPtr prgnDst,
+ DDXPointPtr pptSrc, unsigned long planemask, unsigned long bitPlane)
+{
+ int srcx, srcy, dstx, dsty, width, height;
+ unsigned long *psrcBase;
+ unsigned long *pdstBase;
+ int widthSrc, widthDst;
+ unsigned int *psrcLine;
+ unsigned int *pdstLine;
+ register unsigned int *psrc;
+ register int i;
+ register int curBit;
+ register int bitPos;
+ register unsigned int bits;
+ register unsigned int *pdst;
+ unsigned int startmask, endmask;
+ int niStart = 0, niEnd = 0;
+ int bitStart = 0, bitEnd = 0;
+ int nl, nlMiddle;
+ int nbox;
+ BoxPtr pbox;
+ int result;
+
+ extern int starttab[32], endtab[32];
+ extern unsigned int partmasks[32][32];
+
+ if (!(planemask & 1))
+ return;
+
+ /* must explicitly ask for "int" widths, as code below expects it */
+ /* on some machines (Sparc64), "long" and "int" are not the same size */
+ cfbGetTypedWidthAndPointer (pSrcDrawable, widthSrc, psrcBase, int, unsigned long)
+ cfbGetTypedWidthAndPointer (pDstDrawable, widthDst, pdstBase, int, unsigned long)
+
+ bitPos = ffs (bitPlane) - 1;
+
+ nbox = REGION_NUM_RECTS(prgnDst);
+ pbox = REGION_RECTS(prgnDst);
+ while (nbox--) {
+ dstx = pbox->x1;
+ dsty = pbox->y1;
+ srcx = pptSrc->x;
+ srcy = pptSrc->y;
+ width = pbox->x2 - pbox->x1;
+ height = pbox->y2 - pbox->y1;
+ pbox++;
+ pptSrc++;
+ psrcLine = (unsigned int *)psrcBase + srcy * widthSrc + srcx;
+ pdstLine = (unsigned int *)pdstBase + dsty * widthDst + (dstx >> 5);
+ if (dstx + width <= 32) {
+ mfbmaskpartialbits(dstx, width, startmask);
+ nlMiddle = 0;
+ endmask = 0;
+ } else {
+ mfbmaskbits (dstx, width, startmask, endmask, nlMiddle);
+ }
+ if (startmask) {
+ niStart = 32 - (dstx & 0x1f);
+ bitStart = LeftMost;
+ StepBit (bitStart, (dstx & 0x1f));
+ }
+ if (endmask) {
+ niEnd = (dstx + width) & 0x1f;
+ bitEnd = LeftMost;
+ }
+ if (rop == GXcopy) {
+ while (height--) {
+ psrc = psrcLine;
+ pdst = pdstLine;
+ psrcLine += widthSrc;
+ pdstLine += widthDst;
+ if (startmask) {
+ i = niStart;
+ curBit = bitStart;
+ GetBits (psrc, i, curBit, bitPos, bits);
+
+ *pdst = (*pdst & ~startmask) | bits;
+ pdst++;
+ }
+ nl = nlMiddle;
+
+ while (nl--) {
+ i = 32;
+ curBit = LeftMost;
+ GetBits (psrc, i, curBit, bitPos, bits);
+ *pdst++ = bits;
+ }
+ if (endmask) {
+ i = niEnd;
+ curBit = bitEnd;
+ GetBits (psrc, i, curBit, bitPos, bits);
+
+ *pdst = (*pdst & ~endmask) | bits;
+ }
+ }
+ } else {
+ while (height--) {
+ psrc = psrcLine;
+ pdst = pdstLine;
+ psrcLine += widthSrc;
+ pdstLine += widthDst;
+ if (startmask) {
+ i = niStart;
+ curBit = bitStart;
+ GetBits (psrc, i, curBit, bitPos, bits);
+ DoRop (result, rop, bits, *pdst);
+
+ *pdst = (*pdst & ~startmask) | (result & startmask);
+ pdst++;
+ }
+ nl = nlMiddle;
+ while (nl--) {
+ i = 32;
+ curBit = LeftMost;
+ GetBits (psrc, i, curBit, bitPos, bits);
+ DoRop (result, rop, bits, *pdst);
+ *pdst = result;
+ ++pdst;
+ }
+ if (endmask) {
+ i = niEnd;
+ curBit = bitEnd;
+ GetBits (psrc, i, curBit, bitPos, bits);
+ DoRop (result, rop, bits, *pdst);
+
+ *pdst = (*pdst & ~endmask) | (result & endmask);
+ }
+ }
+ }
+ }
+}
+
+static unsigned int copyPlaneFG, copyPlaneBG;
+
+static void
+CreatorCopyPlane1toFbBpp (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, int alu, RegionPtr prgnDst, DDXPointPtr pptSrc, unsigned long planemask, unsigned long bitPlane)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pDstDrawable->pScreen);
+ WindowPtr pWin = (WindowPtr) pDstDrawable;
+ ffb_fbcPtr ffb = pFfb->regs;
+ int srcx, srcy, dstx, dsty, width, height;
+ int xoffSrc, widthSrc;
+ unsigned int *psrcBase, *psrc, *psrcStart;
+ unsigned int w, tmp, i;
+ int nbox;
+ BoxPtr pbox;
+
+ {
+ unsigned int ppc = (FFB_PPC_APE_DISABLE | FFB_PPC_TBE_OPAQUE |
+ FFB_PPC_CS_CONST);
+ unsigned int ppc_mask = (FFB_PPC_APE_MASK | FFB_PPC_TBE_MASK |
+ FFB_PPC_CS_MASK);
+ unsigned int rop = (FFB_ROP_EDIT_BIT | alu) | (FFB_ROP_NEW << 8);
+ unsigned int fbc = FFB_FBC_WIN(pWin);
+
+ fbc = (fbc & ~FFB_FBC_XE_MASK) | FFB_FBC_XE_OFF;
+
+ if((pFfb->ppc_cache & ppc_mask) != ppc ||
+ pFfb->fg_cache != copyPlaneFG ||
+ pFfb->fbc_cache != fbc ||
+ pFfb->rop_cache != rop ||
+ pFfb->pmask_cache != planemask ||
+ pFfb->bg_cache != copyPlaneBG) {
+ pFfb->ppc_cache &= ~ppc_mask;
+ pFfb->ppc_cache |= ppc;
+ pFfb->fg_cache = copyPlaneFG;
+ pFfb->fbc_cache = fbc;
+ pFfb->rop_cache = rop;
+ pFfb->pmask_cache = planemask;
+ pFfb->bg_cache = copyPlaneBG;
+ pFfb->rp_active = 1;
+ FFBFifo(pFfb, 6);
+ ffb->ppc = ppc;
+ ffb->fg = copyPlaneFG;
+ ffb->fbc = fbc;
+ ffb->rop = rop;
+ ffb->pmask = planemask;
+ ffb->bg = copyPlaneBG;
+ }
+ }
+
+ cfbGetTypedWidthAndPointer (pSrcDrawable, widthSrc, psrcBase, unsigned int, unsigned int)
+
+ nbox = REGION_NUM_RECTS(prgnDst);
+ pbox = REGION_RECTS(prgnDst);
+ while (nbox--) {
+ dstx = pbox->x1;
+ dsty = pbox->y1;
+ srcx = pptSrc->x;
+ srcy = pptSrc->y;
+ width = pbox->x2 - dstx;
+ height = pbox->y2 - dsty;
+ pbox++;
+ pptSrc++;
+ if (!width)
+ continue;
+ psrc = psrcBase + srcy * widthSrc + (srcx >> 5);
+ for (xoffSrc = srcx & 0x1f; height--; psrc = psrcStart + widthSrc) {
+ w = width;
+ psrcStart = psrc;
+ FFBFifo(pFfb, (1 + (xoffSrc != 0)));
+ ffb->fontxy = ((dsty++ << 16) | (dstx & 0xffff));
+ if (xoffSrc) {
+ tmp = 32 - xoffSrc;
+ if (tmp > w)
+ tmp = w;
+ FFB_WRITE_FONTW(pFfb, ffb, tmp);
+ FFB_WRITE_FONTINC(pFfb, ffb, tmp);
+ ffb->font = *psrc++ << xoffSrc;
+ w -= tmp;
+ }
+ if (!w)
+ continue;
+ FFB_WRITE_FONTW(pFfb, ffb, 32);
+ FFB_WRITE_FONTINC(pFfb, ffb, 32);
+ while (w >= 256) {
+ FFBFifo(pFfb, 8);
+ for (i = 0; i < 8; i++)
+ ffb->font = *psrc++;
+ w -= 256;
+ }
+ while (w >= 32) {
+ FFBFifo(pFfb, 1);
+ ffb->font = *psrc++;
+ w -= 32;
+ }
+ if (w) {
+ FFB_WRITE_FONTW(pFfb, ffb, w);
+ FFBFifo(pFfb, 1);
+ ffb->font = *psrc++;
+ }
+ }
+ }
+ pFfb->rp_active = 1;
+ FFBSync(pFfb, ffb);
+}
+
+RegionPtr CreatorCopyPlane(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
+ GCPtr pGC, int srcx, int srcy, int width, int height,
+ int dstx, int dsty, unsigned long bitPlane)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pSrcDrawable->pScreen);
+ WindowPtr pWin = (WindowPtr) pDstDrawable;
+ ffb_fbcPtr ffb = pFfb->regs;
+ RegionPtr ret;
+
+ FFBLOG(("CreatorCopyPlane: sbpp(%d) dbpp(%d) src[%08x:%08x] dst[%08x:%08x] bplane(%08x)\n",
+ pSrcDrawable->bitsPerPixel, pDstDrawable->bitsPerPixel,
+ srcx, srcy, dstx, dsty, bitPlane));
+ if (pSrcDrawable->bitsPerPixel == 1 &&
+ (pDstDrawable->bitsPerPixel == 32 || pDstDrawable->bitsPerPixel == 8)) {
+ if (bitPlane == 1) {
+ copyPlaneFG = pGC->fgPixel;
+ copyPlaneBG = pGC->bgPixel;
+ ret = cfbBitBlt (pSrcDrawable, pDstDrawable,
+ pGC, srcx, srcy, width, height,
+ dstx, dsty, CreatorCopyPlane1toFbBpp, bitPlane);
+ } else
+ ret = miHandleExposures (pSrcDrawable, pDstDrawable,
+ pGC, srcx, srcy, width, height, dstx, dsty, bitPlane);
+ } else if ((pSrcDrawable->bitsPerPixel == 32 || pSrcDrawable->bitsPerPixel == 8)
+ && pDstDrawable->bitsPerPixel == 1) {
+ extern int InverseAlu[16];
+ int oldalu;
+
+ oldalu = pGC->alu;
+ if ((pGC->fgPixel & 1) == 0 && (pGC->bgPixel&1) == 1)
+ pGC->alu = InverseAlu[pGC->alu];
+ else if ((pGC->fgPixel & 1) == (pGC->bgPixel & 1))
+ pGC->alu = mfbReduceRop(pGC->alu, pGC->fgPixel);
+ FFB_ATTR_SFB_VAR_WIN(pFfb, 0x00ffffff, GXcopy, pWin);
+ FFBWait(pFfb, ffb);
+ if (pSrcDrawable->bitsPerPixel == 32) {
+ ret = cfbBitBlt (pSrcDrawable, pDstDrawable,
+ pGC, srcx, srcy, width, height, dstx, dsty,
+ CreatorCopyPlane32to1, bitPlane);
+ } else {
+ ret = cfbBitBlt (pSrcDrawable, pDstDrawable,
+ pGC, srcx, srcy, width, height, dstx, dsty,
+ cfbCopyPlane8to1, bitPlane);
+ }
+ pGC->alu = oldalu;
+ } else {
+ PixmapPtr pBitmap;
+ ScreenPtr pScreen = pSrcDrawable->pScreen;
+ GCPtr pGC1;
+
+ pBitmap = (*pScreen->CreatePixmap) (pScreen, width, height, 1);
+ if (!pBitmap)
+ return NULL;
+ pGC1 = GetScratchGC (1, pScreen);
+ if (!pGC1) {
+ (*pScreen->DestroyPixmap) (pBitmap);
+ return NULL;
+ }
+ /*
+ * don't need to set pGC->fgPixel,bgPixel as copyPlane{8,32}to1
+ * ignores pixel values, expecting the rop to "do the
+ * right thing", which GXcopy will.
+ */
+ ValidateGC ((DrawablePtr) pBitmap, pGC1);
+ /* no exposures here, scratch GC's don't get graphics expose */
+ FFB_ATTR_SFB_VAR_WIN(pFfb, 0x00ffffff, GXcopy, pWin);
+ FFBWait(pFfb, ffb);
+ if (pSrcDrawable->bitsPerPixel == 32) {
+ cfbBitBlt (pSrcDrawable, (DrawablePtr) pBitmap,
+ pGC1, srcx, srcy, width, height, 0, 0,
+ CreatorCopyPlane32to1, bitPlane);
+ } else {
+ cfbBitBlt (pSrcDrawable, (DrawablePtr) pBitmap,
+ pGC1, srcx, srcy, width, height, 0, 0,
+ cfbCopyPlane8to1, bitPlane);
+ }
+ copyPlaneFG = pGC->fgPixel;
+ copyPlaneBG = pGC->bgPixel;
+ cfbBitBlt ((DrawablePtr) pBitmap, pDstDrawable, pGC,
+ 0, 0, width, height, dstx, dsty, CreatorCopyPlane1toFbBpp, 1);
+ FreeScratchGC (pGC1);
+ (*pScreen->DestroyPixmap) (pBitmap);
+ /* compute resultant exposures */
+ ret = miHandleExposures (pSrcDrawable, pDstDrawable, pGC,
+ srcx, srcy, width, height,
+ dstx, dsty, bitPlane);
+ }
+ return ret;
+}
diff --git a/src/ffb_cursor.c b/src/ffb_cursor.c
new file mode 100644
index 0000000..3fc2292
--- /dev/null
+++ b/src/ffb_cursor.c
@@ -0,0 +1,139 @@
+/*
+ * Hardware cursor support for Creator, Creator 3D and Elite 3D
+ *
+ * Copyright 2000 by Jakub Jelinek <jakub@redhat.com>.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of Jakub
+ * Jelinek not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Jakub Jelinek makes no representations about the
+ * suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * JAKUB JELINEK DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL JAKUB JELINEK BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_cursor.c,v 1.2 2000/05/23 04:47:44 dawes Exp $ */
+
+#include "ffb.h"
+
+/* This file just performs cursor software state management. The
+ * actual programming is done by calls into the DAC layer.
+ */
+
+static void FFBLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src);
+static void FFBShowCursor(ScrnInfoPtr pScrn);
+static void FFBHideCursor(ScrnInfoPtr pScrn);
+static void FFBSetCursorPosition(ScrnInfoPtr pScrn, int x, int y);
+static void FFBSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg);
+
+static void
+FFBLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
+ unsigned int *data = (unsigned int *)src;
+ int x, y;
+
+ pFfb->CursorData = src;
+ x = pFfb->CursorShiftX;
+ y = pFfb->CursorShiftY;
+ if (x >= 64 || y >= 64)
+ y = 64;
+ FFBDacCursorLoadBitmap(pFfb, x, y, data);
+}
+
+static void
+FFBShowCursor(ScrnInfoPtr pScrn)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
+
+ FFBDacCursorEnableDisable(pFfb, 1);
+}
+
+static void
+FFBHideCursor(ScrnInfoPtr pScrn)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
+
+ FFBDacCursorEnableDisable(pFfb, 0);
+ pFfb->CursorData = NULL;
+}
+
+static void
+FFBSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
+ int CursorShiftX = 0, CursorShiftY = 0;
+
+ if (x < 0) {
+ CursorShiftX = -x;
+ x = 0;
+ if (CursorShiftX > 64)
+ CursorShiftX = 64;
+ }
+ if (y < 0) {
+ CursorShiftY = -y;
+ y = 0;
+ if (CursorShiftY > 64)
+ CursorShiftY = 64;
+ }
+ if ((CursorShiftX != pFfb->CursorShiftX ||
+ CursorShiftY != pFfb->CursorShiftY) &&
+ pFfb->CursorData != NULL) {
+ pFfb->CursorShiftX = CursorShiftX;
+ pFfb->CursorShiftY = CursorShiftY;
+ FFBLoadCursorImage(pScrn, pFfb->CursorData);
+ }
+
+ FFBDacLoadCursorPos(pFfb, x, y);
+}
+
+static void
+FFBSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
+
+ FFBDacLoadCursorColor(pFfb, fg, bg);
+}
+
+Bool
+FFBHWCursorInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ FFBPtr pFfb;
+ xf86CursorInfoPtr infoPtr;
+
+ pFfb = GET_FFB_FROM_SCRN(pScrn);
+ pFfb->CursorShiftX = 0;
+ pFfb->CursorShiftY = 0;
+ pFfb->CursorData = NULL;
+
+ infoPtr = xf86CreateCursorInfoRec();
+ if(!infoPtr) return FALSE;
+
+ pFfb->CursorInfoRec = infoPtr;
+
+ infoPtr->MaxWidth = 64;
+ infoPtr->MaxHeight = 64;
+ infoPtr->Flags = HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
+ HARDWARE_CURSOR_SOURCE_MASK_NOT_INTERLEAVED;
+
+ infoPtr->SetCursorColors = FFBSetCursorColors;
+ infoPtr->SetCursorPosition = FFBSetCursorPosition;
+ infoPtr->LoadCursorImage = FFBLoadCursorImage;
+ infoPtr->HideCursor = FFBHideCursor;
+ infoPtr->ShowCursor = FFBShowCursor;
+ infoPtr->UseHWCursor = NULL;
+
+ return xf86InitCursor(pScreen, infoPtr);
+}
diff --git a/src/ffb_dac.c b/src/ffb_dac.c
new file mode 100644
index 0000000..01b746e
--- /dev/null
+++ b/src/ffb_dac.c
@@ -0,0 +1,612 @@
+/*
+ * Acceleration for the Creator and Creator3D framebuffer - DAC programming.
+ *
+ * Copyright (C) 2000 David S. Miller (davem@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_dac.c,v 1.4 2002/12/06 02:44:03 tsi Exp $ */
+
+#include "ffb.h"
+#include "ffb_rcache.h"
+#include "ffb_fifo.h"
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+
+#include "xf86DDC.h"
+
+/*
+ * Used for stabilize time after playing with power management on the display
+ */
+
+#ifndef DPMS_SPIN_COUNT
+#define DPMS_SPIN_COUNT 100
+#endif /* DPMS_SPIN_COUNT */
+
+/* Cursor programming */
+
+void
+FFBDacLoadCursorPos(FFBPtr pFfb, int x, int y)
+{
+ ffb_dacPtr dac = pFfb->dac;
+ int posval;
+
+ posval = ((y & 0xffff) << 16) | (x & 0xffff);
+ posval &= (FFBDAC_CUR_POS_Y_SIGN |
+ FFBDAC_CUR_POS_Y |
+ FFBDAC_CUR_POS_X_SIGN |
+ FFBDAC_CUR_POS_X);
+
+ DACCUR_WRITE(dac, FFBDAC_CUR_POS, posval);
+}
+
+void
+FFBDacLoadCursorColor(FFBPtr pFfb, int fg, int bg)
+{
+ ffb_dacPtr dac = pFfb->dac;
+
+ dac->cur = FFBDAC_CUR_COLOR1;
+ dac->curdata = bg;
+ dac->curdata = fg;
+}
+
+void
+FFBDacCursorEnableDisable(FFBPtr pFfb, int enable)
+{
+ ffb_dac_info_t *p = &pFfb->dac_info;
+ ffb_dacPtr dac = pFfb->dac;
+ int val;
+
+ val = 0;
+ if (!enable)
+ val = (FFBDAC_CUR_CTRL_P0 | FFBDAC_CUR_CTRL_P1);
+
+ /* PAC1 ramdacs with manufacturing revision less than
+ * '3' invert these control bits, wheee...
+ */
+ if (p->flags & FFB_DAC_ICURCTL)
+ val ^= (FFBDAC_CUR_CTRL_P0 | FFBDAC_CUR_CTRL_P1);
+
+ DACCUR_WRITE(dac, FFBDAC_CUR_CTRL, val);
+}
+
+void
+FFBDacCursorLoadBitmap(FFBPtr pFfb, int xshift, int yshift, unsigned int *bitmap)
+{
+ ffb_dacPtr dac = pFfb->dac;
+ int i, j;
+
+ dac->cur = FFBDAC_CUR_BITMAP_P0;
+ for (j = 0; j < 2; j++) {
+ bitmap += yshift * 2;
+ if (!xshift) {
+ for (i = yshift * 2; i < 128; i++)
+ dac->curdata = *bitmap++;
+ } else if (xshift < 32) {
+ for (i = yshift; i < 64; i++, bitmap += 2) {
+ dac->curdata = (bitmap[0] << xshift) |
+ (bitmap[1] >> (32 - xshift));
+ dac->curdata = bitmap[1] << xshift;
+ }
+ } else {
+ for (i = yshift; i < 64; i++, bitmap += 2) {
+ dac->curdata = bitmap[1] << (xshift - 32);
+ dac->curdata = 0;
+ }
+ }
+
+ for (i = 0; i < yshift * 2; i++)
+ dac->curdata = 0;
+ }
+}
+
+/* Config space programming */
+
+/* XF86 LoadPalette callback. */
+
+void
+FFBDacLoadPalette(ScrnInfoPtr pScrn, int ncolors, int *indices, LOCO *colors, VisualPtr pVisual)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
+ ffb_dac_info_t *p = &pFfb->dac_info;
+ ffb_dacPtr dac = pFfb->dac;
+ unsigned int *cluts;
+ int i, index, palette;
+
+ if ((pVisual->nplanes != 8 && pVisual->class != DirectColor) ||
+ (pVisual->nplanes == 8 && pVisual->class == StaticGray))
+ return;
+
+ palette = 0;
+ if (p->flags & FFB_DAC_PAC2) {
+ if (pVisual->class == PseudoColor)
+ palette = 0;
+ if (pVisual->class == GrayScale)
+ palette = 1;
+ if (pVisual->class == DirectColor)
+ palette = 2;
+ }
+
+ cluts = &p->x_dac_state.clut[256 * palette];
+ for (i = 0; i < ncolors; i++) {
+ unsigned int regval;
+
+ index = indices[i];
+ if (pVisual->class == GrayScale) {
+ regval = cluts[index] =
+ ((colors[index].red << FFBDAC_COLOR_RED_SHFT) |
+ (colors[index].red << FFBDAC_COLOR_GREEN_SHFT) |
+ (colors[index].red << FFBDAC_COLOR_BLUE_SHFT));
+ } else {
+ regval = cluts[index] =
+ ((colors[index].red << FFBDAC_COLOR_RED_SHFT) |
+ (colors[index].green << FFBDAC_COLOR_GREEN_SHFT) |
+ (colors[index].blue << FFBDAC_COLOR_BLUE_SHFT));
+ }
+
+ FFBLOG(("FFBDacLoadPalette: visclass(%d) index(%d) val[%08x]\n",
+ pVisual->class, index, regval));
+
+ /* Now update the hardware copy. */
+ dac->cfg = FFBDAC_CFG_CLUP(palette) + index;
+ dac->cfgdata = regval;
+ }
+}
+
+/* WARNING: Very dangerous function, use with extreme care. */
+static void
+dac_stop(FFBPtr pFfb)
+{
+ ffb_dacPtr dac = pFfb->dac;
+ unsigned int tgctrl;
+
+ tgctrl = DACCFG_READ(dac, FFBDAC_CFG_TGEN);
+ if (tgctrl & FFBDAC_CFG_TGEN_TGE) {
+ long limit = 1000000;
+
+ /* We try to shut off the timing generation
+ * precisely at the beginning of a vertical
+ * retrace. This is really just to make it
+ * look nice, it's not a functional necessity.
+ *
+ * The limit is so that malfunctioning hardware
+ * does not end up hanging the server.
+ */
+ while (limit--) {
+ unsigned int vctr = DACCFG_READ(dac, FFBDAC_CFG_TGVC);
+
+ if (vctr == 0)
+ break;
+ }
+
+ DACCFG_WRITE(dac, FFBDAC_CFG_TGEN, 0);
+ }
+}
+
+/* This is made slightly complex because the ordering matters
+ * between several operations. We have to stop the DAC while
+ * restoring the timing registers so that some intermediate
+ * state does not emit wild retrace signals to the monitor.
+ *
+ * Another further complication is that we need to mess with
+ * some portions of the FFB framebuffer config registers to
+ * do this all properly.
+ */
+static void
+dac_state_restore(FFBPtr pFfb, ffb_dac_hwstate_t *state)
+{
+ ffb_dac_info_t *p = &pFfb->dac_info;
+ ffb_dacPtr dac = pFfb->dac;
+ ffb_fbcPtr ffb = pFfb->regs;
+ int i, nluts;
+
+ /* Step 1: Shut off all pixel timing generation. */
+ dac_stop(pFfb);
+ ffb->fbcfg0 = 0;
+
+ /* Step 2: Restore timing settings. */
+ DACCFG_WRITE(dac, FFBDAC_CFG_VBNP, state->vbnp);
+ DACCFG_WRITE(dac, FFBDAC_CFG_VBAP, state->vbap);
+ DACCFG_WRITE(dac, FFBDAC_CFG_VSNP, state->vsnp);
+ DACCFG_WRITE(dac, FFBDAC_CFG_VSAP, state->vsap);
+ DACCFG_WRITE(dac, FFBDAC_CFG_HSNP, state->hsnp);
+ DACCFG_WRITE(dac, FFBDAC_CFG_HBNP, state->hbnp);
+ DACCFG_WRITE(dac, FFBDAC_CFG_HBAP, state->hbap);
+ DACCFG_WRITE(dac, FFBDAC_CFG_HSYNCNP, state->hsyncnp);
+ DACCFG_WRITE(dac, FFBDAC_CFG_HSYNCAP, state->hsyncap);
+ DACCFG_WRITE(dac, FFBDAC_CFG_HSCENNP, state->hscennp);
+ DACCFG_WRITE(dac, FFBDAC_CFG_HSCENAP, state->hscenap);
+ DACCFG_WRITE(dac, FFBDAC_CFG_EPNP, state->epnp);
+ DACCFG_WRITE(dac, FFBDAC_CFG_EINP, state->einp);
+ DACCFG_WRITE(dac, FFBDAC_CFG_EIAP, state->eiap);
+
+ /* Step 3: Restore rest of DAC hw state. */
+ DACCFG_WRITE(dac, FFBDAC_CFG_PPLLCTRL, state->ppllctrl);
+ DACCFG_WRITE(dac, FFBDAC_CFG_GPLLCTRL, state->gpllctrl);
+ DACCFG_WRITE(dac, FFBDAC_CFG_PFCTRL, state->pfctrl);
+ DACCFG_WRITE(dac, FFBDAC_CFG_UCTRL, state->uctrl);
+
+ nluts = (p->flags & FFB_DAC_PAC1) ? 256 : (4 * 256);
+ dac->cfg = FFBDAC_CFG_CLUP_BASE;
+ for (i = 0; i < nluts; i++)
+ dac->cfgdata = state->clut[i];
+
+ if (p->flags & FFB_DAC_PAC2) {
+ dac->cfg = FFBDAC_PAC2_AOVWLUT0;
+ for (i = 0; i < 4; i++)
+ dac->cfgdata = state->ovluts[i];
+ }
+
+ DACCFG_WRITE(dac, FFBDAC_CFG_WTCTRL, state->wtctrl);
+ DACCFG_WRITE(dac, FFBDAC_CFG_TMCTRL, state->tmctrl);
+ DACCFG_WRITE(dac, FFBDAC_CFG_TCOLORKEY, state->tcolorkey);
+ if (p->flags & FFB_DAC_PAC2)
+ DACCFG_WRITE(dac, FFBDAC_CFG_WAMASK, state->wamask);
+
+ if (p->flags & FFB_DAC_PAC1) {
+ dac->cfg = FFBDAC_PAC1_APWLUT_BASE;
+ for (i = 0; i < 32; i++)
+ dac->cfgdata = state->pwluts[i];
+ } else {
+ dac->cfg = FFBDAC_PAC2_APWLUT_BASE;
+ for (i = 0; i < 64; i++)
+ dac->cfgdata = state->pwluts[i];
+ }
+
+ DACCFG_WRITE(dac, FFBDAC_CFG_DACCTRL, state->dacctrl);
+
+ /* Step 4: Restore FFB framebuffer config state. */
+ if (pFfb->ffb_type == ffb2_vertical_plus ||
+ pFfb->ffb_type == ffb2_horizontal_plus ||
+ pFfb->ffb_type == afb_m3 ||
+ pFfb->ffb_type == afb_m6)
+ ffb->passin = p->ffb_passin_ctrl;
+ ffb->fbcfg0 = p->ffbcfg0;
+ ffb->fbcfg2 = p->ffbcfg2;
+
+ /* Step 5: Restore the timing generator control reg. */
+ DACCFG_WRITE(dac, FFBDAC_CFG_TGEN, state->tgen);
+
+ /* Step 6: Pause for a bit. */
+ for (i = 0; i < 100; i++)
+ (void) DACCFG_READ(dac, FFBDAC_CFG_TGVC);
+}
+
+static void
+dac_state_save(FFBPtr pFfb, ffb_dac_hwstate_t *state)
+{
+ ffb_dac_info_t *p = &pFfb->dac_info;
+ ffb_dacPtr dac = pFfb->dac;
+ int i, nluts;
+
+ state->ppllctrl = DACCFG_READ(dac, FFBDAC_CFG_PPLLCTRL);
+ state->gpllctrl = DACCFG_READ(dac, FFBDAC_CFG_GPLLCTRL);
+ state->pfctrl = DACCFG_READ(dac, FFBDAC_CFG_PFCTRL);
+ state->uctrl = DACCFG_READ(dac, FFBDAC_CFG_UCTRL);
+
+ nluts = (p->flags & FFB_DAC_PAC1) ? 256 : (4 * 256);
+ dac->cfg = FFBDAC_CFG_CLUP_BASE;
+ for (i = 0; i < nluts; i++)
+ state->clut[i] = dac->cfgdata;
+
+ if (p->flags & FFB_DAC_PAC2) {
+ dac->cfg = FFBDAC_PAC2_AOVWLUT0;
+ for (i = 0; i < 4; i++)
+ state->ovluts[i] = dac->cfgdata;
+ }
+
+ state->wtctrl = DACCFG_READ(dac, FFBDAC_CFG_WTCTRL);
+ state->tmctrl = DACCFG_READ(dac, FFBDAC_CFG_TMCTRL);
+ state->tcolorkey = DACCFG_READ(dac, FFBDAC_CFG_TCOLORKEY);
+ if (p->flags & FFB_DAC_PAC2)
+ state->wamask = DACCFG_READ(dac, FFBDAC_CFG_WAMASK);
+
+ if (p->flags & FFB_DAC_PAC1) {
+ dac->cfg = FFBDAC_PAC1_APWLUT_BASE;
+ for (i = 0; i < 32; i++)
+ state->pwluts[i] = dac->cfgdata;
+ } else {
+ dac->cfg = FFBDAC_PAC2_APWLUT_BASE;
+ for (i = 0; i < 64; i++)
+ state->pwluts[i] = dac->cfgdata;
+ }
+
+ state->dacctrl = DACCFG_READ(dac, FFBDAC_CFG_DACCTRL);
+
+ state->tgen = DACCFG_READ(dac, FFBDAC_CFG_TGEN);
+ state->vbnp = DACCFG_READ(dac, FFBDAC_CFG_VBNP);
+ state->vbap = DACCFG_READ(dac, FFBDAC_CFG_VBAP);
+ state->vsnp = DACCFG_READ(dac, FFBDAC_CFG_VSNP);
+ state->vsap = DACCFG_READ(dac, FFBDAC_CFG_VSAP);
+ state->hsnp = DACCFG_READ(dac, FFBDAC_CFG_HSNP);
+ state->hbnp = DACCFG_READ(dac, FFBDAC_CFG_HBNP);
+ state->hbap = DACCFG_READ(dac, FFBDAC_CFG_HBAP);
+ state->hsyncnp = DACCFG_READ(dac, FFBDAC_CFG_HSYNCNP);
+ state->hsyncap = DACCFG_READ(dac, FFBDAC_CFG_HSYNCAP);
+ state->hscennp = DACCFG_READ(dac, FFBDAC_CFG_HSCENNP);
+ state->hscenap = DACCFG_READ(dac, FFBDAC_CFG_HSCENAP);
+ state->epnp = DACCFG_READ(dac, FFBDAC_CFG_EPNP);
+ state->einp = DACCFG_READ(dac, FFBDAC_CFG_EINP);
+ state->eiap = DACCFG_READ(dac, FFBDAC_CFG_EIAP);
+}
+
+static void
+init_dac_flags(FFBPtr pFfb)
+{
+ ffb_dac_info_t *p = &pFfb->dac_info;
+ ffb_dacPtr dac = pFfb->dac;
+ unsigned int did, manuf_rev, partnum;
+ char *device;
+
+ /* Fetch kernel WID. */
+ p->kernel_wid = *((volatile unsigned char *)pFfb->dfb8x);
+
+ /* For AFB, assume it is PAC2 which also implies not having
+ * the inverted cursor control attribute.
+ */
+ if (pFfb->ffb_type == afb_m3 || pFfb->ffb_type == afb_m6) {
+ p->flags = FFB_DAC_PAC2;
+ manuf_rev = 4;
+ } else {
+ p->flags = 0;
+
+ did = DACCFG_READ(dac, FFBDAC_CFG_DID);
+
+ manuf_rev = DACCFG_READ(dac, FFBDAC_CFG_UCTRL);
+ manuf_rev = (manuf_rev & FFBDAC_UCTRL_MANREV) >> 8;
+
+ partnum = ((did & FFBDAC_CFG_DID_PNUM) >> 12);
+ if (partnum == 0x236e)
+ p->flags |= FFB_DAC_PAC2;
+ else
+ p->flags |= FFB_DAC_PAC1;
+ }
+
+ device = pFfb->psdp->device;
+ if ((p->flags & FFB_DAC_PAC1) != 0) {
+ if (manuf_rev < 3) {
+ p->flags |= FFB_DAC_ICURCTL;
+ xf86Msg(X_INFO, "%s: BT9068 (PAC1) ramdac detected (with "
+ "inverted cursor control)\n", device);
+ } else {
+ xf86Msg(X_INFO, "%s: BT9068 (PAC1) ramdac detected (with "
+ "normal cursor control)\n", device);
+ }
+ } else {
+ xf86Msg(X_INFO, "%s: BT498 (PAC2) ramdac detected\n", device);
+ }
+}
+
+/* The registers of the chip must be mapped, and the FFB/AFB
+ * board type must be probed before this is invoked.
+ */
+Bool
+FFBDacInit(FFBPtr pFfb)
+{
+ ffb_dac_info_t *p = &pFfb->dac_info;
+ ffb_fbcPtr ffb = pFfb->regs;
+
+ init_dac_flags(pFfb);
+
+ p->ffbcfg0 = ffb->fbcfg0;
+ p->ffbcfg2 = ffb->fbcfg2;
+ if (pFfb->ffb_type == ffb2_vertical_plus ||
+ pFfb->ffb_type == ffb2_horizontal_plus ||
+ pFfb->ffb_type == afb_m3 ||
+ pFfb->ffb_type == afb_m6)
+ p->ffb_passin_ctrl = ffb->passin;
+
+ /* Save the kernel DAC state. We also save to the
+ * X server state here as well even though we have
+ * not modified anything yet.
+ */
+ dac_state_save(pFfb, &p->kern_dac_state);
+ dac_state_save(pFfb, &p->x_dac_state);
+
+ /* Fire up the WID layer. */
+ FFBWidPoolInit(pFfb);
+
+ return TRUE;
+}
+
+/* We need to reset the A buffer X planes to the value 0xff
+ * when giving the hardware back to the kernel too, thus...
+ * Also need to do this for the B buffer X planes when double
+ * buffering is available.
+ */
+static void
+restore_kernel_xchannel(FFBPtr pFfb)
+{
+ ffb_fbcPtr ffb = pFfb->regs;
+ unsigned int fbc, ppc, ppc_mask, drawop, wid;
+
+ wid = pFfb->dac_info.kernel_wid;
+
+ if (pFfb->has_double_buffer)
+ fbc = FFB_FBC_WB_AB;
+ else
+ fbc = FFB_FBC_WB_A;
+
+ fbc |= (FFB_FBC_WM_COMBINED | FFB_FBC_RB_A | FFB_FBC_SB_BOTH |
+ FFB_FBC_ZE_OFF | FFB_FBC_YE_OFF |
+ FFB_FBC_XE_ON | FFB_FBC_RGBE_MASK);
+
+ ppc = (FFB_PPC_APE_DISABLE | FFB_PPC_CS_CONST | FFB_PPC_XS_WID);
+ ppc_mask = (FFB_PPC_APE_MASK | FFB_PPC_CS_MASK | FFB_PPC_XS_MASK);
+
+ drawop = FFB_DRAWOP_RECTANGLE;
+
+ FFB_ATTR_RAW(pFfb, ppc, ppc_mask, ~0,
+ (FFB_ROP_EDIT_BIT | GXcopy)|(FFB_ROP_NEW<<8),
+ drawop, 0x0, fbc, wid);
+
+ FFBFifo(pFfb, 4);
+ FFB_WRITE64(&ffb->by, 0, 0);
+ FFB_WRITE64_2(&ffb->bh, pFfb->psdp->height, pFfb->psdp->width);
+ pFfb->rp_active = 1;
+ FFBWait(pFfb, ffb);
+}
+
+void
+FFBDacFini(FFBPtr pFfb)
+{
+ ffb_dac_info_t *p = &pFfb->dac_info;
+
+ /* Just restore the kernel ramdac/x-channel state. */
+ dac_state_restore(pFfb, &p->kern_dac_state);
+ restore_kernel_xchannel(pFfb);
+}
+
+
+/* Restore X server DAC state. */
+void
+FFBDacEnterVT(FFBPtr pFfb)
+{
+ ffb_dac_info_t *p = &pFfb->dac_info;
+
+ /* Save kernel DAC state. */
+ dac_state_save(pFfb, &p->kern_dac_state);
+
+ /* Restore X DAC state. */
+ dac_state_restore(pFfb, &p->x_dac_state);
+}
+
+/* Restore kernel DAC state. */
+void
+FFBDacLeaveVT(FFBPtr pFfb)
+{
+ ffb_dac_info_t *p = &pFfb->dac_info;
+
+ /* Save X DAC state. */
+ dac_state_save(pFfb, &p->x_dac_state);
+
+ /* Restore kernel DAC and x-channel state. */
+ dac_state_restore(pFfb, &p->kern_dac_state);
+ restore_kernel_xchannel(pFfb);
+}
+
+/* DPMS stuff, courtesy of a hint from David S. Miller.
+ * 05.xii.01, FEM
+ */
+
+/*
+ * I don't know why, if at all, this is needed, but JJ or DSM do it
+ * on restore. I observe that when just blanking/unblanking, everything
+ * works fine without it, but that sometimes DPMS -> Standby actually
+ * results in Off. Maybe related?
+ */
+static void
+SPIN(ffb_dacPtr d, int count) {
+ while(count-- > 0) {
+ (void) DACCFG_READ(d, FFBDAC_CFG_TGVC);
+ }
+ return;
+}
+
+/* Screen save (blank) restore */
+Bool
+FFBDacSaveScreen(FFBPtr pFfb, int mode) {
+ int tmp;
+ ffb_dacPtr dac;
+ if(!pFfb) return FALSE; /* Is there any way at all this could happen? */
+ else dac = pFfb -> dac;
+
+ tmp = DACCFG_READ(dac, FFBDAC_CFG_TGEN); /* Get the timing information */
+
+ switch(mode) {
+ case SCREEN_SAVER_ON:
+ case SCREEN_SAVER_CYCLE:
+ tmp &= ~FFBDAC_CFG_TGEN_VIDE; /* Kill the video */
+ break;
+
+ case SCREEN_SAVER_OFF:
+ case SCREEN_SAVER_FORCER:
+ tmp |= FFBDAC_CFG_TGEN_VIDE; /* Turn the video on */
+ break;
+
+ default:
+ return FALSE; /* Don't know what to do; gently fail. */
+ }
+ DACCFG_WRITE(dac, FFBDAC_CFG_TGEN, tmp); /* Restore timing register, video set as asked */
+ SPIN(dac, DPMS_SPIN_COUNT/10);
+ return TRUE;
+}
+
+/* DPMS Control, also hinted at by David Miller.
+
+ The rule seems to be:
+
+ StandBy = -HSYNC +VSYNC -VIDEO
+ Suspend = +HSYNC -VSYNC -VIDEO
+ Off = -HSYNC -VSYNC -VIDEO
+ On = +HSYNC +VSINC +VIDEO
+
+ If you don't force video off, someone periodically tries to turn the
+ monitor on for some reason. I don't know who or why, so I kill the video
+ when trying to go into some sort of energy saving mode. (In real life,
+ 'xset s blank s xx' could well have taken care of this.)
+
+ Also, on MY monitor, StandBy as above defined (-H+V-Vid) in fact
+ gives the same as Off, which I don't want. Hence, I just do (-Vid)
+
+ 05.xii.01, FEM
+ 08.xii.01, FEM
+*/
+void
+FFBDacDPMSMode(FFBPtr pFfb, int DPMSMode, int flags) {
+ int tmp;
+ ffb_dacPtr dac = pFfb -> dac;
+
+ tmp = DACCFG_READ(dac, FFBDAC_CFG_TGEN); /* Get timing control */
+
+ switch(DPMSMode) {
+
+ case DPMSModeOn:
+ tmp &= ~(FFBDAC_CFG_TGEN_VSD | FFBDAC_CFG_TGEN_HSD); /* Turn off VSYNC, HSYNC
+ disable bits */
+ tmp |= FFBDAC_CFG_TGEN_VIDE; /* Turn the video on */
+ break;
+
+ case DPMSModeStandby:
+#ifdef DPMS_TRUE_STANDBY
+ tmp |= FFBDAC_CFG_TGEN_HSD; /* HSYNC = OFF */
+#endif /* DPMS_TRUE_STANDBY */
+ tmp &= ~FFBDAC_CFG_TGEN_VSD; /* VSYNC = ON */
+ tmp &= ~FFBDAC_CFG_TGEN_VIDE; /* Kill the video */
+ break;
+
+ case DPMSModeSuspend:
+ tmp |= FFBDAC_CFG_TGEN_VSD; /* VSYNC = OFF */
+ tmp &= ~FFBDAC_CFG_TGEN_HSD; /* HSYNC = ON */
+ tmp &= ~FFBDAC_CFG_TGEN_VIDE; /* Kill the video */
+ break;
+
+ case DPMSModeOff:
+ tmp |= (FFBDAC_CFG_TGEN_VSD | FFBDAC_CFG_TGEN_HSD); /* Kill HSYNC, VSYNC both */
+ tmp &= ~FFBDAC_CFG_TGEN_VIDE; /* Kill the video */
+ break;
+
+ default:
+ return; /* If we get here, we really should log an error */
+ }
+ DACCFG_WRITE(dac, FFBDAC_CFG_TGEN,tmp); /* Restore timing register, video set as asked */
+ SPIN(dac, DPMS_SPIN_COUNT); /* Is this necessary? Why? */
+}
diff --git a/src/ffb_dac.h b/src/ffb_dac.h
new file mode 100644
index 0000000..b6c4f5d
--- /dev/null
+++ b/src/ffb_dac.h
@@ -0,0 +1,365 @@
+/*
+ * Acceleration for the Creator and Creator3D framebuffer - DAC register layout.
+ *
+ * Copyright (C) 2000 David S. Miller (davem@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_dac.h,v 1.2 2001/04/05 17:42:33 dawes Exp $ */
+
+#ifndef _FFB_DAC_H
+#define _FFB_DAC_H
+
+/* FFB utilizes two different ramdac chips:
+ *
+ * 1) BT9068 "Pacifica1", used in all FFB1 and
+ * FFB2 boards.
+ *
+ * 2) BT498(a) "Pacifica2", used in FFB2+ and
+ * AFB boards.
+ *
+ * They are mostly equivalent, except in a few key areas:
+ *
+ * 1) WID register layout
+ * 2) Number of CLUT tables
+ * 3) Presence of Window Address Mask register
+ * 4) Method of GAMMA correction support
+ */
+
+/* NOTE: All addresses described in this file are DAC
+ * indirect addresses.
+ */
+
+/* DAC color values are in the following format. */
+#define FFBDAC_COLOR_BLUE 0x00ff0000
+#define FFBDAC_COLOR_BLUE_SHFT 16
+#define FFBDAC_COLOR_GREEN 0x0000ff00
+#define FFBDAC_COLOR_GREEN_SHFT 8
+#define FFBDAC_COLOR_RED 0x000000ff
+#define FFBDAC_COLOR_RED_SHFT 0
+
+/* Cursor DAC register addresses. */
+#define FFBDAC_CUR_BITMAP_P0 0x000 /* Plane 0 cursor bitmap */
+#define FFBDAC_CUR_BITMAP_P1 0x080 /* Plane 1 cursor bitmap */
+#define FFBDAC_CUR_CTRL 0x100 /* Cursor control */
+#define FFBDAC_CUR_COLOR0 0x101 /* Cursor Color 0 */
+#define FFBDAC_CUR_COLOR1 0x102 /* Cursor Color 1 (bg) */
+#define FFBDAC_CUR_COLOR2 0x103 /* Cursor Color 2 (fg) */
+#define FFBDAC_CUR_POS 0x104 /* Active cursor position */
+
+/* Cursor control register.
+ * WARNING: Be careful, reverse logic on these bits.
+ */
+#define FFBDAC_CUR_CTRL_P0 0x00000001 /* Plane0 display disable */
+#define FFBDAC_CUR_CTRL_P1 0x00000002 /* Plane1 display disable */
+
+/* Active cursor position register */
+#define FFBDAC_CUR_POS_Y_SIGN 0x80000000 /* Sign of Y position */
+#define FFBDAC_CUR_POS_Y 0x0fff0000 /* Y position */
+#define FFBDAC_CUR_POS_X_SIGN 0x00008000 /* Sign of X position */
+#define FFBDAC_CUR_POS_X 0x00000fff /* X position */
+
+/* Configuration and Palette DAC register addresses. */
+#define FFBDAC_CFG_PPLLCTRL 0x0000 /* Pixel PLL Control */
+#define FFBDAC_CFG_GPLLCTRL 0x0001 /* General Purpose PLL Control */
+#define FFBDAC_CFG_PFCTRL 0x1000 /* Pixel Format Control */
+#define FFBDAC_CFG_UCTRL 0x1001 /* User Control */
+#define FFBDAC_CFG_CLUP_BASE 0x2000 /* Color Lookup Palette */
+#define FFBDAC_CFG_CLUP(entry) (FFBDAC_CFG_CLUP_BASE + ((entry) * 0x100))
+#define FFBDAC_PAC2_SOVWLUT0 0x3100 /* Shadow Overlay Window Lookup 0*/
+#define FFBDAC_PAC2_SOVWLUT1 0x3101 /* Shadow Overlay Window Lookup 1*/
+#define FFBDAC_PAC2_SOVWLUT2 0x3102 /* Shadow Overlay Window Lookup 2*/
+#define FFBDAC_PAC2_SOVWLUT3 0x3103 /* Shadow Overlay Window Lookup 3*/
+#define FFBDAC_PAC2_AOVWLUT0 0x3210 /* Active Overlay Window Lookup 0*/
+#define FFBDAC_PAC2_AOVWLUT1 0x3211 /* Active Overlay Window Lookup 1*/
+#define FFBDAC_PAC2_AOVWLUT2 0x3212 /* Active Overlay Window Lookup 2*/
+#define FFBDAC_PAC2_AOVWLUT3 0x3213 /* Active Overlay Window Lookup 3*/
+#define FFBDAC_CFG_WTCTRL 0x3150 /* Window Transfer Control */
+#define FFBDAC_CFG_TMCTRL 0x3151 /* Transparent Mask Control */
+#define FFBDAC_CFG_TCOLORKEY 0x3152 /* Transparent Color Key */
+#define FFBDAC_CFG_WAMASK 0x3153 /* Window Address Mask (PAC2 only) */
+#define FFBDAC_PAC1_SPWLUT_BASE 0x3100 /* Shadow Primary Window Lookups */
+#define FFBDAC_PAC1_SPWLUT(entry) (FFBDAC_PAC1_SPWLUT_BASE + (entry))
+#define FFBDAC_PAC1_APWLUT_BASE 0x3120 /* Active Primary Window Lookups */
+#define FFBDAC_PAC1_APWLUT(entry) (FFBDAC_PAC1_APWLUT_BASE + (entry))
+#define FFBDAC_PAC2_SPWLUT_BASE 0x3200 /* Shadow Primary Window Lookups */
+#define FFBDAC_PAC2_SPWLUT(entry) (FFBDAC_PAC2_SPWLUT_BASE + (entry))
+#define FFBDAC_PAC2_APWLUT_BASE 0x3240 /* Active Primary Window Lookups */
+#define FFBDAC_PAC2_APWLUT(entry) (FFBDAC_PAC2_APWLUT_BASE + (entry))
+#define FFBDAC_CFG_SANAL 0x5000 /* Signature Analysis Control */
+#define FFBDAC_CFG_DACCTRL 0x5001 /* DAC Control */
+#define FFBDAC_CFG_TGEN 0x6000 /* Timing Generator Control */
+#define FFBDAC_CFG_VBNP 0x6001 /* Vertical Blank Negation Point */
+#define FFBDAC_CFG_VBAP 0x6002 /* Vertical Blank Assertion Point*/
+#define FFBDAC_CFG_VSNP 0x6003 /* Vertical Sync Negation Point */
+#define FFBDAC_CFG_VSAP 0x6004 /* Vertical Sync Assertion Point */
+#define FFBDAC_CFG_HSNP 0x6005 /* Horz Serration Negation Point */
+#define FFBDAC_CFG_HBNP 0x6006 /* Horz Blank Negation Point */
+#define FFBDAC_CFG_HBAP 0x6007 /* Horz Blank Assertion Point */
+#define FFBDAC_CFG_HSYNCNP 0x6008 /* Horz Sync Negation Point */
+#define FFBDAC_CFG_HSYNCAP 0x6009 /* Horz Sync Assertion Point */
+#define FFBDAC_CFG_HSCENNP 0x600A /* Horz SCEN Negation Point */
+#define FFBDAC_CFG_HSCENAP 0x600B /* Horz SCEN Assertion Point */
+#define FFBDAC_CFG_EPNP 0x600C /* Eql'zing Pulse Negation Point */
+#define FFBDAC_CFG_EINP 0x600D /* Eql'zing Intvl Negation Point */
+#define FFBDAC_CFG_EIAP 0x600E /* Eql'zing Intvl Assertion Point*/
+#define FFBDAC_CFG_TGVC 0x600F /* Timing Generator Vert Counter */
+#define FFBDAC_CFG_TGHC 0x6010 /* Timing Generator Horz Counter */
+#define FFBDAC_CFG_DID 0x8000 /* Device Identification */
+#define FFBDAC_CFG_MPDATA 0x8001 /* Monitor Port Data */
+#define FFBDAC_CFG_MPSENSE 0x8002 /* Monitor Port Sense */
+
+/* Pixel PLL Control Register */
+#define FFBDAC_CFG_PPLLCTRL_M 0x0000007f /* PLL VCO Multiplicand */
+#define FFBDAC_CFG_PPLLCTRL_D 0x00000780 /* PLL VCO Divisor */
+#define FFBDAC_CFG_PPLLCTRL_PFD 0x00001800 /* Post VCO Frequency Divider */
+#define FFBDAC_CFG_PPLLCTRL_EN 0x00004000 /* Enable PLL as pixel clock src */
+
+/* General Purpose PLL Control Register */
+#define FFBDAC_CFG_GPLLCTRL_M 0x0000007f /* PLL VCO Multiplicand */
+#define FFBDAC_CFG_GPLLCTRL_D 0x00000780 /* PLL VCO Divisor */
+#define FFBDAC_CFG_GPLLCTRL_PFD 0x00001800 /* Post VCO Frequency Divider */
+#define FFBDAC_CFG_GPLLCTRL_EN 0x00004000 /* Enable PLL as Gen. Purpose clk*/
+
+/* Pixel Format Control Register */
+#define FFBDAC_CFG_PFCTRL_2_1 0x00000000 /* 2:1 pixel interleave format */
+#define FFBDAC_CFG_PFCTRL_4_1 0x00000001 /* 4:1 pixel interleave format */
+#define FFBDAC_CFG_PFCTRL_42_1 0x00000002 /* 4/2:1 pixel interleave format */
+#define FFBDAC_CFG_PFCTRL_82_1 0x00000003 /* 8/2:1 pixel interleave format */
+
+/* User Control Register */
+#define FFBDAC_UCTRL_IPDISAB 0x00000001 /* Disable input pullup resistors*/
+#define FFBDAC_UCTRL_ABLANK 0x00000002 /* Asynchronous Blank */
+#define FFBDAC_UCTRL_DBENAB 0x00000004 /* Double-Buffer Enable */
+#define FFBDAC_UCTRL_OVENAB 0x00000008 /* Overlay Enable */
+#define FFBDAC_UCTRL_WMODE 0x00000030 /* Window Mode */
+#define FFBDAC_UCTRL_WM_COMB 0x00000000 /* Window Mode = Combined */
+#define FFBDAC_UCTRL_WM_S4 0x00000010 /* Window Mode = Seperate_4 */
+#define FFBDAC_UCTRL_WM_S8 0x00000020 /* Window Mode = Seperate_8 */
+#define FFBDAC_UCTRL_WM_RESV 0x00000030 /* Window Mode = reserved */
+#define FFBDAC_UCTRL_MANREV 0x00000f00 /* 4-bit Manufacturing Revision */
+
+/* Overlay Window Lookup Registers (PAC2 only) */
+#define FFBDAC_CFG_OVWLUT_PSEL 0x0000000f /* Palette Section, Seperate_4 */
+#define FFBDAC_CFG_OVWLUT_PTBL 0x00000030 /* Palette Table */
+#define FFBDAC_CFG_OVWLUT_LKUP 0x00000100 /* 1 = Use palette, 0 = Bypass */
+#define FFBDAC_CFG_OVWLUT_OTYP 0x00000c00 /* Overlay Type */
+#define FFBDAC_CFG_OVWLUT_O_N 0x00000000 /* Overlay Type - None */
+#define FFBDAC_CFG_OVWLUT_O_T 0x00000400 /* Overlay Type - Transparent */
+#define FFBDAC_CFG_OVWLUT_O_O 0x00000800 /* Overlay Type - Opaque */
+#define FFBDAC_CFG_OVWLUT_O_R 0x00000c00 /* Overlay Type - Reserved */
+#define FFBDAC_CFG_OVWLUT_PCS 0x00003000 /* Psuedocolor Src */
+#define FFBDAC_CFG_OVWLUT_P_XO 0x00000000 /* Psuedocolor Src - XO[7:0] */
+#define FFBDAC_CFG_OVWLUT_P_R 0x00001000 /* Psuedocolor Src - R[7:0] */
+#define FFBDAC_CFG_OVWLUT_P_G 0x00002000 /* Psuedocolor Src - G[7:0] */
+#define FFBDAC_CFG_OVWLUT_P_B 0x00003000 /* Psuedocolor Src - B[7:0] */
+
+/* Window Transfer Control Register */
+#define FFBDAC_CFG_WTCTRL_DS 0x00000001 /* Device Status, 1 = Busy */
+#define FFBDAC_CFG_WTCTRL_TCMD 0x00000002 /* Transfer Command
+ * 1 = Transfer, 0 = No Action
+ */
+#define FFBDAC_CFG_WTCTRL_TE 0x00000004 /* Transfer Event
+ * 1 = Next Frame, 0 = Next Field
+ */
+#define FFBDAC_CFG_WTCTRL_DRD 0x00000008 /* Drawing Data
+ * 1 = Local Drawing Active
+ * 0 = Local Drawing Idle
+ */
+#define FFBDAC_CFG_WTCTRL_DRS 0x00000010 /* Drawing Status
+ * 1 = Network Drawing Active
+ * 0 = Network Drawing Idle
+ */
+
+/* Transparent Mask Control Register */
+#define FFBDAC_CFG_TMCTRL_OMSK 0x000000ff /* Overlay Mask */
+
+/* Transparent Color Key Register */
+#define FFBDAC_CFG_TCOLORKEY_K 0x000000ff /* Overlay Color Key */
+
+/* Window Address Mask Register (PAC2 only) */
+#define FFBDAC_CFG_WAMASK_PMSK 0x0000003f /* PWLUT select PMASK */
+#define FFBDAC_CFG_WAMASK_OMSK 0x00000300 /* OWLUT control OMASK */
+
+/* (non-Overlay) Window Lookup Table Registers, PAC1 format */
+#define FFBDAC_PAC1_WLUT_DB 0x00000020 /* 0 = Buffer A, 1 = Buffer B */
+#define FFBDAC_PAC1_WLUT_C 0x0000001c /* C: Color Model Selection */
+#define FFBDAC_PAC1_WLUT_C_8P 0x00000000 /* C: 8bpp Pseudocolor */
+#define FFBDAC_PAC1_WLUT_C_8LG 0x00000004 /* C: 8bpp Linear Grey */
+#define FFBDAC_PAC1_WLUT_C_8NG 0x00000008 /* C: 8bpp Non-Linear Grey */
+#define FFBDAC_PAC1_WLUT_C_24D 0x00000010 /* C: 24bpp Directcolor */
+#define FFBDAC_PAC1_WLUT_C_24LT 0x00000014 /* C: 24bpp Linear Truecolor */
+#define FFBDAC_PAC1_WLUT_C_24NT 0x00000018 /* C: 24bpp Non-Linear Truecolor */
+#define FFBDAC_PAC1_WLUT_PCS 0x00000003 /* Pseudocolor Src */
+#define FFBDAC_PAC1_WLUT_P_XO 0x00000000 /* Pseudocolor Src - XO[7:0] */
+#define FFBDAC_PAC1_WLUT_P_R 0x00000001 /* Pseudocolor Src - R[7:0] */
+#define FFBDAC_PAC1_WLUT_P_G 0x00000002 /* Pseudocolor Src - G[7:0] */
+#define FFBDAC_PAC1_WLUT_P_B 0x00000003 /* Pseudocolor Src - B[7:0] */
+
+/* (non-Overlay) Window Lookup Table Registers, PAC2 format */
+#define FFBDAC_PAC2_WLUT_PTBL 0x00000030 /* Palette Table Entry */
+#define FFBDAC_PAC2_WLUT_LKUP 0x00000100 /* 1 = Use palette, 0 = Bypass */
+#define FFBDAC_PAC2_WLUT_PCS 0x00003000 /* Pseudocolor Src */
+#define FFBDAC_PAC2_WLUT_P_XO 0x00000000 /* Pseudocolor Src - XO[7:0] */
+#define FFBDAC_PAC2_WLUT_P_R 0x00001000 /* Pseudocolor Src - R[7:0] */
+#define FFBDAC_PAC2_WLUT_P_G 0x00002000 /* Pseudocolor Src - G[7:0] */
+#define FFBDAC_PAC2_WLUT_P_B 0x00003000 /* Pseudocolor Src - B[7:0] */
+#define FFBDAC_PAC2_WLUT_DEPTH 0x00004000 /* 0 = Pseudocolor, 1 = Truecolor*/
+#define FFBDAC_PAC2_WLUT_DB 0x00008000 /* 0 = Buffer A, 1 = Buffer B */
+
+/* Signature Analysis Control Register */
+#define FFBDAC_CFG_SANAL_SRR 0x000000ff /* DAC Seed/Result for Red */
+#define FFBDAC_CFG_SANAL_SRG 0x0000ff00 /* DAC Seed/Result for Green */
+#define FFBDAC_CFG_SANAL_SRB 0x00ff0000 /* DAC Seed/Result for Blue */
+#define FFBDAC_CFG_SANAL_RQST 0x01000000 /* Signature Capture Request */
+#define FFBDAC_CFG_SANAL_BSY 0x02000000 /* Signature Analysis Busy */
+#define FFBDAC_CFG_SANAL_DSM 0x04000000 /* Data Strobe Mode
+ * 0 = Signature Analysis Mode
+ * 1 = Data Strobe Mode
+ */
+
+/* DAC Control Register */
+#define FFBDAC_CFG_DACCTRL_O2 0x00000003 /* Operand 2 Select
+ * 00 = Normal Operation
+ * 01 = Select 145mv Reference
+ * 10 = Select Blue DAC Output
+ * 11 = Reserved
+ */
+#define FFBDAC_CFG_DACCTRL_O1 0x0000000c /* Operand 1 Select
+ * 00 = Normal Operation
+ * 01 = Select Green DAC Output
+ * 10 = Select Red DAC Output
+ * 11 = Reserved
+ */
+#define FFBDAC_CFG_DACCTRL_CR 0x00000010 /* Comparator Result
+ * 0 = operand1 < operand2
+ * 1 = operand1 > operand2
+ */
+#define FFBDAC_CFG_DACCTRL_SGE 0x00000020 /* Sync-on-Green Enable */
+#define FFBDAC_CFG_DACCTRL_PE 0x00000040 /* Pedestal Enable */
+#define FFBDAC_CFG_DACCTRL_VPD 0x00000080 /* VSYNC* Pin Disable */
+#define FFBDAC_CFG_DACCTRL_SPB 0x00000100 /* Sync Polarity Bit
+ * 0 = VSYNC* and CSYNC* active low
+ * 1 = VSYNC* and CSYNC* active high
+ */
+
+/* Timing Generator Control Register */
+#define FFBDAC_CFG_TGEN_VIDE 0x00000001 /* Video Enable */
+#define FFBDAC_CFG_TGEN_TGE 0x00000002 /* Timing Generator Enable */
+#define FFBDAC_CFG_TGEN_HSD 0x00000004 /* HSYNC* Disabled */
+#define FFBDAC_CFG_TGEN_VSD 0x00000008 /* VSYNC* Disabled */
+#define FFBDAC_CFG_TGEN_EQD 0x00000010 /* Equalization Disabled */
+#define FFBDAC_CFG_TGEN_MM 0x00000020 /* 0 = Slave, 1 = Master */
+#define FFBDAC_CFG_TGEN_IM 0x00000040 /* 1 = Interlaced Mode */
+
+/* Device Identification Register, should be 0xA236E1AD for FFB bt497/bt498 */
+#define FFBDAC_CFG_DID_ONE 0x00000001 /* Always set */
+#define FFBDAC_CFG_DID_MANUF 0x00000ffe /* Manufacturer ID */
+#define FFBDAC_CFG_DID_PNUM 0x0ffff000 /* Device Part Number */
+#define FFBDAC_CFG_DID_REV 0xf0000000 /* Device Revision */
+
+/* Monitor Port Data Register */
+#define FFBDAC_CFG_MPDATA_SCL 0x00000001 /* SCL Data */
+#define FFBDAC_CFG_MPDATA_SDA 0x00000002 /* SDA Data */
+
+/* Monitor Port Sense Register */
+#define FFBDAC_CFG_MPSENSE_SCL 0x00000001 /* SCL Sense */
+#define FFBDAC_CFG_MPSENSE_SDA 0x00000002 /* SDA Sense */
+
+/* DAC register access shorthands. */
+#define DACCUR_READ(DAC, ADDR) ((DAC)->cur = (ADDR), (DAC)->curdata)
+#define DACCUR_WRITE(DAC, ADDR, VAL) ((DAC)->cur = (ADDR), (DAC)->curdata = (VAL))
+#define DACCFG_READ(DAC, ADDR) ((DAC)->cfg = (ADDR), (DAC)->cfgdata)
+#define DACCFG_WRITE(DAC, ADDR, VAL) ((DAC)->cfg = (ADDR), (DAC)->cfgdata = (VAL))
+
+typedef struct ffb_dac_hwstate {
+ unsigned int ppllctrl;
+ unsigned int gpllctrl;
+ unsigned int pfctrl;
+ unsigned int uctrl;
+ unsigned int clut[256 * 4]; /* One 256 entry clut on PAC1, 4 on PAC2 */
+ unsigned int ovluts[4]; /* Overlay WLUTS, PAC2 only */
+ unsigned int wtctrl;
+ unsigned int tmctrl;
+ unsigned int tcolorkey;
+ unsigned int wamask;
+ unsigned int pwluts[64];
+ unsigned int dacctrl;
+ unsigned int tgen;
+ unsigned int vbnp;
+ unsigned int vbap;
+ unsigned int vsnp;
+ unsigned int vsap;
+ unsigned int hsnp;
+ unsigned int hbnp;
+ unsigned int hbap;
+ unsigned int hsyncnp;
+ unsigned int hsyncap;
+ unsigned int hscennp;
+ unsigned int hscenap;
+ unsigned int epnp;
+ unsigned int einp;
+ unsigned int eiap;
+} ffb_dac_hwstate_t;
+
+typedef struct {
+ Bool InUse;
+
+ /* The following fields are undefined unless InUse is TRUE. */
+ int refcount;
+ Bool canshare;
+ unsigned int wlut_regval;
+ int buffer; /* 0 = Buffer A, 1 = Buffer B */
+ int depth; /* 8 or 32 bpp */
+ int greyscale; /* 1 = greyscale, 0 = color */
+ int linear; /* 1 = linear, 0 = non-linear */
+ int direct; /* 1 = 24bpp directcolor */
+ int channel; /* 0 = X, 1 = R, 2 = G, 3 = B */
+ int palette; /* Only PAC2 has multiple CLUTs */
+} ffb_wid_info_t;
+
+#define FFB_MAX_PWIDS 64
+typedef struct {
+ int num_wids;
+ int wid_shift; /* To get X channel value */
+ ffb_wid_info_t wid_pool[FFB_MAX_PWIDS];
+} ffb_wid_pool_t;
+
+typedef struct ffb_dac_info {
+ unsigned int flags;
+#define FFB_DAC_PAC1 0x00000001 /* Pacifica1 DAC, BT9068 */
+#define FFB_DAC_PAC2 0x00000002 /* Pacifica2 DAC, BT498 */
+#define FFB_DAC_ICURCTL 0x00000004 /* Inverted CUR_CTRL bits */
+
+ unsigned int kernel_wid;
+
+ /* These registers need to be modified when changing DAC
+ * timing state, so at init time we capture their values.
+ */
+ unsigned int ffbcfg0;
+ unsigned int ffbcfg2;
+ unsigned int ffb_passin_ctrl; /* FFB2+/AFB only */
+
+ ffb_dac_hwstate_t kern_dac_state;
+ ffb_dac_hwstate_t x_dac_state;
+
+ ffb_wid_pool_t wid_table;
+} ffb_dac_info_t;
+
+#endif /* _FFB_DAC_H */
diff --git a/src/ffb_dbe.c b/src/ffb_dbe.c
new file mode 100644
index 0000000..09395f7
--- /dev/null
+++ b/src/ffb_dbe.c
@@ -0,0 +1,902 @@
+/*
+ * Acceleration for the Creator and Creator3D framebuffer - Dbe Acceleration.
+ *
+ * Copyright (C) 2000 David S. Miller (davem@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_dbe.c,v 1.2 2003/02/11 03:19:02 dawes Exp $ */
+
+#define NEED_REPLIES
+#define NEED_EVENTS
+#include "X.h"
+#include "Xproto.h"
+#include "misc.h"
+#include "os.h"
+#include "windowstr.h"
+#include "scrnintstr.h"
+#include "pixmapstr.h"
+#include "extnsionst.h"
+#include "dixstruct.h"
+#include "resource.h"
+#include "opaque.h"
+#include "dbestruct.h"
+#include "regionstr.h"
+#include "gcstruct.h"
+#include "inputstr.h"
+
+#define PSZ 8
+#include "cfb.h"
+#undef PSZ
+#include "cfb32.h"
+
+#include "xf86_ansic.h"
+#include "xf86.h"
+
+#include "ffb.h"
+#include "ffb_fifo.h"
+#include "ffb_rcache.h"
+
+static int FFBDbePrivPrivGeneration = 0;
+static int FFBDbeWindowPrivPrivIndex = -1;
+static RESTYPE dbeDrawableResType;
+static RESTYPE dbeWindowPrivResType;
+static int dbeScreenPrivIndex = -1;
+static int dbeWindowPrivIndex = -1;
+
+#define FFB_DBE_WINDOW_PRIV_PRIV(pDbeWindowPriv) \
+ (((FFBDbeWindowPrivPrivIndex < 0) || (!pDbeWindowPriv)) ? \
+ NULL : \
+ ((FFBDbeWindowPrivPrivPtr) \
+ ((pDbeWindowPriv)->devPrivates[FFBDbeWindowPrivPrivIndex].ptr)))
+
+#define FFB_DBE_WINDOW_PRIV_PRIV_FROM_WINDOW(pWin) \
+ FFB_DBE_WINDOW_PRIV_PRIV(DBE_WINDOW_PRIV(pWin))
+
+typedef struct _FFBDbeWindowPrivPrivRec {
+ int HwAccelerated;
+ int HwCurrentBuf; /* 0 = buffer A, 1 = buffer B */
+
+ /* We need also what midbe would use in case we must
+ * revert to unaccelerated dbe.
+ */
+ PixmapPtr pBackBuffer;
+ PixmapPtr pFrontBuffer;
+
+ /* Back pointer to generic DBE layer window private. */
+ DbeWindowPrivPtr pDbeWindowPriv;
+} FFBDbeWindowPrivPrivRec, *FFBDbeWindowPrivPrivPtr;
+
+static Bool
+FFBDbeGetVisualInfo(ScreenPtr pScreen, XdbeScreenVisualInfo *pScrVisInfo)
+{
+ XdbeVisualInfo *visInfo;
+ DepthPtr pDepth;
+ int i, j, k, count;
+
+ /* XXX Should check for double-buffer presence. But even if
+ * XXX the double-buffer is not present we can still play
+ * XXX tricks with GetWindowPixmap in 8bpp mode, ie. double
+ * XXX buffer between the R and G planes of buffer A. -DaveM
+ */
+
+ /* Determine number of visuals for this screen. */
+ for (i = 0, count = 0; i < pScreen->numDepths; i++)
+ count += pScreen->allowedDepths[i].numVids;
+
+ /* Allocate an array of XdbeVisualInfo items. */
+ if (!(visInfo = (XdbeVisualInfo *)xalloc(count * sizeof(XdbeVisualInfo))))
+ return FALSE;
+
+ for (i = 0, k = 0; i < pScreen->numDepths; i++) {
+ /* For each depth of this screen, get visual information. */
+ pDepth = &pScreen->allowedDepths[i];
+ for (j = 0; j < pDepth->numVids; j++) {
+ /* For each visual for this depth of this screen, get visual ID
+ * and visual depth. For now, we will always return
+ * the same performance level for all visuals (0). A higher
+ * performance level value indicates higher performance.
+ */
+ visInfo[k].visual = pDepth->vids[j];
+ visInfo[k].depth = pDepth->depth;
+
+ /* XXX We should set this appropriately... -DaveM */
+ visInfo[k].perflevel = 0;
+ k++;
+ }
+ }
+
+ /* Record the number of visuals and point visual_depth to
+ * the array of visual info.
+ */
+ pScrVisInfo->count = count;
+ pScrVisInfo->visinfo = visInfo;
+
+ return TRUE;
+}
+
+static void
+FFBDbeUpdateWidPlane(WindowPtr pWin, GCPtr pGC)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN(pWin->drawable.pScreen);
+ CreatorPrivWinPtr pFfbPrivWin = CreatorGetWindowPrivate(pWin);
+ RegionPtr prgnClip;
+ BoxPtr pboxClipped, pboxClippedBase;
+ unsigned int fbc;
+ int numRects;
+ int x, y, w, h;
+
+ x = pWin->drawable.x;
+ y = pWin->drawable.y;
+ w = pWin->drawable.width;
+ h = pWin->drawable.height;
+
+ fbc = pFfbPrivWin->fbc_base;
+ fbc = (fbc & ~FFB_FBC_WB_MASK) | FFB_FBC_WB_AB;
+ fbc = (fbc & ~FFB_FBC_XE_MASK) | FFB_FBC_XE_ON;
+ fbc = (fbc & ~FFB_FBC_RGBE_MASK) | FFB_FBC_RGBE_OFF;
+
+ prgnClip = cfbGetCompositeClip(pGC);
+ numRects = REGION_NUM_RECTS (prgnClip);
+ pboxClippedBase = (BoxPtr) ALLOCATE_LOCAL(numRects * sizeof(BoxRec));
+ if (!pboxClippedBase)
+ return;
+
+ pboxClipped = pboxClippedBase;
+ {
+ int x1, y1, x2, y2, bx2, by2;
+ BoxRec box;
+ BoxPtr pextent;
+
+ pextent = REGION_EXTENTS(pGC->pScreen, prgnClip);
+ x1 = pextent->x1;
+ y1 = pextent->y1;
+ x2 = pextent->x2;
+ y2 = pextent->y2;
+
+ if ((box.x1 = x) < x1)
+ box.x1 = x1;
+
+ if ((box.y1 = y) < y1)
+ box.y1 = y1;
+
+ bx2 = (int) x + (int) w;
+ if (bx2 > x2)
+ bx2 = x2;
+ box.x2 = bx2;
+
+ by2 = (int) y + (int) h;
+ if (by2 > y2)
+ by2 = y2;
+ box.y2 = by2;
+
+ if ((box.x1 < box.x2) && (box.y1 < box.y2)) {
+ int n = REGION_NUM_RECTS (prgnClip);
+ BoxPtr pbox = REGION_RECTS(prgnClip);
+
+ /* Clip the rectangle to each box in the clip region
+ * this is logically equivalent to calling Intersect()
+ */
+ while(n--) {
+ pboxClipped->x1 = max(box.x1, pbox->x1);
+ pboxClipped->y1 = max(box.y1, pbox->y1);
+ pboxClipped->x2 = min(box.x2, pbox->x2);
+ pboxClipped->y2 = min(box.y2, pbox->y2);
+ pbox++;
+
+ /* see if clipping left anything */
+ if(pboxClipped->x1 < pboxClipped->x2 &&
+ pboxClipped->y1 < pboxClipped->y2)
+ pboxClipped++;
+ }
+ }
+ }
+
+ if (pboxClipped != pboxClippedBase) {
+ ffb_fbcPtr ffb = pFfb->regs;
+ int num = (pboxClipped - pboxClippedBase);
+
+ FFB_ATTR_RAW(pFfb,
+ FFB_PPC_APE_DISABLE | FFB_PPC_CS_CONST | FFB_PPC_XS_WID,
+ FFB_PPC_APE_MASK | FFB_PPC_CS_MASK | FFB_PPC_XS_MASK,
+ pGC->planemask,
+ ((FFB_ROP_EDIT_BIT | pGC->alu) | (FFB_ROP_NEW << 8)),
+ FFB_DRAWOP_RECTANGLE,
+ pGC->fgPixel,
+ fbc, pFfbPrivWin->wid);
+
+ pboxClipped = pboxClippedBase;
+ while (num--) {
+ int xx, yy, ww, hh;
+
+ xx = pboxClipped->x1;
+ yy = pboxClipped->y1;
+ ww = (pboxClipped->x2 - xx);
+ hh = (pboxClipped->y2 - yy);
+ FFBFifo(pFfb, 4);
+ FFB_WRITE64(&ffb->by, yy, xx);
+ FFB_WRITE64_2(&ffb->bh, hh, ww);
+ }
+ }
+
+ DEALLOCATE_LOCAL (pboxClippedBase);
+}
+
+static int
+FFBDbeAllocBackBufferName(WindowPtr pWin, XID bufId, int swapAction)
+{
+ ScreenPtr pScreen;
+ FFBPtr pFfb;
+ DbeWindowPrivPtr pDbeWindowPriv;
+ FFBDbeWindowPrivPrivPtr pDbeWindowPrivPriv;
+ DbeScreenPrivPtr pDbeScreenPriv;
+ GCPtr pGC;
+ xRectangle clearRect;
+
+ pScreen = pWin->drawable.pScreen;
+ pDbeWindowPriv = DBE_WINDOW_PRIV(pWin);
+ pFfb = GET_FFB_FROM_SCREEN(pScreen);
+
+ pDbeWindowPrivPriv = FFB_DBE_WINDOW_PRIV_PRIV(pDbeWindowPriv);
+ if (pDbeWindowPriv->nBufferIDs == 0) {
+ /* There is no buffer associated with the window.
+ * We have to create the window priv priv. Remember, the window
+ * priv was created at the DIX level, so all we need to do is
+ * create the priv priv and attach it to the priv.
+ */
+ pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen);
+
+ /* Setup the window priv priv. */
+ pDbeWindowPrivPriv->pDbeWindowPriv = pDbeWindowPriv;
+
+ if (!pFfb->NoAccel && pFfb->has_double_buffer) {
+ CreatorPrivWinPtr pFfbPrivWin;
+ unsigned int wid, fbc;
+
+ /* We just render directly into the hardware, all
+ * that is needed is to swap the rendering attributes
+ * and the WID settings during a swap.
+ */
+ if (!AddResource(bufId, dbeDrawableResType,
+ (pointer)&pWin->drawable)) {
+ /* Free the buffer and the drawable resource. */
+ FreeResource(bufId, RT_NONE);
+ return BadAlloc;
+ }
+
+ pFfbPrivWin = CreatorGetWindowPrivate(pWin);
+ wid = FFBWidUnshare(pFfb, pFfbPrivWin->wid);
+ if (wid == (unsigned int)-1)
+ return BadAlloc;
+
+ pFfbPrivWin->wid = wid;
+
+ /* Attach the priv priv to the priv. */
+ pDbeWindowPriv->devPrivates[FFBDbeWindowPrivPrivIndex].ptr =
+ (pointer)pDbeWindowPrivPriv;
+
+ /* Indicate we are doing hw acceleration. */
+ pDbeWindowPrivPriv->HwAccelerated = 1;
+
+ /* Start rendering into buffer B. */
+ pDbeWindowPrivPriv->HwCurrentBuf = 1;
+
+ /* No back/front temporary pixmaps. */
+ pDbeWindowPrivPriv->pFrontBuffer = NULL;
+ pDbeWindowPrivPriv->pBackBuffer = NULL;
+
+ /* Switch to writing into buffer B. */
+ fbc = pFfbPrivWin->fbc_base;
+ fbc &= ~(FFB_FBC_WB_MASK | FFB_FBC_RB_MASK);
+ fbc |= (FFB_FBC_WB_B | FFB_FBC_RB_B);
+ pFfbPrivWin->fbc_base = fbc;
+
+ pGC = GetScratchGC(pWin->drawable.depth, pWin->drawable.pScreen);
+
+ /* Fill X plane of front and back buffers. */
+ if ((*pDbeScreenPriv->SetupBackgroundPainter)(pWin, pGC)) {
+ ValidateGC(&pWin->drawable, pGC);
+ FFBDbeUpdateWidPlane(pWin, pGC);
+ }
+
+ /* Clear out buffer B. */
+ clearRect.x = clearRect.y = 0;
+ clearRect.width = pWin->drawable.width;
+ clearRect.height = pWin->drawable.height;
+ if ((*pDbeScreenPriv->SetupBackgroundPainter)(pWin, pGC)) {
+ ValidateGC(&pWin->drawable, pGC);
+ (*pGC->ops->PolyFillRect)(&pWin->drawable, pGC, 1, &clearRect);
+ }
+
+ FreeScratchGC(pGC);
+ } else {
+ /* Get a front pixmap. */
+ if (!(pDbeWindowPrivPriv->pFrontBuffer =
+ (*pScreen->CreatePixmap)(pScreen, pDbeWindowPriv->width,
+ pDbeWindowPriv->height,
+ pWin->drawable.depth)))
+ return BadAlloc;
+
+ /* Get a back pixmap. */
+ if (!(pDbeWindowPrivPriv->pBackBuffer =
+ (*pScreen->CreatePixmap)(pScreen, pDbeWindowPriv->width,
+ pDbeWindowPriv->height,
+ pWin->drawable.depth))) {
+ (*pScreen->DestroyPixmap)(pDbeWindowPrivPriv->pFrontBuffer);
+ return BadAlloc;
+ }
+
+
+ /* Make the back pixmap a DBE drawable resource. */
+ if (!AddResource(bufId, dbeDrawableResType,
+ (pointer)pDbeWindowPrivPriv->pBackBuffer)) {
+ /* Free the buffer and the drawable resource. */
+ FreeResource(bufId, RT_NONE);
+ return(BadAlloc);
+ }
+
+ /* Attach the priv priv to the priv. */
+ pDbeWindowPriv->devPrivates[FFBDbeWindowPrivPrivIndex].ptr =
+ (pointer)pDbeWindowPrivPriv;
+
+ /* Indicate we are doing this non-accelerated. */
+ pDbeWindowPrivPriv->HwAccelerated = 0;
+
+ /* Clear the back buffer. */
+ pGC = GetScratchGC(pWin->drawable.depth, pWin->drawable.pScreen);
+ if ((*pDbeScreenPriv->SetupBackgroundPainter)(pWin, pGC)) {
+ ValidateGC((DrawablePtr)pDbeWindowPrivPriv->pBackBuffer, pGC);
+ clearRect.x = clearRect.y = 0;
+ clearRect.width = pDbeWindowPrivPriv->pBackBuffer->drawable.width;
+ clearRect.height = pDbeWindowPrivPriv->pBackBuffer->drawable.height;
+ (*pGC->ops->PolyFillRect)(
+ (DrawablePtr)pDbeWindowPrivPriv->pBackBuffer, pGC, 1,
+ &clearRect);
+ }
+ FreeScratchGC(pGC);
+ }
+ } else {
+ pointer cookie;
+
+ /* A buffer is already associated with the window.
+ * Place the new buffer ID information at the head of the ID list.
+ */
+ if (pDbeWindowPrivPriv->HwAccelerated != 0)
+ cookie = (pointer)&pWin->drawable;
+ else
+ cookie = (pointer)pDbeWindowPrivPriv->pBackBuffer;
+
+ /* Associate the new ID with an existing pixmap. */
+ if (!AddResource(bufId, dbeDrawableResType, cookie))
+ return BadAlloc;
+ }
+
+ return Success;
+}
+
+static void
+FFBDbeAliasBuffers(DbeWindowPrivPtr pDbeWindowPriv)
+{
+ FFBDbeWindowPrivPrivPtr pDbeWindowPrivPriv =
+ FFB_DBE_WINDOW_PRIV_PRIV(pDbeWindowPriv);
+ pointer cookie;
+ int i;
+
+ if (pDbeWindowPrivPriv->HwAccelerated != 0)
+ cookie = (pointer) &pDbeWindowPriv->pWindow->drawable;
+ else
+ cookie = (pointer) pDbeWindowPrivPriv->pBackBuffer;
+
+ for (i = 0; i < pDbeWindowPriv->nBufferIDs; i++)
+ ChangeResourceValue(pDbeWindowPriv->IDs[i], dbeDrawableResType, cookie);
+}
+
+static int
+FFBDbeSwapBuffers(ClientPtr client, int *pNumWindows, DbeSwapInfoPtr swapInfo)
+{
+ FFBDbeWindowPrivPrivPtr pDbeWindowPrivPriv;
+ DbeScreenPrivPtr pDbeScreenPriv;
+ PixmapPtr pTmpBuffer;
+ xRectangle clearRect;
+ WindowPtr pWin;
+ GCPtr pGC;
+
+ pWin = swapInfo[0].pWindow;
+ pDbeScreenPriv = DBE_SCREEN_PRIV_FROM_WINDOW(pWin);
+ pDbeWindowPrivPriv = FFB_DBE_WINDOW_PRIV_PRIV_FROM_WINDOW(pWin);
+ pGC = GetScratchGC(pWin->drawable.depth, pWin->drawable.pScreen);
+
+ if (pDbeWindowPrivPriv->HwAccelerated != 0) {
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN(pWin->drawable.pScreen);
+ CreatorPrivWinPtr pFfbPrivWin = CreatorGetWindowPrivate(pWin);
+ unsigned int fbc;
+ int visible;
+
+ /* Unfortunately, this is necessary for correctness. */
+ FFBWait(pFfb, pFfb->regs);
+
+ /* Flip front/back in the WID. */
+ visible = 0;
+ if (pWin->viewable &&
+ pWin->visibility != VisibilityFullyObscured)
+ visible = 1;
+ FFBWidChangeBuffer(pFfb, pFfbPrivWin->wid, visible);
+
+ /* Indicate where we are rendering now. */
+ pDbeWindowPrivPriv->HwCurrentBuf ^= 1;
+
+ /* Update framebuffer controls. */
+ fbc = pFfbPrivWin->fbc_base;
+ fbc &= ~(FFB_FBC_WB_MASK | FFB_FBC_RB_MASK);
+ if (pDbeWindowPrivPriv->HwCurrentBuf == 0)
+ fbc |= FFB_FBC_WB_A | FFB_FBC_RB_A;
+ else
+ fbc |= FFB_FBC_WB_B | FFB_FBC_RB_B;
+
+ /* For XdbeUndefined we do not have to do anything.
+ * This is true for XdbeUntouched as well because we
+ * do in fact retain the unobscured contents of the
+ * front buffer while it is being displayed, thus now
+ * when it has become the back buffer it is still holding
+ * those contents.
+ *
+ * The XdbeUntouched case is important because most apps
+ * using dbe use this type of swap.
+ */
+
+ if (swapInfo[0].swapAction == XdbeCopied) {
+ unsigned int fbc_front_to_back;
+
+ /* Do a GCOPY, front to back. */
+ fbc_front_to_back = fbc & ~FFB_FBC_RB_MASK;
+ if (pDbeWindowPrivPriv->HwCurrentBuf == 0)
+ fbc_front_to_back |= FFB_FBC_RB_B;
+ else
+ fbc_front_to_back |= FFB_FBC_RB_A;
+
+ pFfbPrivWin->fbc_base = fbc_front_to_back;
+ ValidateGC(&pWin->drawable, pGC);
+ (*pGC->ops->CopyArea)(&pWin->drawable,
+ &pWin->drawable,
+ pGC,
+ 0, 0,
+ pWin->drawable.width,
+ pWin->drawable.height,
+ 0, 0);
+ } else if (swapInfo[0].swapAction == XdbeBackground) {
+ if ((*pDbeScreenPriv->SetupBackgroundPainter)(pWin, pGC)) {
+ ValidateGC(&pWin->drawable, pGC);
+ clearRect.x = 0;
+ clearRect.y = 0;
+ clearRect.width = pWin->drawable.width;
+ clearRect.height = pWin->drawable.height;
+ (*pGC->ops->PolyFillRect)(&pWin->drawable, pGC,
+ 1, &clearRect);
+ }
+ }
+
+ /* Ok, now render with these fb controls. */
+ pFfbPrivWin->fbc_base = fbc;
+ } else {
+ if (swapInfo[0].swapAction == XdbeUntouched) {
+ ValidateGC((DrawablePtr)pDbeWindowPrivPriv->pFrontBuffer, pGC);
+ (*pGC->ops->CopyArea)((DrawablePtr)pWin,
+ (DrawablePtr)pDbeWindowPrivPriv->pFrontBuffer,
+ pGC, 0, 0, pWin->drawable.width,
+ pWin->drawable.height, 0, 0);
+ }
+
+ ValidateGC((DrawablePtr)pWin, pGC);
+ (*pGC->ops->CopyArea)((DrawablePtr)pDbeWindowPrivPriv->pBackBuffer,
+ (DrawablePtr)pWin, pGC, 0, 0,
+ pWin->drawable.width, pWin->drawable.height,
+ 0, 0);
+
+ if (swapInfo[0].swapAction == XdbeBackground) {
+ if ((*pDbeScreenPriv->SetupBackgroundPainter)(pWin, pGC)) {
+ ValidateGC((DrawablePtr)pDbeWindowPrivPriv->pBackBuffer,
+ pGC);
+ clearRect.x = 0;
+ clearRect.y = 0;
+ clearRect.width =
+ pDbeWindowPrivPriv->pBackBuffer->drawable.width;
+ clearRect.height =
+ pDbeWindowPrivPriv->pBackBuffer->drawable.height;
+ (*pGC->ops->PolyFillRect)(
+ (DrawablePtr)pDbeWindowPrivPriv->pBackBuffer,
+ pGC, 1, &clearRect);
+ }
+ } else if (swapInfo[0].swapAction == XdbeUntouched) {
+ /* Swap pixmap pointers. */
+ pTmpBuffer = pDbeWindowPrivPriv->pBackBuffer;
+ pDbeWindowPrivPriv->pBackBuffer =
+ pDbeWindowPrivPriv->pFrontBuffer;
+ pDbeWindowPrivPriv->pFrontBuffer = pTmpBuffer;
+ FFBDbeAliasBuffers(pDbeWindowPrivPriv->pDbeWindowPriv);
+ }
+ }
+
+ /* Remove the swapped window from the swap information array and decrement
+ * pNumWindows to indicate to the DIX level how many windows were actually
+ * swapped.
+ */
+ if (*pNumWindows > 1) {
+ /* We were told to swap more than one window, but we only swapped the
+ * first one. Remove the first window in the list by moving the last
+ * window to the beginning.
+ */
+ swapInfo[0].pWindow = swapInfo[*pNumWindows - 1].pWindow;
+ swapInfo[0].swapAction = swapInfo[*pNumWindows - 1].swapAction;
+
+ /* Clear the last window information just to be safe. */
+ swapInfo[*pNumWindows - 1].pWindow = (WindowPtr)NULL;
+ swapInfo[*pNumWindows - 1].swapAction = 0;
+ } else {
+ /* Clear the window information just to be safe. */
+ swapInfo[0].pWindow = (WindowPtr)NULL;
+ swapInfo[0].swapAction = 0;
+ }
+
+ (*pNumWindows)--;
+
+ FreeScratchGC(pGC);
+
+ return Success;
+}
+
+static void
+FFBDbeWinPrivDelete(DbeWindowPrivPtr pDbeWindowPriv, XID bufId)
+{
+ WindowPtr pWin = pDbeWindowPriv->pWindow;
+ FFBDbeWindowPrivPrivPtr pDbeWindowPrivPriv;
+
+ if (pDbeWindowPriv->nBufferIDs != 0) {
+ /* We still have at least one more buffer ID associated with this
+ * window.
+ */
+ return;
+ }
+
+ /* We have no more buffer IDs associated with this window. We need to
+ * free some stuff.
+ */
+ pDbeWindowPrivPriv = FFB_DBE_WINDOW_PRIV_PRIV(pDbeWindowPriv);
+
+ /* If we were accelerating we need to restore the framebuffer
+ * attributes. We need to also free up the Dbe WID and go
+ * back to using the shared one.
+ */
+ if (pDbeWindowPrivPriv->HwAccelerated != 0) {
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN(pWin->drawable.pScreen);
+ CreatorPrivWinPtr pFfbPrivWin = CreatorGetWindowPrivate(pWin);
+ xRectangle clearRect;
+ unsigned int fbc;
+ GCPtr pGC;
+
+ pFfbPrivWin->wid = FFBWidReshare(pFfb, pFfbPrivWin->wid);
+
+ /* Go back to using buffer A. */
+ fbc = pFfbPrivWin->fbc_base;
+ fbc &= ~(FFB_FBC_WB_MASK | FFB_FBC_RB_MASK);
+ fbc |= FFB_FBC_WB_A | FFB_FBC_RB_A;
+
+ /* Now fixup the WID channel. */
+ pFfbPrivWin->fbc_base =
+ (fbc & ~FFB_FBC_RGBE_MASK) | FFB_FBC_RGBE_OFF;
+
+ pGC = GetScratchGC(pWin->drawable.depth, pWin->drawable.pScreen);
+ clearRect.x = clearRect.y = 0;
+ clearRect.width = pWin->drawable.width;
+ clearRect.height = pWin->drawable.height;
+ ValidateGC(&pWin->drawable, pGC);
+ FFBDbeUpdateWidPlane(pWin, pGC);
+ (*pGC->ops->PolyFillRect)(&pWin->drawable, pGC, 1, &clearRect);
+ FreeScratchGC(pGC);
+
+ pFfbPrivWin->fbc_base = fbc;
+ } else {
+ /* Destroy the front and back pixmaps. */
+ if (pDbeWindowPrivPriv->pFrontBuffer)
+ (*pDbeWindowPriv->pWindow->drawable.pScreen->DestroyPixmap)(
+ pDbeWindowPrivPriv->pFrontBuffer);
+ if (pDbeWindowPrivPriv->pBackBuffer)
+ (*pDbeWindowPriv->pWindow->drawable.pScreen->DestroyPixmap)(
+ pDbeWindowPrivPriv->pBackBuffer);
+ }
+}
+
+static Bool
+FFBDbePositionWindow(WindowPtr pWin, int x, int y)
+{
+ ScreenPtr pScreen;
+ DbeScreenPrivPtr pDbeScreenPriv;
+ DbeWindowPrivPtr pDbeWindowPriv;
+ FFBDbeWindowPrivPrivPtr pDbeWindowPrivPriv;
+ int width, height;
+ int dx, dy, dw, dh;
+ int sourcex, sourcey;
+ int destx, desty;
+ int savewidth, saveheight;
+ PixmapPtr pFrontBuffer;
+ PixmapPtr pBackBuffer;
+ Bool clear;
+ GCPtr pGC;
+ xRectangle clearRect;
+ Bool ret;
+
+ /* 1. Unwrap the member routine. */
+ pScreen = pWin->drawable.pScreen;
+ pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen);
+ pScreen->PositionWindow = pDbeScreenPriv->PositionWindow;
+
+ /* 2. Do any work necessary before the member routine is called.
+ *
+ * In this case we do not need to do anything.
+ */
+
+ /* 3. Call the member routine, saving its result if necessary. */
+ ret = (*pScreen->PositionWindow)(pWin, x, y);
+
+ /* 4. Rewrap the member routine, restoring the wrapper value first in case
+ * the wrapper (or something that it wrapped) change this value.
+ */
+ pDbeScreenPriv->PositionWindow = pScreen->PositionWindow;
+ pScreen->PositionWindow = FFBDbePositionWindow;
+
+ /* 5. Do any work necessary after the member routine has been called. */
+ if (!(pDbeWindowPriv = DBE_WINDOW_PRIV(pWin)))
+ return ret;
+
+ if (pDbeWindowPriv->width == pWin->drawable.width &&
+ pDbeWindowPriv->height == pWin->drawable.height)
+ return ret;
+
+ width = pWin->drawable.width;
+ height = pWin->drawable.height;
+
+ dx = pWin->drawable.x - pDbeWindowPriv->x;
+ dy = pWin->drawable.y - pDbeWindowPriv->y;
+ dw = width - pDbeWindowPriv->width;
+ dh = height - pDbeWindowPriv->height;
+
+ GravityTranslate (0, 0, -dx, -dy, dw, dh, pWin->bitGravity, &destx, &desty);
+
+ clear = ((pDbeWindowPriv->width < (unsigned short)width ) ||
+ (pDbeWindowPriv->height < (unsigned short)height) ||
+ (pWin->bitGravity == ForgetGravity));
+
+ sourcex = 0;
+ sourcey = 0;
+ savewidth = pDbeWindowPriv->width;
+ saveheight = pDbeWindowPriv->height;
+
+ /* Clip rectangle to source and destination. */
+ if (destx < 0) {
+ savewidth += destx;
+ sourcex -= destx;
+ destx = 0;
+ }
+
+ if (destx + savewidth > width)
+ savewidth = width - destx;
+
+ if (desty < 0) {
+ saveheight += desty;
+ sourcey -= desty;
+ desty = 0;
+ }
+
+ if (desty + saveheight > height)
+ saveheight = height - desty;
+
+ pDbeWindowPriv->width = width;
+ pDbeWindowPriv->height = height;
+ pDbeWindowPriv->x = pWin->drawable.x;
+ pDbeWindowPriv->y = pWin->drawable.y;
+
+ pGC = GetScratchGC (pWin->drawable.depth, pScreen);
+
+ if (clear) {
+ if ((*pDbeScreenPriv->SetupBackgroundPainter)(pWin, pGC)) {
+ clearRect.x = 0;
+ clearRect.y = 0;
+ clearRect.width = width;
+ clearRect.height = height;
+ } else {
+ clear = FALSE;
+ }
+ }
+
+ pDbeWindowPrivPriv = FFB_DBE_WINDOW_PRIV_PRIV(pDbeWindowPriv);
+ if (pDbeWindowPrivPriv->HwAccelerated != 0) {
+ /* If we're hw accelerating, things are much easier. */
+ ValidateGC(&pWin->drawable, pGC);
+ FFBDbeUpdateWidPlane(pWin, pGC);
+ if (clear) {
+ CreatorPrivWinPtr pFfbPrivWin = CreatorGetWindowPrivate(pWin);
+ unsigned int fbc, orig_fbc;
+
+ ValidateGC(&pWin->drawable, pGC);
+ (*pGC->ops->PolyFillRect)(&pWin->drawable, pGC,
+ 1, &clearRect);
+
+ orig_fbc = fbc = pFfbPrivWin->fbc_base;
+ fbc &= ~(FFB_FBC_WB_MASK);
+ if (pDbeWindowPrivPriv->HwCurrentBuf == 0)
+ fbc |= FFB_FBC_WB_B;
+ else
+ fbc |= FFB_FBC_WB_A;
+
+ pFfbPrivWin->fbc_base = fbc;
+
+ if ((*pDbeScreenPriv->SetupBackgroundPainter)(pWin, pGC)) {
+ ValidateGC(&pWin->drawable, pGC);
+ clearRect.x = 0;
+ clearRect.y = 0;
+ clearRect.width = width;
+ clearRect.height = height;
+ (*pGC->ops->PolyFillRect)(&pWin->drawable, pGC,
+ 1, &clearRect);
+ }
+
+ pFfbPrivWin->fbc_base = orig_fbc;
+ }
+
+ FreeScratchGC(pGC);
+ } else {
+ /* Create DBE buffer pixmaps equal to size of resized window. */
+ pFrontBuffer = (*pScreen->CreatePixmap)(pScreen, width, height,
+ pWin->drawable.depth);
+
+ pBackBuffer = (*pScreen->CreatePixmap)(pScreen, width, height,
+ pWin->drawable.depth);
+
+ if (!pFrontBuffer || !pBackBuffer) {
+ /* We failed at creating 1 or 2 of the pixmaps. */
+ if (pFrontBuffer)
+ (*pScreen->DestroyPixmap)(pFrontBuffer);
+ if (pBackBuffer)
+ (*pScreen->DestroyPixmap)(pBackBuffer);
+
+ /* Destroy all buffers for this window. */
+ while (pDbeWindowPriv) {
+ /* DbeWindowPrivDelete() will free the window private
+ * if there no more buffer IDs associated with this
+ * window.
+ */
+ FreeResource(pDbeWindowPriv->IDs[0], RT_NONE);
+ pDbeWindowPriv = DBE_WINDOW_PRIV(pWin);
+ }
+ FreeScratchGC(pGC);
+ return FALSE;
+ } else {
+ /* Clear out the new DBE buffer pixmaps. */
+ ValidateGC((DrawablePtr)pFrontBuffer, pGC);
+
+ /* I suppose this could avoid quite a bit of work if
+ * it computed the minimal area required.
+ */
+ if (clear) {
+ (*pGC->ops->PolyFillRect)((DrawablePtr)pFrontBuffer, pGC, 1,
+ &clearRect);
+ (*pGC->ops->PolyFillRect)((DrawablePtr)pBackBuffer , pGC, 1,
+ &clearRect);
+ }
+
+ /* Copy the contents of the old DBE pixmaps to the new pixmaps. */
+ if (pWin->bitGravity != ForgetGravity) {
+ (*pGC->ops->CopyArea)((DrawablePtr)pDbeWindowPrivPriv->pFrontBuffer,
+ (DrawablePtr)pFrontBuffer, pGC,
+ sourcex, sourcey,
+ savewidth, saveheight,
+ destx, desty);
+ (*pGC->ops->CopyArea)((DrawablePtr)pDbeWindowPrivPriv->pBackBuffer,
+ (DrawablePtr)pBackBuffer, pGC,
+ sourcex, sourcey,
+ savewidth, saveheight, destx, desty);
+ }
+
+ /* Destroy the old pixmaps, and point the DBE window priv to the new
+ * pixmaps.
+ */
+ (*pScreen->DestroyPixmap)(pDbeWindowPrivPriv->pFrontBuffer);
+ (*pScreen->DestroyPixmap)(pDbeWindowPrivPriv->pBackBuffer);
+
+ pDbeWindowPrivPriv->pFrontBuffer = pFrontBuffer;
+ pDbeWindowPrivPriv->pBackBuffer = pBackBuffer;
+
+ /* Make sure all XID are associated with the new back pixmap. */
+ FFBDbeAliasBuffers(pDbeWindowPriv);
+
+ FreeScratchGC(pGC);
+ }
+ }
+
+ return ret;
+}
+
+static void
+FFBDbeResetProc(ScreenPtr pScreen)
+{
+ DbeScreenPrivPtr pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen);
+
+ /* Unwrap wrappers */
+ pScreen->PositionWindow = pDbeScreenPriv->PositionWindow;
+}
+
+static Bool
+FFBDbeInit(ScreenPtr pScreen, DbeScreenPrivPtr pDbeScreenPriv)
+{
+ ScrnInfoPtr pScrn;
+ FFBPtr pFfb;
+
+ pScrn = xf86Screens[pScreen->myNum];
+ pFfb = GET_FFB_FROM_SCRN(pScrn);
+ xf86Msg(X_INFO, "%s: Setting up double-buffer acceleration.\n",
+ pFfb->psdp->device);
+
+ /* Copy resource types created by DIX */
+ dbeDrawableResType = pDbeScreenPriv->dbeDrawableResType;
+ dbeWindowPrivResType = pDbeScreenPriv->dbeWindowPrivResType;
+
+ /* Copy private indices created by DIX */
+ dbeScreenPrivIndex = pDbeScreenPriv->dbeScreenPrivIndex;
+ dbeWindowPrivIndex = pDbeScreenPriv->dbeWindowPrivIndex;
+
+ /* Reset the window priv privs if generations do not match. */
+ if (FFBDbePrivPrivGeneration != serverGeneration) {
+ /* Allocate the window priv priv. */
+ FFBDbeWindowPrivPrivIndex = (*pDbeScreenPriv->AllocWinPrivPrivIndex)();
+
+ if (!(*pDbeScreenPriv->AllocWinPrivPriv)(pScreen,
+ FFBDbeWindowPrivPrivIndex,
+ sizeof(FFBDbeWindowPrivPrivRec)))
+ return FALSE;
+
+ /* Make sure we only do this code once. */
+ FFBDbePrivPrivGeneration = serverGeneration;
+ }
+
+ /* Wrap functions. */
+ pDbeScreenPriv->PositionWindow = pScreen->PositionWindow;
+ pScreen->PositionWindow = FFBDbePositionWindow;
+
+ /* Initialize the per-screen DBE function pointers. */
+ pDbeScreenPriv->GetVisualInfo = FFBDbeGetVisualInfo;
+ pDbeScreenPriv->AllocBackBufferName = FFBDbeAllocBackBufferName;
+ pDbeScreenPriv->SwapBuffers = FFBDbeSwapBuffers;
+ pDbeScreenPriv->BeginIdiom = 0;
+ pDbeScreenPriv->EndIdiom = 0;
+ pDbeScreenPriv->ResetProc = FFBDbeResetProc;
+ pDbeScreenPriv->WinPrivDelete = FFBDbeWinPrivDelete;
+
+ /* The FFB implementation doesn't need buffer validation. */
+ pDbeScreenPriv->ValidateBuffer = (void (*)())NoopDDA;
+
+ return TRUE;
+}
+
+extern void DbeRegisterFunction(ScreenPtr pScreen, Bool (*funct)(ScreenPtr, DbeScreenPrivPtr));
+
+Bool
+FFBDbePreInit(ScreenPtr pScreen)
+{
+ DbeRegisterFunction(pScreen, FFBDbeInit);
+ return TRUE;
+}
diff --git a/src/ffb_ddc.c b/src/ffb_ddc.c
new file mode 100644
index 0000000..6d1a312
--- /dev/null
+++ b/src/ffb_ddc.c
@@ -0,0 +1,195 @@
+/*
+ * Acceleration for the Creator and Creator3D framebuffer - DDC support.
+ *
+ * Copyright (C) 2000 David S. Miller (davem@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_ddc.c,v 1.1 2000/05/23 04:47:44 dawes Exp $ */
+
+#include "ffb.h"
+
+#include "ffb_dac.h"
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+
+#include "xf86DDC.h"
+
+/* XXX This needs a lot more work. Only an attempt at the PAC2 version
+ * XXX is below, and that is untested. The BT498 manual is unclear about
+ * XXX several details and I must figure them out by trial and error.
+ */
+
+/* Wait for the next VSYNC. */
+static void
+WaitForVSYNC(ffb_dacPtr dac)
+{
+ unsigned int vsap = DACCFG_READ(dac, FFBDAC_CFG_VSAP);
+ unsigned int vcnt;
+
+ vcnt = DACCFG_READ(dac, FFBDAC_CFG_TGVC);
+ while (vcnt > vsap)
+ vcnt = DACCFG_READ(dac, FFBDAC_CFG_TGVC);
+ while (vcnt <= vsap)
+ vcnt = DACCFG_READ(dac, FFBDAC_CFG_TGVC);
+
+}
+
+/* The manual seems to imply this is needed, but it's really clumsy
+ * so we can test if it really is a requirement with this.
+ */
+#define MDATA_NEEDS_BLANK
+
+/* DDC1/DDC2 support */
+static unsigned int
+FFBDacDdc1Read(ScrnInfoPtr pScrn)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
+ ffb_dacPtr dac = pFfb->dac;
+ unsigned int val;
+#ifdef MDATA_NEEDS_BLANK
+ unsigned int uctrl;
+#endif
+
+#ifdef MDATA_NEEDS_BLANK
+ /* Force a blank of the screen. */
+ uctrl = DACCFG_READ(dac, FFBDAC_CFG_UCTRL);
+ DACCFG_WRITE(dac, FFBDAC_CFG_UCTRL,
+ (uctrl | FFBDAC_UCTRL_ABLANK));
+#endif
+
+ /* Tristate SCL pin. */
+ DACCFG_WRITE(dac, FFBDAC_CFG_MPDATA,
+ FFBDAC_CFG_MPDATA_SCL);
+
+ /* Pause until VSYNC is hit. */
+ WaitForVSYNC(dac);
+
+ /* Read the sense line to see what the monitor is driving
+ * it at.
+ */
+ val = DACCFG_READ(dac, FFBDAC_CFG_MPSENSE);
+ val = (val & FFBDAC_CFG_MPSENSE_SCL) ? 1 : 0;
+
+ /* Stop tristating the SCL pin. */
+ DACCFG_WRITE(dac, FFBDAC_CFG_MPDATA, 0);
+
+#ifdef MDATA_NEEDS_BLANK
+ /* Restore UCTRL to unblank the screen. */
+ DACCFG_WRITE(dac, FFBDAC_CFG_UCTRL, uctrl);
+#endif
+
+ /* Return the result and we're done. */
+ return val;
+}
+
+static void
+FFBI2CGetBits(I2CBusPtr b, int *clock, int *data)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCRN(xf86Screens[b->scrnIndex]);
+ ffb_dacPtr dac = pFfb->dac;
+ unsigned int val;
+#ifdef MDATA_NEEDS_BLANK
+ unsigned int uctrl;
+#endif
+
+#ifdef MDATA_NEEDS_BLANK
+ /* Force a blank of the screen. */
+ uctrl = DACCFG_READ(dac, FFBDAC_CFG_UCTRL);
+ DACCFG_WRITE(dac, FFBDAC_CFG_UCTRL,
+ (uctrl | FFBDAC_UCTRL_ABLANK));
+#endif
+
+ /* Tristate SCL+SDA pins. */
+ DACCFG_WRITE(dac, FFBDAC_CFG_MPDATA,
+ (FFBDAC_CFG_MPDATA_SCL | FFBDAC_CFG_MPDATA_SDA));
+
+ /* Read the sense line to see what the monitor is driving
+ * them at.
+ */
+ val = DACCFG_READ(dac, FFBDAC_CFG_MPSENSE);
+ *clock = (val & FFBDAC_CFG_MPSENSE_SCL) ? 1 : 0;
+ *data = (val & FFBDAC_CFG_MPSENSE_SDA) ? 1 : 0;
+
+ /* Stop tristating the SCL pin. */
+ DACCFG_WRITE(dac, FFBDAC_CFG_MPDATA, 0);
+
+#ifdef MDATA_NEEDS_BLANK
+ /* Restore UCTRL to unblank the screen. */
+ DACCFG_WRITE(dac, FFBDAC_CFG_UCTRL, uctrl);
+#endif
+}
+
+static void
+FFBI2CPutBits(I2CBusPtr b, int clock, int data)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCRN(xf86Screens[b->scrnIndex]);
+ ffb_dacPtr dac = pFfb->dac;
+ unsigned int val;
+#ifdef MDATA_NEEDS_BLANK
+ unsigned int uctrl;
+#endif
+
+ val = 0;
+ if (clock)
+ val |= FFBDAC_CFG_MPDATA_SCL;
+ if (data)
+ val |= FFBDAC_CFG_MPDATA_SDA;
+
+#ifdef MDATA_NEEDS_BLANK
+ /* Force a blank of the screen. */
+ uctrl = DACCFG_READ(dac, FFBDAC_CFG_UCTRL);
+ DACCFG_WRITE(dac, FFBDAC_CFG_UCTRL,
+ (uctrl | FFBDAC_UCTRL_ABLANK));
+#endif
+
+ /* Tristate requested pins. */
+ DACCFG_WRITE(dac, FFBDAC_CFG_MPDATA, val);
+
+#ifdef MDATA_NEEDS_BLANK
+ /* Restore UCTRL to unblank the screen. */
+ DACCFG_WRITE(dac, FFBDAC_CFG_UCTRL, uctrl);
+#endif
+}
+
+Bool
+FFBi2cInit(ScrnInfoPtr pScrn)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
+ I2CBusPtr I2CPtr;
+
+ I2CPtr = xf86CreateI2CBusRec();
+ if (!I2CPtr)
+ return FALSE;
+
+ pFfb->I2C = I2CPtr;
+
+ I2CPtr->BusName = "DDC";
+ I2CPtr->scrnIndex = pScrn->scrnIndex;
+ I2CPtr->I2CPutBits = FFBI2CPutBits;
+ I2CPtr->I2CGetBits = FFBI2CGetBits;
+ I2CPtr->AcknTimeout = 5;
+
+ if (!xf86I2CBusInit(I2CPtr))
+ return FALSE;
+
+ return TRUE;
+}
diff --git a/src/ffb_dga.c b/src/ffb_dga.c
new file mode 100644
index 0000000..3ba43df
--- /dev/null
+++ b/src/ffb_dga.c
@@ -0,0 +1,280 @@
+/*
+ * Acceleration for the Creator and Creator3D framebuffer - DGA support.
+ *
+ * Copyright (C) 2000 David S. Miller (davem@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_dga.c,v 1.2 2000/10/17 16:53:17 tsi Exp $ */
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+#include "dgaproc.h"
+
+#include "ffb.h"
+#include "ffb_regs.h"
+#include "ffb_rcache.h"
+#include "ffb_fifo.h"
+#include "ffb_stip.h"
+#include "ffb_loops.h"
+
+static Bool FFB_OpenFramebuffer(ScrnInfoPtr pScrn, char **name, unsigned char **mem,
+ int *size, int *offset, int *extra);
+static void FFB_CloseFramebuffer(ScrnInfoPtr pScrn);
+static Bool FFB_SetMode(ScrnInfoPtr pScrn, DGAModePtr pMode);
+static void FFB_SetViewport(ScrnInfoPtr pScrn, int x, int y, int flags);
+static int FFB_GetViewport(ScrnInfoPtr pScrn);
+static void FFB_Flush(ScrnInfoPtr pScrn);
+
+/* Have to disable all this stuff for now until I figure out where
+ * we should get the WID values from... ho hum... -DaveM
+ */
+#if 0
+static void FFB_FillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h, unsigned long color);
+
+#ifdef USE_VIS
+static void FFB_BlitRect(ScrnInfoPtr pScrn, int srcx, int srcy, int w, int h,
+ int dstx, int dsty);
+#else
+#define FFB_BlitRect NULL
+#endif
+#else
+#define FFB_FillRect NULL
+#define FFB_BlitRect NULL
+#endif
+
+static DGAFunctionRec FFB_DGAFuncs = {
+ FFB_OpenFramebuffer,
+ FFB_CloseFramebuffer,
+ FFB_SetMode,
+ FFB_SetViewport,
+ FFB_GetViewport,
+ FFB_Flush,
+ FFB_FillRect,
+ FFB_BlitRect,
+ NULL
+};
+
+void FFB_InitDGA(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ FFBPtr pFfb;
+ DGAModePtr mode;
+ Bool result;
+
+ pFfb = GET_FFB_FROM_SCRN(pScrn);
+
+ mode = xnfcalloc(sizeof(DGAModeRec), 1);
+ if (!mode) {
+ xf86Msg(X_WARNING, "%s: DGA init failed, cannot alloc DGAMode.\n",
+ pFfb->psdp->device);
+ return;
+ }
+
+ mode->num = 0;
+ mode->mode = pScrn->modes;
+
+ /* Hmmm, what does concurrent access really mean? -DaveM */
+ mode->flags = (DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE | DGA_FILL_RECT);
+
+#ifdef USE_VIS
+ mode->flags |= DGA_BLIT_RECT;
+#endif
+
+ mode->imageWidth = 2048;
+ mode->imageHeight = 2048;
+ mode->pixmapWidth = 2048;
+ mode->pixmapHeight = 2048;
+
+ /* XXX I would imagine that this value states how many bytes
+ * XXX you add to advance exactly one full horizontal line in
+ * XXX the framebuffer addressing, but the way we set the pScrn
+ * XXX mode values do not match that definition.
+ * XXX
+ * XXX Ask Jakub what is going on here. -DaveM
+ */
+#if 1
+ mode->bytesPerScanline = pScrn->modes->HDisplay * 4;
+#else
+ mode->bytesPerScanline = (2048 * 4);
+#endif
+
+ mode->byteOrder = pScrn->imageByteOrder;
+ mode->depth = 32;
+ mode->bitsPerPixel = 32;
+ mode->red_mask = 0xff;
+ mode->green_mask = 0xff00;
+ mode->blue_mask = 0xff0000;
+ mode->visualClass = TrueColor;
+ mode->viewportWidth = pScrn->modes->HDisplay;
+ mode->viewportHeight = pScrn->modes->VDisplay;
+
+ /* Do these values even matter if we do not support
+ * viewports? -DaveM
+ */
+ mode->xViewportStep = 0;
+ mode->yViewportStep = 0;
+ mode->maxViewportX = 0;
+ mode->maxViewportY = 0;
+
+ mode->viewportFlags = 0;
+ mode->offset = 0;
+
+ result = DGAInit(pScreen, &FFB_DGAFuncs, mode, 1);
+ if (result == FALSE) {
+ xf86Msg(X_WARNING,
+ "%s: DGA init failed, DGAInit returns FALSE.\n",
+ pFfb->psdp->device);
+ } else {
+ xf86Msg(X_INFO, "%s: DGA support initialized.\n",
+ pFfb->psdp->device);
+ }
+}
+
+static Bool FFB_OpenFramebuffer(ScrnInfoPtr pScrn, char **name, unsigned char **mem,
+ int *size, int *offset, int *extra)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
+
+ *name = pFfb->psdp->device;
+
+ /* We give the user the dumb frame buffer. */
+ *mem = (unsigned char *)FFB_DFB24_VOFF;
+ *size = 0x1000000;
+ *offset = 0;
+ *extra = 0;
+
+ return TRUE;
+}
+
+static void FFB_CloseFramebuffer(ScrnInfoPtr pScrn)
+{
+}
+
+static Bool FFB_SetMode(ScrnInfoPtr pScrn, DGAModePtr pMode)
+{
+ /* Nothing to do, we currently only support one mode
+ * and we are always in it.
+ */
+ return TRUE;
+}
+
+static void FFB_SetViewport(ScrnInfoPtr pScrn, int x, int y, int flags)
+{
+ /* We don't support viewports, so... */
+}
+
+static int FFB_GetViewport(ScrnInfoPtr pScrn)
+{
+ /* No viewports, none pending... */
+ return 0;
+}
+
+static void FFB_Flush(ScrnInfoPtr pScrn)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
+ ffb_fbcPtr ffb = pFfb->regs;
+
+ FFBWait(pFfb, ffb);
+}
+
+#if 0
+
+extern void CreatorFillBoxSolid (DrawablePtr pDrawable, int nBox,
+ BoxPtr pBox, unsigned long pixel);
+
+static void FFB_FillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h, unsigned long color)
+{
+ DrawableRec draw;
+ BoxRec box;
+
+ draw.pScreen = pScrn->pScreen;
+ box.x1 = x;
+ box.y1 = y;
+ box.x2 = x + w;
+ box.y2 = y + h;
+
+ CreatorFillBoxSolid(&draw, 1, &box, color);
+}
+
+#ifdef USE_VIS
+extern void VISmoveImageLR(unsigned char *, unsigned char *, long, long, long, long);
+extern void VISmoveImageRL(unsigned char *, unsigned char *, long, long, long, long);
+
+static void FFB_BlitRect(ScrnInfoPtr pScrn, int srcx, int srcy,
+ int w, int h, int dstx, int dsty)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
+ ffb_fbcPtr ffb = pFfb->regs;
+
+ if (!pFfb->disable_vscroll &&
+ dstx == srcx &&
+ dsty != dsty) {
+ FFB_WRITE_ATTRIBUTES_VSCROLL(pFfb, 0x00ffffff);
+ FFBFifo(pFfb, 7);
+ ffb->drawop = FFB_DRAWOP_VSCROLL;
+ FFB_WRITE64(&ffb->by, srcy, srcx);
+ FFB_WRITE64_2(&ffb->dy, dsty, dstx);
+ FFB_WRITE64_3(&ffb->bh, h, w);
+ pFfb->rp_active = 1;
+ } else {
+ unsigned char *base = (unsigned char *)pFfb->fb;
+ int use_prefetch = pFfb->use_blkread_prefetch;
+
+ FFB_WRITE_ATTRIBUTES_SFB_VAR(pFfb, 0x00ffffff, GXcopy);
+ FFBWait(pFfb, ffb);
+ if (use_prefetch) {
+ FFBFifo(pFfb, 1);
+ ffb->mer = FFB_MER_EIRA;
+ pFfb->rp_active = 1;
+ FFBWait(pFfb, ffb);
+ }
+ if (srcx < dstx) {
+ VISmoveImageRL((base +
+ ((srcy + h - 1) * (2048 * 4)) +
+ (srcx * (32 / 8))),
+ (base +
+ ((dsty + h - 1) * (2048 * 4)) +
+ (dstx * (32 / 8))),
+ (w * (32 / 8)),
+ h,
+ -(2048 * 4), - (2048 * 4));
+ } else {
+ VISmoveImageLR((base +
+ ((srcy + h - 1) * (2048 * 4)) +
+ (srcx * (32 / 8))),
+ (base +
+ ((dsty + h - 1) * (2048 * 4)) +
+ (dstx * (32 / 8))),
+ (w * (32 / 8)),
+ h,
+ -(2048 * 4), - (2048 * 4));
+ }
+ if (use_prefetch) {
+ FFBFifo(pFfb, 1);
+ ffb->mer = FFB_MER_DRA;
+ pFfb->rp_active = 1;
+ FFBWait(pFfb, pFfb->regs);
+ }
+ }
+}
+#endif
+
+#endif
diff --git a/src/ffb_dri.c b/src/ffb_dri.c
new file mode 100644
index 0000000..334bdfd
--- /dev/null
+++ b/src/ffb_dri.c
@@ -0,0 +1,529 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_dri.c,v 1.9 2001/05/02 15:06:10 dawes Exp $
+ * Acceleration for the Creator and Creator3D framebuffer - DRI/DRM support.
+ *
+ * Copyright (C) 2000 David S. Miller (davem@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+#include "xf86Priv.h"
+
+#include "xf86PciInfo.h"
+#include "xf86Pci.h"
+#define PSZ 8
+#include "cfb.h"
+#undef PSZ
+#include "cfb16.h"
+#include "cfb32.h"
+
+#include "miline.h"
+
+#include "GL/glxtokens.h"
+
+#include "xf86drm.h"
+#include "sarea.h"
+#define _XF86DRI_SERVER_
+#include "xf86dri.h"
+#include "dri.h"
+#include "dristruct.h"
+
+#include "GL/glxint.h"
+
+#include "ffb.h"
+#include "ffb_regs.h"
+#include "ffb_fifo.h"
+#include "ffb_rcache.h"
+
+static char FFBKernelDriverName[] = "ffb";
+static char FFBClientDriverName[] = "ffb";
+
+/* Forward declarations. */
+static Bool FFBDRICreateContext(ScreenPtr, VisualPtr, drmContext,
+ void *, DRIContextType);
+static void FFBDRIDestroyContext(ScreenPtr, drmContext, DRIContextType);
+
+static void FFBDRIInitBuffers(WindowPtr, RegionPtr, CARD32);
+static void FFBDRIMoveBuffers(WindowPtr, DDXPointRec, RegionPtr, CARD32);
+
+static void FFBDRISetDrawableIndex(WindowPtr, CARD32);
+
+/* XXX Why isn't this in a header somewhere? XXX */
+extern void GlxSetVisualConfigs(int nconfigs, __GLXvisualConfig *configs,
+ void **configprivs);
+
+static Bool
+FFBDRIInitVisualConfigs(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
+ __GLXvisualConfig *pConfigs;
+ FFBConfigPrivPtr pFfbConfigs;
+ FFBConfigPrivPtr *pFfbConfigPtrs;
+
+ pConfigs = (__GLXvisualConfig *)
+ xcalloc(sizeof(__GLXvisualConfig), 1);
+ if (!pConfigs)
+ return FALSE;
+
+ pFfbConfigs = (FFBConfigPrivPtr)
+ xcalloc(sizeof(FFBConfigPrivRec), 1);
+ if (!pFfbConfigs) {
+ xfree(pConfigs);
+ return FALSE;
+ }
+
+ pFfbConfigPtrs = (FFBConfigPrivPtr *)
+ xcalloc(sizeof(FFBConfigPrivPtr), 1);
+ if (!pFfbConfigPtrs) {
+ xfree(pConfigs);
+ xfree(pFfbConfigs);
+ return FALSE;
+ }
+
+ pFfbConfigPtrs[0] = &pFfbConfigs[0];
+
+ pConfigs->vid = -1;
+ pConfigs->class = -1;
+ pConfigs->rgba = TRUE;
+ pConfigs->redSize = 8;
+ pConfigs->greenSize = 8;
+ pConfigs->blueSize = 8;
+ pConfigs->alphaSize = 0;
+ pConfigs->redMask = 0x000000ff;
+ pConfigs->greenMask = 0x0000ff00;
+ pConfigs->blueMask = 0x00ff0000;
+ pConfigs->alphaMask = 0;
+ pConfigs->accumRedSize = 0;
+ pConfigs->accumGreenSize = 0;
+ pConfigs->accumBlueSize = 0;
+ pConfigs->accumAlphaSize = 0;
+ pConfigs->doubleBuffer = TRUE;
+ pConfigs->stereo = FALSE;
+ pConfigs->bufferSize = 32;
+ pConfigs->depthSize = 16;
+ pConfigs->stencilSize = 0;
+ pConfigs->auxBuffers = 0;
+ pConfigs->level = 0;
+ pConfigs->visualRating = 0;
+ pConfigs->transparentPixel = 0;
+ pConfigs->transparentRed = 0;
+ pConfigs->transparentGreen = 0;
+ pConfigs->transparentBlue = 0;
+ pConfigs->transparentAlpha = 0;
+ pConfigs->transparentIndex = 0;
+
+ pFfb->numVisualConfigs = 1;
+ pFfb->pVisualConfigs = pConfigs;
+ pFfb->pVisualConfigsPriv = pFfbConfigs;
+
+ GlxSetVisualConfigs(1, pConfigs, (void **)pFfbConfigPtrs);
+
+ return TRUE;
+}
+
+static void
+init_ffb_sarea(FFBPtr pFfb, ffb_dri_state_t *pFfbSarea)
+{
+ int i;
+
+ pFfbSarea->flags = 0;
+
+ switch (pFfb->ffb_type) {
+ case ffb2_prototype:
+ case ffb2_vertical:
+ case ffb2_vertical_plus:
+ case ffb2_horizontal:
+ case ffb2_horizontal_plus:
+ pFfbSarea->flags |= FFB_DRI_FFB2;
+ break;
+
+ default:
+ break;
+ };
+
+ if (pFfb->ffb_type == ffb2_vertical_plus ||
+ pFfb->ffb_type == ffb2_horizontal_plus)
+ pFfbSarea->flags |= FFB_DRI_FFB2PLUS;
+
+ if (pFfb->dac_info.flags & FFB_DAC_PAC1)
+ pFfbSarea->flags |= FFB_DRI_PAC1;
+
+ if (pFfb->dac_info.flags & FFB_DAC_PAC2)
+ pFfbSarea->flags |= FFB_DRI_PAC2;
+
+ for (i = 0; i < FFB_DRI_NWIDS; i++)
+ pFfbSarea->wid_table[i] = 0;
+}
+
+#define FFB_DFB24_POFF 0x02000000UL
+#define FFB_DFB24_SIZE 0x01000000UL
+
+#define FFB_FBC_REGS_POFF 0x00600000UL
+#define FFB_FBC_REGS_SIZE 0x00002000UL
+
+#define FFB_DAC_POFF 0x00400000UL
+#define FFB_DAC_SIZE 0x00002000UL
+
+#define FFB_SFB8R_POFF 0x04000000UL
+#define FFB_SFB8R_SIZE 0x00400000UL
+
+#define FFB_SFB32_POFF 0x05000000UL
+#define FFB_SFB32_SIZE 0x01000000UL
+
+#define FFB_SFB64_POFF 0x06000000UL
+#define FFB_SFB64_SIZE 0x02000000UL
+
+Bool
+FFBDRIScreenInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
+ DRIInfoPtr pDRIInfo;
+ FFBDRIPtr pFfbDRI;
+
+ /* Check that the GLX, DRI, and DRM modules have been loaded by testing
+ * for canonical symbols in each module.
+ */
+ if (!xf86LoaderCheckSymbol("GlxSetVisualConfigs"))
+ return FALSE;
+ if (!xf86LoaderCheckSymbol("DRIScreenInit"))
+ return FALSE;
+ if (!xf86LoaderCheckSymbol("drmAvailable"))
+ return FALSE;
+ if (!xf86LoaderCheckSymbol("DRIQueryVersion")) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "FFBDRIScreenInit failed (libdri.a too old)\n");
+ return FALSE;
+ }
+
+ /* Check the DRI version */
+ {
+ int major, minor, patch;
+ DRIQueryVersion(&major, &minor, &patch);
+ if (major != 4 || minor < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] FFBDRIScreenInit failed because of a version mismatch.\n"
+ "[dri] libDRI version is %d.%d.%d but version, 4.0.x is needed.\n"
+ "[dri] Disabling DRI.\n",
+ major, minor, patch);
+ return FALSE;
+ }
+ }
+
+ pDRIInfo = DRICreateInfoRec();
+ if (pDRIInfo == NULL)
+ return FALSE;
+
+ pFfb->pDRIInfo = pDRIInfo;
+
+ pDRIInfo->drmDriverName = FFBKernelDriverName;
+ pDRIInfo->clientDriverName = FFBClientDriverName;
+
+ pDRIInfo->ddxDriverMajorVersion = 0;
+ pDRIInfo->ddxDriverMinorVersion = 0;
+ pDRIInfo->ddxDriverPatchVersion = 1;
+
+ pDRIInfo->busIdString = xalloc(64); /* Freed in DRIDestroyInfoRec */
+ sprintf(pDRIInfo->busIdString, "SBUS:%s", pFfb->psdp->device);
+
+ /* Dumb rendering port for now... */
+ pDRIInfo->frameBufferPhysicalAddress = FFB_DFB24_POFF;
+ pDRIInfo->frameBufferSize = FFB_DFB24_SIZE;
+ pDRIInfo->frameBufferStride = (2048 * 4);
+
+ /* XXX */
+ pDRIInfo->ddxDrawableTableEntry = 15;
+ pDRIInfo->maxDrawableTableEntry = 15;
+ pDRIInfo->SAREASize = (SAREA_MAX + (0x2000 - 1)) & ~(0x2000 - 1);
+
+ pFfbDRI = (FFBDRIPtr) xcalloc(sizeof(FFBDRIRec), 1);
+ if (pFfbDRI == NULL) {
+ DRIDestroyInfoRec(pFfb->pDRIInfo);
+ return FALSE;
+ }
+
+ pDRIInfo->devPrivate = pFfbDRI;
+ pDRIInfo->devPrivateSize = sizeof(*pFfbDRI);
+ pDRIInfo->contextSize = 0; /* kernel does ctx swaps */
+
+ pDRIInfo->CreateContext = FFBDRICreateContext;
+ pDRIInfo->DestroyContext = FFBDRIDestroyContext;
+ pDRIInfo->InitBuffers = FFBDRIInitBuffers;
+ pDRIInfo->MoveBuffers = FFBDRIMoveBuffers;
+ pDRIInfo->SetDrawableIndex = FFBDRISetDrawableIndex;
+
+ /* Our InitBuffers depends heavily on this setting. */
+ pDRIInfo->bufferRequests = DRI_3D_WINDOWS_ONLY;
+
+ pDRIInfo->createDummyCtx = TRUE;
+ pDRIInfo->createDummyCtxPriv = FALSE;
+
+ if (!DRIScreenInit(pScreen, pDRIInfo, &(pFfb->drmSubFD))) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] DRIScreenInit failed. Disabling DRI.\n");
+ DRIDestroyInfoRec(pFfb->pDRIInfo);
+ xfree(pFfbDRI);
+ return FALSE;
+ }
+
+#if 000 /* XXX this should be cleaned up and used */
+ /* Check the ffb DRM version */
+ version = drmGetVersion(info->drmFD);
+ if (version) {
+ if (version->version_major != 1 ||
+ version->version_minor < 0) {
+ /* incompatible drm version */
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] FFBDRIScreenInit failed because of a version mismatch.\n"
+ "[dri] ffb.o kernel module version is %d.%d.%d but version 1.0.x is needed.\n"
+ "[dri] Disabling the DRI.\n",
+ version->version_major,
+ version->version_minor,
+ version->version_patchlevel);
+ drmFreeVersion(version);
+ R128DRICloseScreen(pScreen);
+ return FALSE;
+ }
+ drmFreeVersion(version);
+ }
+#endif
+
+ pFfb->pFfbSarea = DRIGetSAREAPrivate(pScreen);
+ init_ffb_sarea(pFfb, pFfb->pFfbSarea);
+
+ /* Setup device specific direct rendering memory maps. */
+ if (drmAddMap(pFfb->drmSubFD,
+ FFB_FBC_REGS_POFF, FFB_FBC_REGS_SIZE,
+ DRM_REGISTERS, 0, &pFfbDRI->hFbcRegs) < 0) {
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+ pFfbDRI->sFbcRegs = FFB_FBC_REGS_SIZE;
+ pFfbDRI->mFbcRegs = 0;
+
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[drm] FBC Register handle = 0x%08x\n",
+ pFfbDRI->hFbcRegs);
+
+ if (drmAddMap(pFfb->drmSubFD,
+ FFB_DAC_POFF, FFB_DAC_SIZE,
+ DRM_REGISTERS, 0, &pFfbDRI->hDacRegs) < 0) {
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+ pFfbDRI->sDacRegs = FFB_DAC_SIZE;
+ pFfbDRI->mDacRegs = 0;
+
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[drm] DAC Register handle = 0x%08x\n",
+ pFfbDRI->hDacRegs);
+
+ /* Now add maps for the "Smart" views of the framebuffer. */
+ if (drmAddMap(pFfb->drmSubFD,
+ FFB_SFB8R_POFF, FFB_SFB8R_SIZE,
+ DRM_REGISTERS, 0, &pFfbDRI->hSfb8r) < 0) {
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+ pFfbDRI->sSfb8r = FFB_SFB8R_SIZE;
+ pFfbDRI->mSfb8r = 0;
+
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[drm] SFB8R handle = 0x%08x\n",
+ pFfbDRI->hSfb8r);
+
+ if (drmAddMap(pFfb->drmSubFD,
+ FFB_SFB32_POFF, FFB_SFB32_SIZE,
+ DRM_REGISTERS, 0, &pFfbDRI->hSfb32) < 0) {
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+ pFfbDRI->sSfb32 = FFB_SFB32_SIZE;
+ pFfbDRI->mSfb32 = 0;
+
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[drm] SFB32 handle = 0x%08x\n",
+ pFfbDRI->hSfb32);
+
+ if (drmAddMap(pFfb->drmSubFD,
+ FFB_SFB64_POFF, FFB_SFB64_SIZE,
+ DRM_REGISTERS, 0, &pFfbDRI->hSfb64) < 0) {
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+ pFfbDRI->sSfb64 = FFB_SFB64_SIZE;
+ pFfbDRI->mSfb64 = 0;
+
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[drm] SFB64 handle = 0x%08x\n",
+ pFfbDRI->hSfb64);
+
+ /* Setup visual configurations. */
+ if (!FFBDRIInitVisualConfigs(pScreen)) {
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[drm] Visual configs initialized\n");
+
+ return TRUE;
+}
+
+void
+FFBDRICloseScreen(ScreenPtr pScreen)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN(pScreen);
+
+ DRICloseScreen(pScreen);
+
+ if (pFfb->pDRIInfo) {
+ DRIInfoPtr pDRIInfo = pFfb->pDRIInfo;
+
+ if (pDRIInfo->devPrivate)
+ xfree(pDRIInfo->devPrivate);
+ DRIDestroyInfoRec(pDRIInfo);
+ pFfb->pDRIInfo = NULL;
+ }
+
+ if (pFfb->pVisualConfigs) {
+ xfree(pFfb->pVisualConfigs);
+ pFfb->pVisualConfigs = NULL;
+ }
+ if (pFfb->pVisualConfigsPriv) {
+ xfree(pFfb->pVisualConfigsPriv);
+ pFfb->pVisualConfigsPriv = NULL;
+ }
+}
+
+static Bool
+FFBDRICreateContext(ScreenPtr pScreen, VisualPtr visual, drmContext hwContext,
+ void *pVisualConfigPriv, DRIContextType context)
+{
+ /* Nothing to do... */
+ return TRUE;
+}
+
+static void
+FFBDRIDestroyContext(ScreenPtr pScreen, drmContext hwContext, DRIContextType context)
+{
+ /* Nothing to do... */
+}
+
+Bool
+FFBDRIFinishScreenInit(ScreenPtr pScreen)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN(pScreen);
+ DRIInfoPtr pDRIInfo = pFfb->pDRIInfo;
+ FFBDRIPtr pFfbDRI = (FFBDRIPtr) pDRIInfo->devPrivate;
+ int i;
+
+ /* This belongs in the kernel. I'm sorry, the rest
+ * of the current DRI switching mechanisms just suck.
+ */
+ pDRIInfo->driverSwapMethod = DRI_KERNEL_SWAP;
+
+ /* Copy over the fast/page filling parameters now that
+ * acceleration has been fully setup.
+ */
+ pFfbDRI->disable_pagefill = pFfb->disable_pagefill;
+ pFfbDRI->fastfill_small_area = FFB_FFPARMS(pFfb).fastfill_small_area;
+ pFfbDRI->pagefill_small_area = FFB_FFPARMS(pFfb).pagefill_small_area;
+ pFfbDRI->fastfill_height = FFB_FFPARMS(pFfb).fastfill_height;
+ pFfbDRI->fastfill_width = FFB_FFPARMS(pFfb).fastfill_width;
+ pFfbDRI->pagefill_height = FFB_FFPARMS(pFfb).pagefill_height;
+ pFfbDRI->pagefill_width = FFB_FFPARMS(pFfb).pagefill_width;
+ for (i = 0; i < 0x800; i++)
+ pFfbDRI->Pf_AlignTab[i] = pFfb->Pf_AlignTab[i];
+
+ return DRIFinishScreenInit(pScreen);
+}
+
+static void
+FFBDRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN(pScreen);
+ CreatorPrivWinPtr pFfbPrivWin = CreatorGetWindowPrivate(pWin);
+ ffb_fbcPtr ffb = pFfb->regs;
+ unsigned int fbc;
+ BoxPtr pBox;
+ int nBox;
+
+ fbc = pFfbPrivWin->fbc_base;
+ fbc = (fbc & ~FFB_FBC_WB_MASK) | FFB_FBC_WB_AB;
+ fbc = (fbc & ~FFB_FBC_XE_MASK) | FFB_FBC_XE_ON;
+ fbc = (fbc & ~FFB_FBC_RGBE_MASK) | FFB_FBC_RGBE_OFF;
+
+ pBox = REGION_RECTS(prgn);
+ nBox = (int) REGION_NUM_RECTS(prgn);
+ FFB_WRITE_ROP(pFfb, ffb, (FFB_ROP_NEW | (FFB_ROP_NEW << 8)));
+ FFB_WRITE_PPC(pFfb, ffb,
+ (FFB_PPC_APE_DISABLE | FFB_PPC_CS_CONST | FFB_PPC_XS_WID),
+ (FFB_PPC_APE_MASK | FFB_PPC_CS_MASK | FFB_PPC_XS_MASK));
+ FFB_WRITE_PMASK(pFfb, ffb, ~0);
+ FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_RECTANGLE);
+ FFB_WRITE_FBC(pFfb, ffb, fbc);
+ FFB_WRITE_WID(pFfb, ffb, FFB_WID_WIN(pWin));
+
+ while(nBox--) {
+ register int x, y, w, h;
+
+ x = pBox->x1;
+ y = pBox->y1;
+ w = (pBox->x2 - x);
+ h = (pBox->y2 - y);
+ FFBFifo(pFfb, 4);
+ FFB_WRITE64(&ffb->by, y, x);
+ FFB_WRITE64_2(&ffb->bh, h, w);
+ pBox++;
+ }
+ pFfb->rp_active = 1;
+ FFBSync(pFfb, ffb);
+}
+
+static void
+FFBDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg,
+ RegionPtr prgnSrc, CARD32 index)
+{
+}
+
+static void
+FFBDRISetDrawableIndex(WindowPtr pWin, CARD32 index)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN(pScreen);
+ CreatorPrivWinPtr pFfbPrivWin = CreatorGetWindowPrivate(pWin);
+ unsigned int wid;
+
+ if (FFBWidIsShared(pFfb, pFfbPrivWin->wid)) {
+ wid = FFBWidUnshare(pFfb, pFfbPrivWin->wid);
+ if (wid == (unsigned int) -1)
+ return;
+
+ ErrorF("FFB: Allocated WID %x for DRI window.\n", wid);
+ pFfbPrivWin->wid = wid;
+
+ /* Now update the SAREA. */
+ pFfb->pFfbSarea->wid_table[index] = wid;
+ }
+}
diff --git a/src/ffb_drishare.h b/src/ffb_drishare.h
new file mode 100644
index 0000000..501dd5b
--- /dev/null
+++ b/src/ffb_drishare.h
@@ -0,0 +1,53 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_drishare.h,v 1.2 2000/06/21 00:47:37 dawes Exp $ */
+
+#ifndef _FFB_DRISHARE_H
+#define _FFB_DRISHARE_H
+
+typedef struct ffb_dri_state {
+ int flags;
+#define FFB_DRI_FFB2 0x00000001
+#define FFB_DRI_FFB2PLUS 0x00000002
+#define FFB_DRI_PAC1 0x00000004
+#define FFB_DRI_PAC2 0x00000008
+
+ /* Indexed by DRI drawable id. */
+#define FFB_DRI_NWIDS 64
+ unsigned int wid_table[FFB_DRI_NWIDS];
+} ffb_dri_state_t;
+
+#define FFB_DRISHARE(SAREA) \
+ ((ffb_dri_state_t *) (((char *)(SAREA)) + sizeof(XF86DRISAREARec)))
+
+typedef struct {
+ drmHandle hFbcRegs;
+ drmSize sFbcRegs;
+ drmAddress mFbcRegs;
+
+ drmHandle hDacRegs;
+ drmSize sDacRegs;
+ drmAddress mDacRegs;
+
+ drmHandle hSfb8r;
+ drmSize sSfb8r;
+ drmAddress mSfb8r;
+
+ drmHandle hSfb32;
+ drmSize sSfb32;
+ drmAddress mSfb32;
+
+ drmHandle hSfb64;
+ drmSize sSfb64;
+ drmAddress mSfb64;
+
+ /* Fastfill/Pagefill parameters. */
+ unsigned char disable_pagefill;
+ int fastfill_small_area;
+ int pagefill_small_area;
+ int fastfill_height;
+ int fastfill_width;
+ int pagefill_height;
+ int pagefill_width;
+ short Pf_AlignTab[0x800];
+} FFBDRIRec, *FFBDRIPtr;
+
+#endif /* !(_FFB_DRISHARE_H) */
diff --git a/src/ffb_driver.c b/src/ffb_driver.c
new file mode 100644
index 0000000..8921955
--- /dev/null
+++ b/src/ffb_driver.c
@@ -0,0 +1,1122 @@
+/*
+ * Creator, Creator3D and Elite3D framebuffer driver.
+ *
+ * Copyright (C) 2000 Jakub Jelinek (jakub@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * JAKUB JELINEK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_driver.c,v 1.11 2002/12/06 02:44:04 tsi Exp $ */
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+#include "xf86Version.h"
+#include "mipointer.h"
+#include "mibstore.h"
+#include "micmap.h"
+
+#define PSZ 8
+#include "cfb.h"
+#undef PSZ
+#include "cfb32.h"
+#include "cfb8_32wid.h"
+
+#include "xf86cmap.h"
+
+#include "ffb.h"
+
+static const OptionInfoRec * FFBAvailableOptions(int chipid, int busid);
+static void FFBIdentify(int flags);
+static Bool FFBProbe(DriverPtr drv, int flags);
+static Bool FFBPreInit(ScrnInfoPtr pScrn, int flags);
+static Bool FFBScreenInit(int Index, ScreenPtr pScreen, int argc,
+ char **argv);
+static Bool FFBEnterVT(int scrnIndex, int flags);
+static void FFBLeaveVT(int scrnIndex, int flags);
+static Bool FFBCloseScreen(int scrnIndex, ScreenPtr pScreen);
+static Bool FFBSaveScreen(ScreenPtr pScreen, int mode);
+
+/* Required if the driver supports mode switching */
+static Bool FFBSwitchMode(int scrnIndex, DisplayModePtr mode, int flags);
+/* Required if the driver supports moving the viewport */
+static void FFBAdjustFrame(int scrnIndex, int x, int y, int flags);
+
+/* Optional functions */
+static void FFBFreeScreen(int scrnIndex, int flags);
+static int FFBValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose,
+ int flags);
+static void FFBDPMSMode(ScrnInfoPtr pScrn, int DPMSMode, int flags);
+/* ffb_dga.c */
+extern void FFB_InitDGA(ScreenPtr pScreen);
+
+void FFBSync(ScrnInfoPtr pScrn);
+
+#define VERSION 4000
+#define FFB_NAME "SUNFFB"
+#define FFB_DRIVER_NAME "sunffb"
+#define FFB_MAJOR_VERSION 1
+#define FFB_MINOR_VERSION 0
+#define FFB_PATCHLEVEL 0
+
+/*
+ * This contains the functions needed by the server after loading the driver
+ * module. It must be supplied, and gets passed back by the SetupProc
+ * function in the dynamic case. In the static case, a reference to this
+ * is compiled in, and this requires that the name of this DriverRec be
+ * an upper-case version of the driver name.
+ */
+
+DriverRec SUNFFB = {
+ VERSION,
+ FFB_DRIVER_NAME,
+ FFBIdentify,
+ FFBProbe,
+ FFBAvailableOptions,
+ NULL,
+ 0
+};
+
+typedef enum {
+ OPTION_SW_CURSOR,
+ OPTION_HW_CURSOR,
+ OPTION_NOACCEL
+} FFBOpts;
+
+static const OptionInfoRec FFBOptions[] = {
+ { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE },
+ { -1, NULL, OPTV_NONE, {0}, FALSE }
+};
+
+#ifdef XFree86LOADER
+
+static MODULESETUPPROTO(ffbSetup);
+
+static XF86ModuleVersionInfo sunffbVersRec =
+{
+ "sunffb",
+ MODULEVENDORSTRING,
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XF86_VERSION_CURRENT,
+ FFB_MAJOR_VERSION, FFB_MINOR_VERSION, FFB_PATCHLEVEL,
+ ABI_CLASS_VIDEODRV,
+ ABI_VIDEODRV_VERSION,
+ MOD_CLASS_VIDEODRV,
+ {0,0,0,0}
+};
+
+XF86ModuleData sunffbModuleData = { &sunffbVersRec, ffbSetup, NULL };
+
+pointer
+ffbSetup(pointer module, pointer opts, int *errmaj, int *errmin)
+{
+ static Bool setupDone = FALSE;
+
+ if (!setupDone) {
+ setupDone = TRUE;
+ xf86AddDriver(&SUNFFB, module, 0);
+
+ /*
+ * Modules that this driver always requires can be loaded here
+ * by calling LoadSubModule().
+ */
+
+ /*
+ * The return value must be non-NULL on success even though there
+ * is no TearDownProc.
+ */
+ return (pointer)TRUE;
+ } else {
+ if (errmaj) *errmaj = LDR_ONCEONLY;
+ return NULL;
+ }
+}
+
+#endif /* XFree86LOADER */
+
+static Bool
+FFBGetRec(ScrnInfoPtr pScrn)
+{
+ /*
+ * Allocate an FFBRec, and hook it into pScrn->driverPrivate.
+ * pScrn->driverPrivate is initialised to NULL, so we can check if
+ * the allocation has already been done.
+ */
+ if (pScrn->driverPrivate != NULL)
+ return TRUE;
+
+ pScrn->driverPrivate = xnfcalloc(sizeof(FFBRec), 1);
+ return TRUE;
+}
+
+static void
+FFBFreeRec(ScrnInfoPtr pScrn)
+{
+ FFBPtr pFfb;
+
+ if (pScrn->driverPrivate == NULL)
+ return;
+
+ pFfb = GET_FFB_FROM_SCRN(pScrn);
+
+ xfree(pScrn->driverPrivate);
+ pScrn->driverPrivate = NULL;
+
+ return;
+}
+
+static const OptionInfoRec *
+FFBAvailableOptions(int chipid, int busid)
+{
+ return FFBOptions;
+}
+
+/* Mandatory */
+static void
+FFBIdentify(int flags)
+{
+ xf86Msg(X_INFO, "%s: driver for Creator, Creator 3D and Elite 3D\n", FFB_NAME);
+}
+
+
+/* Mandatory */
+static Bool
+FFBProbe(DriverPtr drv, int flags)
+{
+ int i;
+ GDevPtr *devSections;
+ int *usedChips;
+ int numDevSections;
+ int numUsed;
+ Bool foundScreen = FALSE;
+ EntityInfoPtr pEnt;
+
+ /*
+ * The aim here is to find all cards that this driver can handle,
+ * and for the ones not already claimed by another driver, claim the
+ * slot, and allocate a ScrnInfoRec.
+ *
+ * This should be a minimal probe, and it should under no circumstances
+ * change the state of the hardware. Because a device is found, don't
+ * assume that it will be used. Don't do any initialisations other than
+ * the required ScrnInfoRec initialisations. Don't allocate any new
+ * data structures.
+ */
+
+ /*
+ * Next we check, if there has been a chipset override in the config file.
+ * For this we must find out if there is an active device section which
+ * is relevant, i.e., which has no driver specified or has THIS driver
+ * specified.
+ */
+
+ if ((numDevSections = xf86MatchDevice(FFB_DRIVER_NAME,
+ &devSections)) <= 0) {
+ /*
+ * There's no matching device section in the config file, so quit
+ * now.
+ */
+ return FALSE;
+ }
+
+ /*
+ * We need to probe the hardware first. We then need to see how this
+ * fits in with what is given in the config file, and allow the config
+ * file info to override any contradictions.
+ */
+
+ numUsed = xf86MatchSbusInstances(FFB_NAME, SBUS_DEVICE_FFB,
+ devSections, numDevSections,
+ drv, &usedChips);
+
+ xfree(devSections);
+ if (numUsed <= 0)
+ return FALSE;
+
+ if (flags & PROBE_DETECT)
+ foundScreen = TRUE;
+ else for (i = 0; i < numUsed; i++) {
+ pEnt = xf86GetEntityInfo(usedChips[i]);
+
+ /*
+ * Check that nothing else has claimed the slots.
+ */
+ if(pEnt->active) {
+ ScrnInfoPtr pScrn;
+
+ /* Allocate a ScrnInfoRec and claim the slot */
+ pScrn = xf86AllocateScreen(drv, 0);
+
+ /* Fill in what we can of the ScrnInfoRec */
+ pScrn->driverVersion = VERSION;
+ pScrn->driverName = FFB_DRIVER_NAME;
+ pScrn->name = FFB_NAME;
+ pScrn->Probe = FFBProbe;
+ pScrn->PreInit = FFBPreInit;
+ pScrn->ScreenInit = FFBScreenInit;
+ pScrn->SwitchMode = FFBSwitchMode;
+ pScrn->AdjustFrame = FFBAdjustFrame;
+ pScrn->EnterVT = FFBEnterVT;
+ pScrn->LeaveVT = FFBLeaveVT;
+ pScrn->FreeScreen = FFBFreeScreen;
+ pScrn->ValidMode = FFBValidMode;
+ xf86AddEntityToScreen(pScrn, pEnt->index);
+ foundScreen = TRUE;
+ }
+ xfree(pEnt);
+ }
+ xfree(usedChips);
+ return foundScreen;
+}
+
+/* Mandatory */
+static Bool
+FFBPreInit(ScrnInfoPtr pScrn, int flags)
+{
+ FFBPtr pFfb;
+ sbusDevicePtr psdp;
+ MessageType from;
+ int i;
+
+ if (flags & PROBE_DETECT) return FALSE;
+
+ /*
+ * Note: This function is only called once at server startup, and
+ * not at the start of each server generation. This means that
+ * only things that are persistent across server generations can
+ * be initialised here. xf86Screens[] is (pScrn is a pointer to one
+ * of these). Privates allocated using xf86AllocateScrnInfoPrivateIndex()
+ * are too, and should be used for data that must persist across
+ * server generations.
+ *
+ * Per-generation data should be allocated with
+ * AllocateScreenPrivateIndex() from the ScreenInit() function.
+ */
+
+ /* Allocate the FFBRec driverPrivate */
+ if (!FFBGetRec(pScrn))
+ return FALSE;
+
+ pFfb = GET_FFB_FROM_SCRN(pScrn);
+
+ /* Set pScrn->monitor */
+ pScrn->monitor = pScrn->confScreen->monitor;
+
+ /* This driver doesn't expect more than one entity per screen */
+ if (pScrn->numEntities > 1)
+ return FALSE;
+ /* This is the general case */
+ for (i = 0; i < pScrn->numEntities; i++) {
+ EntityInfoPtr pEnt = xf86GetEntityInfo(pScrn->entityList[i]);
+
+ /* FFB is purely UPA (but we handle it as SBUS) */
+ if (pEnt->location.type == BUS_SBUS) {
+ psdp = xf86GetSbusInfoForEntity(pEnt->index);
+ pFfb->psdp = psdp;
+ } else
+ return FALSE;
+ }
+
+ /*********************
+ deal with depth
+ *********************/
+
+ if (!xf86SetDepthBpp(pScrn, 24, 0, 32, Support32bppFb)) {
+ return FALSE;
+ } else {
+ /* Check that the returned depth is one we support */
+ switch (pScrn->depth) {
+ case 24:
+ /* OK */
+ break;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Given depth (%d) is not supported by this driver\n",
+ pScrn->depth);
+ return FALSE;
+ }
+ }
+
+ /* Collect all of the relevant option flags (fill in pScrn->options) */
+ xf86CollectOptions(pScrn, NULL);
+ /* Process the options */
+ if (!(pFfb->Options = xalloc(sizeof(FFBOptions))))
+ return FALSE;
+ memcpy(pFfb->Options, FFBOptions, sizeof(FFBOptions));
+ xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pFfb->Options);
+
+ /*
+ * This must happen after pScrn->display has been set because
+ * xf86SetWeight references it.
+ */
+ if (pScrn->depth > 8) {
+ rgb weight = {8, 8, 8};
+ rgb mask = {0xff, 0xff00, 0xff0000};
+
+ if (!xf86SetWeight(pScrn, weight, mask)) {
+ return FALSE;
+ }
+ }
+
+ if (!xf86SetDefaultVisual(pScrn, -1))
+ return FALSE;
+
+ /*
+ * The new cmap code requires this to be initialised.
+ */
+
+ {
+ Gamma zeros = {0.0, 0.0, 0.0};
+
+ if (!xf86SetGamma(pScrn, zeros)) {
+ return FALSE;
+ }
+ }
+
+ /* Set the bits per RGB for 8bpp mode */
+ from = X_DEFAULT;
+
+ /* determine whether we use hardware or software cursor */
+
+ pFfb->HWCursor = TRUE;
+ if (xf86GetOptValBool(pFfb->Options, OPTION_HW_CURSOR, &pFfb->HWCursor))
+ from = X_CONFIG;
+ if (xf86ReturnOptValBool(pFfb->Options, OPTION_SW_CURSOR, FALSE)) {
+ from = X_CONFIG;
+ pFfb->HWCursor = FALSE;
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n",
+ pFfb->HWCursor ? "HW" : "SW");
+
+ if (xf86ReturnOptValBool(pFfb->Options, OPTION_NOACCEL, FALSE)) {
+ pFfb->NoAccel = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n");
+ }
+
+ if (xf86LoadSubModule(pScrn, "xf8_32wid") == NULL) {
+ FFBFreeRec(pScrn);
+ return FALSE;
+ }
+
+ if (xf86LoadSubModule(pScrn, "cfb32") == NULL) {
+ FFBFreeRec(pScrn);
+ return FALSE;
+ }
+
+ if (xf86LoadSubModule(pScrn, "cfb") == NULL) {
+ FFBFreeRec(pScrn);
+ return FALSE;
+ }
+
+ if (pFfb->HWCursor && xf86LoadSubModule(pScrn, "ramdac") == NULL) {
+ FFBFreeRec(pScrn);
+ return FALSE;
+ }
+
+ if (xf86LoadSubModule(pScrn, "dbe") == NULL) {
+ FFBFreeRec(pScrn);
+ return FALSE;
+ }
+
+#if 0
+/*#ifdef XF86DRI*/
+/*
+ * Loading this automatically isn't compatible
+ * to the behavior of other drivers
+ */
+ if (xf86LoadSubModule(pScrn, "drm") == NULL) {
+ FFBFreeRec(pScrn);
+ return FALSE;
+ }
+
+ if (xf86LoadSubModule(pScrn, "dri") == NULL) {
+ FFBFreeRec(pScrn);
+ return FALSE;
+ }
+#endif
+
+ /*********************
+ set up clock and mode stuff
+ *********************/
+
+ pScrn->progClock = TRUE;
+
+ if(pScrn->display->virtualX || pScrn->display->virtualY) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "FFB does not support a virtual desktop\n");
+ pScrn->display->virtualX = 0;
+ pScrn->display->virtualY = 0;
+ }
+
+ xf86SbusUseBuiltinMode(pScrn, pFfb->psdp);
+ pScrn->currentMode = pScrn->modes;
+ pScrn->displayWidth = pScrn->virtualX;
+
+ /* Set display resolution */
+ xf86SetDpi(pScrn, 0, 0);
+
+ return TRUE;
+}
+
+/* Determine the FFB/AFB board type. We need this information even
+ * if acceleration is disabled because the ramdac support layer needs
+ * to know what kind of FFB/AFB this is.
+ */
+static void
+FFBProbeBoardType(FFBPtr pFfb)
+{
+ ffb_fbcPtr ffb = pFfb->regs;
+ volatile unsigned int *afb_fem;
+ unsigned int val;
+
+ afb_fem = ((volatile unsigned int *) ((char *)ffb + 0x1540));
+ val = *afb_fem;
+ val &= 0x7f;
+
+ xf86Msg(X_INFO, "%s: ", pFfb->psdp->device);
+ if (val == 0x3f || val == 0x07 || val == 0x01) {
+ /* When firmware has not been loaded onto AFB we
+ * just assume it is an M6 board.
+ */
+ if (val == 0x3f || val != 0x07) {
+ pFfb->ffb_type = afb_m6;
+ ErrorF("AFB: Detected Elite3D/M6.\n");
+ } else {
+ pFfb->ffb_type = afb_m3;
+ ErrorF("AFB: Detected Elite3D/M3.\n");
+ }
+
+ /* These attributes are invariant on AFB. */
+ pFfb->has_double_res = 0;
+ pFfb->has_z_buffer = 1;
+ pFfb->has_double_buffer = 1;
+ } else {
+ unsigned char sbits;
+
+ /* Read the board strapping bits twice, because sometimes
+ * the strapping pins can get misrouted to the bus interface
+ * on the first attempt. The second attempt will get the
+ * correct value.
+ */
+ sbits = *((volatile unsigned char *)pFfb->strapping_bits);
+ sbits = *((volatile unsigned char *)pFfb->strapping_bits);
+ switch (sbits & 0x78) {
+ case (0x0 << 5) | (0x0 << 3):
+ pFfb->ffb_type = ffb1_prototype;
+ ErrorF("Detected FFB1 pre-FCS prototype, ");
+ break;
+ case (0x0 << 5) | (0x1 << 3):
+ pFfb->ffb_type = ffb1_standard;
+ ErrorF("Detected FFB1, ");
+ break;
+ case (0x0 << 5) | (0x3 << 3):
+ pFfb->ffb_type = ffb1_speedsort;
+ ErrorF("Detected FFB1-SpeedSort, ");
+ break;
+ case (0x1 << 5) | (0x0 << 3):
+ pFfb->ffb_type = ffb2_prototype;
+ ErrorF("Detected FFB2/vertical pre-FCS prototype, ");
+ break;
+ case (0x1 << 5) | (0x1 << 3):
+ pFfb->ffb_type = ffb2_vertical;
+ ErrorF("Detected FFB2/vertical, ");
+ break;
+ case (0x1 << 5) | (0x2 << 3):
+ pFfb->ffb_type = ffb2_vertical_plus;
+ ErrorF("Detected FFB2+/vertical, ");
+ break;
+ case (0x2 << 5) | (0x0 << 3):
+ pFfb->ffb_type = ffb2_horizontal;
+ ErrorF("Detected FFB2/horizontal, ");
+ break;
+ case (0x2 << 5) | (0x2 << 3):
+ pFfb->ffb_type = ffb2_horizontal;
+ ErrorF("Detected FFB2+/horizontal, ");
+ break;
+ default:
+ pFfb->ffb_type = ffb2_vertical;
+ ErrorF("Unknown boardID[%08x], assuming FFB2, ", sbits);
+ break;
+ };
+
+ if (sbits & (1 << 2)) {
+ ErrorF("DoubleRES, ");
+ pFfb->has_double_res = 1;
+ } else {
+ pFfb->has_double_res = 0;
+ }
+ if (sbits & (1 << 1)) {
+ ErrorF("Z-buffer, ");
+ pFfb->has_z_buffer = 1;
+ } else {
+ pFfb->has_z_buffer = 0;
+ }
+ if (sbits & (1 << 0)) {
+ ErrorF("Double-buffered.\n");
+
+ /* This state really means to the driver that the double
+ * buffers are available for hw accelerate Dbe. When the
+ * FFB is in high-resolution mode, the buffers are combined
+ * into one single large framebuffer. So in high-resolution
+ * hw accelerated double-buffering is not available.
+ */
+ if ((ffb->fbcfg0 & FFB_FBCFG0_RES_MASK) != FFB_FBCFG0_RES_HIGH)
+ pFfb->has_double_buffer = 1;
+ else
+ pFfb->has_double_buffer = 1;
+ } else {
+ ErrorF("Single-buffered.\n");
+ pFfb->has_double_buffer = 0;
+ }
+ }
+}
+
+static unsigned long CreatorUnaccelGeneration = 0;
+static int CreatorUnaccelWindowPrivateIndex;
+
+#define CreatorUnaccelGetWid(w) \
+ ((w)->devPrivates[CreatorUnaccelWindowPrivateIndex].val)
+#define CreatorUnaccelSetWid(w,wid) \
+ (((w)->devPrivates[CreatorUnaccelWindowPrivateIndex].val) = (wid))
+
+static unsigned int
+CreatorWidGet(WindowPtr pWin)
+{
+ return CreatorUnaccelGetWid(pWin);
+}
+
+static Bool
+CreatorWidAlloc(WindowPtr pWin)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
+ unsigned int wid;
+ int i, visual, visclass;
+
+ visual = wVisual(pWin);
+ visclass = 0;
+ for (i = 0; i < pScreen->numVisuals; i++) {
+ if (pScreen->visuals[i].vid == visual) {
+ visclass = pScreen->visuals[i].class;
+ break;
+ }
+ }
+
+ wid = FFBWidAlloc(pFfb, visclass, wColormap(pWin), TRUE);
+ if (wid == (unsigned int) -1)
+ return FALSE;
+
+ CreatorUnaccelSetWid(pWin, wid);
+
+ return TRUE;
+}
+
+static void
+CreatorWidFree(WindowPtr pWin)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pWin->drawable.pScreen->myNum];
+ FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
+ unsigned int wid = CreatorUnaccelGetWid(pWin);
+
+ FFBWidFree(pFfb, wid);
+}
+
+static cfb8_32WidOps CreatorUnaccelWidOps = {
+ CreatorWidGet,
+ CreatorWidAlloc,
+ CreatorWidFree,
+ NULL,
+ NULL
+};
+
+static Bool
+CreatorUnaccelWidInit(ScreenPtr pScreen)
+{
+ if (serverGeneration != CreatorUnaccelGeneration) {
+ CreatorUnaccelWindowPrivateIndex =
+ AllocateWindowPrivateIndex();
+ if (CreatorUnaccelWindowPrivateIndex == -1)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* Mandatory */
+
+/* This gets called at the start of each server generation */
+
+static Bool
+FFBScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
+{
+ ScrnInfoPtr pScrn;
+ FFBPtr pFfb;
+ int ret;
+ unsigned int afb_fem;
+ VisualPtr visual;
+
+ /* Add in our Dbe hook. */
+ if (!FFBDbePreInit(pScreen))
+ return FALSE;
+
+ /*
+ * First get the ScrnInfoRec
+ */
+ pScrn = xf86Screens[pScreen->myNum];
+
+ pFfb = GET_FFB_FROM_SCRN(pScrn);
+
+ /* Map the FFB framebuffer, for each view. */
+
+ /* 24-bit RGB Dumb view */
+ pFfb->fb = pFfb->dfb24 =
+ xf86MapSbusMem (pFfb->psdp, FFB_DFB24_VOFF, 0x1000000);
+
+ if (! pFfb->dfb24)
+ return FALSE;
+
+ /* 8-bit R Dumb view */
+ pFfb->dfb8r =
+ xf86MapSbusMem (pFfb->psdp, FFB_DFB8R_VOFF, 0x400000);
+
+ if (! pFfb->dfb8r)
+ return FALSE;
+
+ /* 8-bit X Dumb view */
+ pFfb->dfb8x =
+ xf86MapSbusMem (pFfb->psdp, FFB_DFB8X_VOFF, 0x400000);
+
+ if (! pFfb->dfb8x)
+ return FALSE;
+
+ /* 32-bit RGB Smart view */
+ pFfb->sfb32 =
+ xf86MapSbusMem (pFfb->psdp, FFB_SFB32_VOFF, 0x1000000);
+
+ if (!pFfb->sfb32)
+ return FALSE;
+
+ /* 8-bit R Smart view */
+ pFfb->sfb8r =
+ xf86MapSbusMem(pFfb->psdp, FFB_SFB8R_VOFF, 0x400000);
+
+ if (!pFfb->sfb8r)
+ return FALSE;
+
+ /* 8-bit X Smart view */
+ pFfb->sfb8x =
+ xf86MapSbusMem(pFfb->psdp, FFB_SFB8X_VOFF, 0x400000);
+
+ if (!pFfb->sfb8x)
+ return FALSE;
+
+ /* Map the rendering pipeline */
+ pFfb->regs =
+ xf86MapSbusMem (pFfb->psdp, FFB_FBC_REGS_VOFF, 16384);
+
+ if (! pFfb->regs)
+ return FALSE;
+
+ /* Map the ramdac */
+ pFfb->dac =
+ xf86MapSbusMem (pFfb->psdp, FFB_DAC_VOFF, 8192);
+
+ if (! pFfb->dac)
+ return FALSE;
+
+ /* Map the board strapping bits */
+ pFfb->strapping_bits = (volatile unsigned int *)
+ xf86MapSbusMem(pFfb->psdp, FFB_EXP_VOFF, 8192);
+
+ if (! pFfb->strapping_bits)
+ return FALSE;
+
+ /* Probe for the type of FFB/AFB we have. */
+ FFBProbeBoardType(pFfb);
+
+ /* Now that we have the board type, we can init the ramdac layer. */
+ if (FFBDacInit(pFfb) == FALSE)
+ return FALSE;
+
+ /* OK, a fun gross hack to detect if this is
+ * AFB and if so whether the correct firmware
+ * has been loaded. The machine will flatline
+ * if you try to use certain acceleration features
+ * without the full firmware loaded.
+ *
+ * The bootup Elite3D/AFB firmware is minimal, and
+ * will leave the FloatEnableMask register at a
+ * value of 0x01. Creator{,3D} lacks the FEM register
+ * and will return a "nonsense" value on attempts to
+ * read this location. After experimentation, an
+ * appropriate definition for "nonsense" seems to
+ * be anything with all low 7 bits not 0x3f, 0x07,
+ * of 0x01.
+ *
+ * If the FEM register is non-zero and is some value
+ * other than 0x1 (usually 0x3f or 0x7 depending upon
+ * whether the card has 3 or 6 floats) we can assume
+ * the correct firmware has been loaded. -DaveM
+ */
+ afb_fem = *(unsigned int *)((char *)pFfb->regs + 0x1540);
+ if ((afb_fem & 0x7f) != 0x3f &&
+ (afb_fem & 0x7f) != 0x07 &&
+ (afb_fem & 0x7f) != 0x01)
+ xf86Msg(X_INFO, "%s: Detected Creator/Creator3D\n", pFfb->psdp->device);
+ else {
+ xf86Msg(X_INFO, "%s: Detected Elite3D M3/M6, checking firmware...\n", pFfb->psdp->device);
+ if (afb_fem == 0x1) {
+ xf86Msg(X_INFO, "%s: ... AFB firmware not loaded\n", pFfb->psdp->device);
+ if (!pFfb->NoAccel) {
+ xf86Msg(X_WARNING, "%s: Forcing no acceleration on Elite3D M3/M6\n", pFfb->psdp->device);
+ pFfb->NoAccel = TRUE;
+ }
+ } else
+ xf86Msg(X_INFO, "%s: ... AFB firmware is loaded\n", pFfb->psdp->device);
+ }
+
+ /* Darken the screen for aesthetic reasons and set the viewport */
+ FFBSaveScreen(pScreen, SCREEN_SAVER_ON);
+
+ if (pFfb->NoAccel == TRUE) {
+ if (!CreatorUnaccelWidInit(pScreen))
+ return FALSE;
+ }
+
+ /*
+ * The next step is to setup the screen's visuals, and initialise the
+ * framebuffer code. In cases where the framebuffer's default
+ * choices for things like visual layouts and bits per RGB are OK,
+ * this may be as simple as calling the framebuffer's ScreenInit()
+ * function. If not, the visuals will need to be setup before calling
+ * a fb ScreenInit() function and fixed up after.
+ */
+
+ /*
+ * Reset visual list.
+ */
+ miClearVisualTypes();
+
+ /* Setup the visuals we support. */
+ if (!miSetVisualTypes(24, TrueColorMask | DirectColorMask,
+ pScrn->rgbBits, TrueColor))
+ return FALSE;
+ if (!miSetVisualTypes(8, PseudoColorMask | GrayScaleMask | StaticGrayMask,
+ pScrn->rgbBits, PseudoColor))
+ return FALSE;
+
+#ifdef XF86DRI
+ if (pFfb->ffb_type != afb_m3 && pFfb->ffb_type != afb_m6 &&
+ pFfb->NoAccel == FALSE) {
+ pFfb->dri_enabled = FFBDRIScreenInit(pScreen);
+ if (pFfb->dri_enabled == TRUE)
+ xf86Msg(X_INFO, "%s: DRM initialized\n",
+ pFfb->psdp->device);
+ else
+ xf86Msg(X_INFO, "%s: DRM setup failed\n",
+ pFfb->psdp->device);
+ } else {
+ pFfb->dri_enabled = FALSE;
+ }
+#endif
+
+ /*
+ * Call the framebuffer layer's ScreenInit function, and fill in other
+ * pScreen fields.
+ */
+ if (pFfb->NoAccel == TRUE) {
+ ret = cfb8_32WidScreenInit(pScreen, pFfb->dfb24, pFfb->dfb8r, pFfb->dfb8x,
+ pScrn->virtualX, pScrn->virtualY,
+ pScrn->xDpi, pScrn->yDpi,
+ 2048, 2048, 2048, 8,
+ &CreatorUnaccelWidOps);
+ } else {
+ /* Use smart framebuffer aperture for cfb8/cfb32. */
+ ret = cfb8_32WidScreenInit(pScreen, pFfb->sfb32, pFfb->sfb8r, pFfb->dfb8x,
+ pScrn->virtualX, pScrn->virtualY,
+ pScrn->xDpi, pScrn->yDpi,
+ 2048, 2048, 2048, 8,
+ &CreatorUnaccelWidOps);
+ }
+
+ if (!ret)
+ return FALSE;
+
+ miInitializeBackingStore(pScreen);
+ xf86SetBackingStore(pScreen);
+ xf86SetSilkenMouse(pScreen);
+
+ xf86SetBlackWhitePixels(pScreen);
+
+ if (pScrn->bitsPerPixel > 8) {
+ /* Fixup RGB ordering */
+ visual = pScreen->visuals + pScreen->numVisuals;
+ while (--visual >= pScreen->visuals) {
+ if ((visual->class | DynamicClass) == DirectColor) {
+ visual->offsetRed = pScrn->offset.red;
+ visual->offsetGreen = pScrn->offset.green;
+ visual->offsetBlue = pScrn->offset.blue;
+ visual->redMask = pScrn->mask.red;
+ visual->greenMask = pScrn->mask.green;
+ visual->blueMask = pScrn->mask.blue;
+ }
+ }
+ }
+
+ if (!pFfb->NoAccel) {
+ if (!FFBAccelInit(pScreen, pFfb))
+ return FALSE;
+ xf86Msg(X_INFO, "%s: Using acceleration\n", pFfb->psdp->device);
+ }
+
+ /* Initialise cursor functions */
+ miDCInitialize (pScreen, xf86GetPointerScreenFuncs());
+
+ /* Initialize HW cursor layer.
+ * Must follow software cursor initialization.
+ */
+ if (pFfb->HWCursor) {
+ if(!FFBHWCursorInit(pScreen)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Hardware cursor initialization failed\n");
+ return(FALSE);
+ }
+ xf86SbusHideOsHwCursor(pFfb->psdp);
+ }
+
+ /* Initialise default colourmap. */
+ if (!miCreateDefColormap(pScreen))
+ return FALSE;
+
+ /* Initialize colormap layer.
+ * Must follow initialization of the default colormap.
+ */
+ if (!xf86HandleColormaps(pScreen, 256, 8,
+ FFBDacLoadPalette, NULL,
+#if 0
+ CMAP_PALETTED_TRUECOLOR |
+#endif
+ CMAP_LOAD_EVEN_IF_OFFSCREEN |
+ CMAP_RELOAD_ON_MODE_SWITCH))
+ return FALSE;
+
+ /* Setup DGA support. */
+ if (!pFfb->NoAccel)
+ FFB_InitDGA(pScreen);
+
+#ifdef XF86DRI
+ if (pFfb->dri_enabled) {
+ /* Now that mi, cfb, drm and others have done their thing,
+ * complete the DRI setup.
+ */
+ pFfb->dri_enabled = FFBDRIFinishScreenInit(pScreen);
+ if (pFfb->dri_enabled)
+ xf86Msg(X_INFO, "%s: DRM finish setup complete\n",
+ pFfb->psdp->device);
+ else
+ xf86Msg(X_INFO, "%s: DRM finish setup failed\n",
+ pFfb->psdp->device);
+ }
+#endif
+
+ pFfb->CloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = FFBCloseScreen;
+ pScreen->SaveScreen = FFBSaveScreen;
+
+ (void) xf86DPMSInit(pScreen, FFBDPMSMode, 0);
+
+ /* Report any unused options (only for the first generation) */
+ if (serverGeneration == 1) {
+ xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
+ }
+
+ /* unblank the screen */
+ FFBSaveScreen(pScreen, SCREEN_SAVER_OFF);
+
+ /* Done */
+ return TRUE;
+}
+
+
+/* Usually mandatory */
+static Bool
+FFBSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
+{
+ return TRUE;
+}
+
+
+/*
+ * This function is used to initialize the Start Address - the first
+ * displayed location in the video memory.
+ */
+/* Usually mandatory */
+static void
+FFBAdjustFrame(int scrnIndex, int x, int y, int flags)
+{
+ /* we don't support virtual desktops */
+ return;
+}
+
+/*
+ * This is called when VT switching back to the X server. Its job is
+ * to reinitialise the video mode.
+ */
+
+/* Mandatory */
+static Bool
+FFBEnterVT(int scrnIndex, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
+
+ pFfb->vtSema = FALSE;
+ if (!pFfb->NoAccel)
+ CreatorVtChange (pScrn->pScreen, TRUE);
+ if (pFfb->HWCursor)
+ xf86SbusHideOsHwCursor (pFfb->psdp);
+
+ FFBDacEnterVT(pFfb);
+
+ return TRUE;
+}
+
+
+/*
+ * This is called when VT switching away from the X server.
+ */
+
+/* Mandatory */
+static void
+FFBLeaveVT(int scrnIndex, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
+
+ FFBDacLeaveVT(pFfb);
+
+ if (!pFfb->NoAccel)
+ CreatorVtChange (pScrn->pScreen, FALSE);
+
+ if (pFfb->HWCursor)
+ xf86SbusHideOsHwCursor (pFfb->psdp);
+
+ pFfb->vtSema = TRUE;
+ return;
+}
+
+
+/*
+ * This is called at the end of each server generation. It restores the
+ * original (text) mode. It should really also unmap the video memory too.
+ */
+
+/* Mandatory */
+static Bool
+FFBCloseScreen(int scrnIndex, ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
+
+#ifdef XF86DRI
+ if (pFfb->dri_enabled)
+ FFBDRICloseScreen(pScreen);
+#endif
+
+ /* Restore kernel ramdac state before we unmap registers. */
+ FFBDacFini(pFfb);
+
+ pScrn->vtSema = FALSE;
+
+ xf86UnmapSbusMem(pFfb->psdp, pFfb->dfb24, 0x1000000);
+ xf86UnmapSbusMem(pFfb->psdp, pFfb->dfb8r, 0x400000);
+ xf86UnmapSbusMem(pFfb->psdp, pFfb->dfb8x, 0x400000);
+ xf86UnmapSbusMem(pFfb->psdp, pFfb->sfb32, 0x1000000);
+ xf86UnmapSbusMem(pFfb->psdp, pFfb->sfb8r, 0x400000);
+ xf86UnmapSbusMem(pFfb->psdp, pFfb->sfb8x, 0x400000);
+ xf86UnmapSbusMem(pFfb->psdp, pFfb->regs, 16384);
+ xf86UnmapSbusMem(pFfb->psdp, pFfb->dac, 8192);
+ xf86UnmapSbusMem(pFfb->psdp, (void *)pFfb->strapping_bits, 8192);
+
+ if (pFfb->HWCursor)
+ xf86SbusHideOsHwCursor (pFfb->psdp);
+
+ pScreen->CloseScreen = pFfb->CloseScreen;
+ return (*pScreen->CloseScreen)(scrnIndex, pScreen);
+}
+
+
+/* Free up any per-generation data structures */
+
+/* Optional */
+static void
+FFBFreeScreen(int scrnIndex, int flags)
+{
+ FFBFreeRec(xf86Screens[scrnIndex]);
+}
+
+
+/* Checks if a mode is suitable for the selected chipset. */
+
+/* Optional */
+static int
+FFBValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
+{
+ if (mode->Flags & V_INTERLACE)
+ return(MODE_BAD);
+
+ return(MODE_OK);
+}
+
+/* Do screen blanking */
+
+/* Mandatory */
+static Bool
+FFBSaveScreen(ScreenPtr pScreen, int mode)
+ /* This function blanks the screen when mode=SCREEN_SAVER_ON and
+ unblanks it when mode=SCREEN_SAVER_OFF. It is used internally in the
+ FFBScreenInit code `for aesthetic reasons,' and it is used for
+ blanking if you set "xset s on s blank." The work (such as it is) is
+ done in "ffb_dac.c" `for aesthetic reasons.'
+ */
+{
+ return FFBDacSaveScreen(GET_FFB_FROM_SCREEN(pScreen), mode);
+}
+
+/*
+ * This is the implementation of the Sync() function.
+ */
+void
+FFBSync(ScrnInfoPtr pScrn)
+{
+ return;
+}
+
+/*
+ Hook for DPMS Mode.
+*/
+
+static void
+FFBDPMSMode(ScrnInfoPtr pScrn, int DPMSMode, int flags)
+{
+ FFBDacDPMSMode(GET_FFB_FROM_SCRN(pScrn), DPMSMode, flags);
+}
diff --git a/src/ffb_fifo.h b/src/ffb_fifo.h
new file mode 100644
index 0000000..0957e84
--- /dev/null
+++ b/src/ffb_fifo.h
@@ -0,0 +1,69 @@
+/*
+ * Acceleration for the Creator and Creator3D framebuffer - fifo macros.
+ *
+ * Copyright (C) 1998,1999 Jakub Jelinek (jakub@redhat.com)
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * JAKUB JELINEK OR DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_fifo.h,v 1.2 2000/05/23 04:47:44 dawes Exp $ */
+
+#ifndef FFBFIFO_H
+#define FFBFIFO_H
+
+#include "ffb.h"
+
+/* This is the smallest FFB fifo size I know of. -DaveM */
+#define FFB_FIFO_MIN 124
+
+#define FFBFifo(__fpriv, __n) \
+do { int __cur_slots = (__fpriv)->fifo_cache; \
+ if((__cur_slots - (__n)) < 0) { \
+ ffb_fbcPtr __ffb = pFfb->regs; \
+ do { __cur_slots = (((int)__ffb->ucsr & FFB_UCSR_FIFO_MASK) - 4); \
+ } while((__cur_slots - (__n)) < 0); \
+ } (__fpriv)->fifo_cache = (__cur_slots - (__n)); \
+} while(0)
+
+/* While we are polling for the raster processor to idle, cache the
+ * fifo count as well.
+ */
+#define FFBWait(__fpriv, __ffb) \
+if ((__fpriv)->rp_active != 0) { \
+ unsigned int __regval = (__ffb)->ucsr; \
+ while((__regval & FFB_UCSR_RP_BUSY) != 0) { \
+ __regval = (__ffb)->ucsr; \
+ } \
+ (__fpriv)->fifo_cache = ((int)(__regval & FFB_UCSR_FIFO_MASK)) - 4; \
+ (__fpriv)->rp_active = 0; \
+} while(0)
+
+/* DEBUGGING: You can use this if you suspect corruption is occuring
+ * because someone is touching the framebuffer while the
+ * raster processor is active. If you enable this and the
+ * problem goes away, odds are your suspicions are correct.
+ */
+#undef FORCE_WAIT_EVERY_ROP
+#ifdef FORCE_WAIT_EVERY_ROP
+#define FFBSync(__fpriv, __ffb) FFBWait(__fpriv, __ffb)
+#else
+#define FFBSync(__fpriv, __ffb) do { } while(0)
+#endif
+
+#endif /* FFBFIFO_H */
diff --git a/src/ffb_frect.c b/src/ffb_frect.c
new file mode 100644
index 0000000..340efef
--- /dev/null
+++ b/src/ffb_frect.c
@@ -0,0 +1,709 @@
+/*
+ * Acceleration for the Creator and Creator3D framebuffer - Rectangle filling.
+ *
+ * Copyright (C) 1998,1999 Jakub Jelinek (jakub@redhat.com)
+ * Copyright (C) 1998 Michal Rehacek (majkl@iname.com)
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * JAKUB JELINEK, MICHAL REHACEK, OR DAVID MILLER BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_frect.c,v 1.3 2001/04/05 17:42:33 dawes Exp $ */
+
+#include "ffb.h"
+#include "ffb_regs.h"
+#include "ffb_rcache.h"
+#include "ffb_fifo.h"
+#include "ffb_stip.h"
+#include "ffb_loops.h"
+
+#include "pixmapstr.h"
+#include "scrnintstr.h"
+
+#define PSZ 8
+#include "cfb.h"
+#undef PSZ
+#include "cfb32.h"
+
+#define PAGEFILL_DISABLED(pFfb) ((pFfb)->disable_pagefill != 0)
+#define FASTFILL_AP_DISABLED(pFfb) ((pFfb)->disable_fastfill_ap != 0)
+
+void
+CreatorFillBoxStipple (DrawablePtr pDrawable, int nBox, BoxPtr pBox, CreatorStipplePtr stipple)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pDrawable->pScreen);
+ WindowPtr pWin = (WindowPtr) pDrawable;
+ ffb_fbcPtr ffb = pFfb->regs;
+ unsigned int bits[32];
+ unsigned int newalign;
+
+ FFBLOG(("CreatorFillBoxStipple: nbox(%d)\n", nBox));
+ newalign = ((pDrawable->y & 31) << 16) | (pDrawable->x & 31);
+ if (stipple->patalign != newalign) {
+ int x, y, i;
+
+ x = (pDrawable->x - (stipple->patalign & 0xffff)) & 31;
+ y = (pDrawable->y - (stipple->patalign >> 16)) & 31;
+ if (x | y) {
+ memcpy(bits, stipple->bits, sizeof(bits));
+ for (i = 0; i < 32; i++)
+ stipple->bits[(i + y) & 31] =
+ (bits[i] >> x) | (bits[i] << (32 - x));
+ stipple->inhw = 0;
+ }
+ stipple->patalign = newalign;
+ }
+
+ FFBSetStipple(pFfb, ffb, stipple,
+ FFB_PPC_APE_DISABLE|FFB_PPC_CS_CONST|FFB_PPC_XS_WID,
+ FFB_PPC_APE_MASK|FFB_PPC_CS_MASK|FFB_PPC_XS_MASK);
+ FFB_WRITE_PMASK(pFfb, ffb, ~0);
+ FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_RECTANGLE);
+ FFB_WRITE_FBC(pFfb, ffb, FFB_FBC_WIN(pWin));
+ FFB_WRITE_WID(pFfb, ffb, FFB_WID_WIN(pWin));
+
+ while(nBox--) {
+ register int x, y, w, h;
+
+ x = pBox->x1;
+ y = pBox->y1;
+ w = (pBox->x2 - x);
+ h = (pBox->y2 - y);
+ FFBFifo(pFfb, 4);
+ FFB_WRITE64(&ffb->by, y, x);
+ FFB_WRITE64_2(&ffb->bh, h, w);
+ pBox++;
+ }
+
+ pFfb->rp_active = 1;
+ FFBSync(pFfb, ffb);
+}
+
+enum ffb_fillrect_method { fillrect_page,
+ fillrect_fast, fillrect_fast_opaque,
+ fillrect_normal };
+
+#define BOX_AREA(__w, __h) ((int)(__w) * (int)(__h))
+
+/* Compute the page aligned box for a page mode fast fill.
+ * In 'ework' this returns greater than zero if there are some odd
+ * edges to take care of which are outside of the page aligned area.
+ * It will place less than zero there if the box is too small,
+ * indicating that a different method must be used to fill it.
+ */
+#define CreatorPageFillParms(pFfb, ffp, x, y, w, h, px, py, pw, ph, ework) \
+do { int xdiff, ydiff; \
+ int pf_bh = ffp->pagefill_height; \
+ int pf_bw = ffp->pagefill_width; \
+ py = ((y + (pf_bh - 1)) & ~(pf_bh - 1)); \
+ ydiff = py - y; \
+ px = pFfb->Pf_AlignTab[x + (pf_bw - 1)]; \
+ xdiff = px - x; \
+ ph = ((h - ydiff) & ~(pf_bh - 1)); \
+ if(ph <= 0) \
+ ework = -1; \
+ else { \
+ pw = pFfb->Pf_AlignTab[w - xdiff]; \
+ if(pw <= 0) { \
+ ework = -1; \
+ } else { \
+ ework = (((xdiff > 0) || \
+ (ydiff > 0) || \
+ ((w - pw) > 0) || \
+ ((h - ph) > 0))) ? 1 : 0; \
+ } \
+ } \
+} while(0);
+
+/* Compute fixups of non-page aligned areas after a page fill.
+ * Return the number of fixups needed.
+ */
+static __inline__ int
+CreatorComputePageFillFixups(xRectangle *fixups,
+ int x, int y, int w, int h,
+ int paligned_x, int paligned_y,
+ int paligned_w, int paligned_h)
+{
+ int nfixups = 0;
+
+ /* FastFill Left */
+ if(paligned_x != x) {
+ fixups[nfixups].x = x;
+ fixups[nfixups].y = paligned_y;
+ fixups[nfixups].width = paligned_x - x;
+ fixups[nfixups].height = paligned_h;
+ nfixups++;
+ }
+ /* FastFill Top */
+ if(paligned_y != y) {
+ fixups[nfixups].x = x;
+ fixups[nfixups].y = y;
+ fixups[nfixups].width = w;
+ fixups[nfixups].height = paligned_y - y;
+ nfixups++;
+ }
+ /* FastFill Right */
+ if((x+w) != (paligned_x+paligned_w)) {
+ fixups[nfixups].x = (paligned_x+paligned_w);
+ fixups[nfixups].y = paligned_y;
+ fixups[nfixups].width = (x+w) - fixups[nfixups].x;
+ fixups[nfixups].height = paligned_h;
+ nfixups++;
+ }
+ /* FastFill Bottom */
+ if((y+h) != (paligned_y+paligned_h)) {
+ fixups[nfixups].x = x;
+ fixups[nfixups].y = (paligned_y+paligned_h);
+ fixups[nfixups].width = w;
+ fixups[nfixups].height = (y+h) - fixups[nfixups].y;
+ nfixups++;
+ }
+ return nfixups;
+}
+
+/* Fill a set of boxes, pagefill and fastfill not allowed. */
+static void
+CreatorBoxFillNormal(FFBPtr pFfb,
+ int nbox, BoxPtr pbox)
+{
+ ffb_fbcPtr ffb = pFfb->regs;
+
+ FFBLOG(("BFNormal: "));
+ if(nbox)
+ FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_RECTANGLE);
+ while(nbox--) {
+ register int x, y, w, h;
+
+ x = pbox->x1;
+ y = pbox->y1;
+ w = (pbox->x2 - x);
+ h = (pbox->y2 - y);
+ pbox++;
+ FFBLOG(("[%08x:%08x:%08x:%08x] ", x, y, w, h));
+ FFBFifo(pFfb, 4);
+ FFB_WRITE64(&ffb->by, y, x);
+ FFB_WRITE64_2(&ffb->bh, h, w);
+ }
+ FFBLOG(("\n"));
+}
+
+/* Fill a set of boxes, only non-pagemode fastfill is allowed. */
+static void
+CreatorBoxFillFast(FFBPtr pFfb,
+ int nbox, BoxPtr pbox)
+{
+ ffb_fbcPtr ffb = pFfb->regs;
+
+ FFBLOG(("BFFast: "));
+ while(nbox--) {
+ struct fastfill_parms *ffp = &FFB_FFPARMS(pFfb);
+ register int x, y, w, h;
+
+ x = pbox->x1;
+ y = pbox->y1;
+ w = (pbox->x2 - x);
+ h = (pbox->y2 - y);
+ pbox++;
+ if(BOX_AREA(w, h) < ffp->fastfill_small_area) {
+ /* Too small for fastfill to be useful. */
+ FFBLOG(("NRM(%08x:%08x:%08x:%08x) ",
+ x, y, w, h));
+ FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_RECTANGLE);
+ FFBFifo(pFfb, 4);
+ FFB_WRITE64(&ffb->by, y, x);
+ FFB_WRITE64_2(&ffb->bh, h, w);
+ } else {
+ FFBLOG(("FST(%08x:%08x:%08x:%08x:[%08x:%08x]) ",
+ x, y, w, h,
+ (w + (x & (ffp->fastfill_width - 1))),
+ (h + (y & (ffp->fastfill_height - 1)))));
+ if (pFfb->ffb_res == ffb_res_high &&
+ ((x & 7) != 0 || (w & 7) != 0)) {
+ FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_RECTANGLE);
+ if ((x & 7) != 0) {
+ register int nx = x;
+ register int nw;
+
+ nw = 8 - (nx & 7);
+ if (nw > w)
+ nw = w;
+ FFBFifo(pFfb, 4);
+ FFB_WRITE64(&ffb->by, y, nx);
+ FFB_WRITE64_2(&ffb->bh, h, nw);
+ x += nw;
+ w -= nw;
+ }
+ if ((w & 7) != 0) {
+ register int nx, nw;
+
+ nw = (w & 7);
+ nx = x + (w - nw);
+ FFBFifo(pFfb, 4);
+ FFB_WRITE64(&ffb->by, y, nx);
+ FFB_WRITE64_2(&ffb->bh, h, nw);
+ w -= nw;
+ }
+ if (w <= 0)
+ goto next_rect;
+ }
+ FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_FASTFILL);
+ FFBFifo(pFfb, 10);
+ ffb->by = FFB_FASTFILL_COLOR_BLK;
+ FFB_WRITE64(&ffb->dy, 0, 0);
+ FFB_WRITE64_2(&ffb->bh,
+ ffp->fastfill_height,
+ (ffp->fastfill_width * 4));
+ FFB_WRITE64_3(&ffb->dy, y, x);
+ ffb->bh = (h + (y & (ffp->fastfill_height - 1)));
+ FFB_WRITE64(&ffb->by, FFB_FASTFILL_BLOCK,
+ (w + (x & (ffp->fastfill_width - 1))));
+ }
+ next_rect:
+ ;
+ }
+ FFBLOG(("\n"));
+}
+
+/* Fill a set of boxes, any fastfill method is allowed. */
+static void
+CreatorBoxFillPage(FFBPtr pFfb,
+ int nbox, BoxPtr pbox)
+{
+ ffb_fbcPtr ffb = pFfb->regs;
+
+ FFBLOG(("BFPage: "));
+ while(nbox--) {
+ struct fastfill_parms *ffp = &FFB_FFPARMS(pFfb);
+ register int x, y, w, h;
+
+ x = pbox->x1;
+ y = pbox->y1;
+ w = (pbox->x2 - x);
+ h = (pbox->y2 - y);
+ pbox++;
+ if(BOX_AREA(w, h) < ffp->fastfill_small_area) {
+ /* Too small for fastfill or page fill to be useful. */
+ FFBLOG(("NRM(%08x:%08x:%08x:%08x) ",
+ x, y, w, h));
+ FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_RECTANGLE);
+ FFBFifo(pFfb, 4);
+ FFB_WRITE64(&ffb->by, y, x);
+ FFB_WRITE64_2(&ffb->bh, h, w);
+ } else {
+ int paligned_y, paligned_x;
+ int paligned_h, paligned_w = 0;
+ int extra_work;
+
+ if (pFfb->ffb_res == ffb_res_high &&
+ ((x & 7) != 0 || (w & 7) != 0)) {
+ FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_RECTANGLE);
+ if ((x & 7) != 0) {
+ register int nx = x;
+ register int nw;
+
+ nw = 8 - (nx & 7);
+ if (nw > w)
+ nw = w;
+ FFBFifo(pFfb, 4);
+ FFB_WRITE64(&ffb->by, y, nx);
+ FFB_WRITE64_2(&ffb->bh, h, nw);
+ x += nw;
+ w -= nw;
+ }
+ if ((w & 7) != 0) {
+ register int nx, nw;
+
+ nw = (w & 7);
+ nx = x + (w - nw);
+ FFBFifo(pFfb, 4);
+ FFB_WRITE64(&ffb->by, y, nx);
+ FFB_WRITE64_2(&ffb->bh, h, nw);
+ w -= nw;
+ }
+ if (w <= 0)
+ goto next_rect;
+ }
+
+ FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_FASTFILL);
+ if((w < (ffp->pagefill_width<<1)) ||
+ (h < (ffp->pagefill_height<<1)))
+ goto do_fastfill;
+
+ CreatorPageFillParms(pFfb, ffp,
+ x, y, w, h,
+ paligned_x, paligned_y,
+ paligned_w, paligned_h, extra_work);
+
+ /* See if the aligned area is large enough for
+ * page fill to be worthwhile.
+ */
+ if(extra_work < 0 ||
+ BOX_AREA(paligned_w, paligned_h) < ffp->pagefill_small_area) {
+ do_fastfill:
+ FFBLOG(("FST(%08x:%08x:%08x:%08x:[%08x:%08x]) ",
+ x, y, w, h,
+ (w + (x & (ffp->fastfill_width - 1))),
+ (h + (y & (ffp->fastfill_height - 1)))));
+ FFBFifo(pFfb, 10);
+ ffb->by = FFB_FASTFILL_COLOR_BLK;
+ FFB_WRITE64(&ffb->dy, 0, 0);
+ FFB_WRITE64_2(&ffb->bh,
+ ffp->fastfill_height,
+ (ffp->fastfill_width * 4));
+ FFB_WRITE64_3(&ffb->dy, y, x);
+ ffb->bh = (h + (y & (ffp->fastfill_height - 1)));
+ FFB_WRITE64(&ffb->by, FFB_FASTFILL_BLOCK,
+ (w + (x & (ffp->fastfill_width - 1))));
+ } else {
+ /* Ok, page fill is worth it, let it rip. */
+ FFBLOG(("PAG(%08x:%08x:%08x:%08x) ",
+ paligned_x, paligned_y, paligned_w, paligned_h));
+ FFBFifo(pFfb, 15);
+ ffb->by = FFB_FASTFILL_COLOR_BLK;
+ FFB_WRITE64(&ffb->dy, 0, 0);
+ FFB_WRITE64_2(&ffb->bh, ffp->fastfill_height, (ffp->fastfill_width * 4));
+ ffb->by = FFB_FASTFILL_BLOCK_X;
+ FFB_WRITE64(&ffb->dy, 0, 0);
+ FFB_WRITE64_2(&ffb->bh, ffp->pagefill_height, (ffp->pagefill_width * 4));
+ FFB_WRITE64_3(&ffb->dy, paligned_y, paligned_x);
+ ffb->bh = paligned_h;
+ FFB_WRITE64(&ffb->by, FFB_FASTFILL_PAGE, paligned_w);
+
+ if(extra_work) {
+ register int nfixups;
+
+ /* Ok, we're going to do at least one fixup. */
+ nfixups = CreatorComputePageFillFixups(pFfb->Pf_Fixups,
+ x, y, w, h,
+ paligned_x, paligned_y,
+ paligned_w, paligned_h);
+
+ /* NOTE: For the highres case we have already
+ * aligned the outermost X and W coordinates.
+ * Therefore we can be assured that the fixup
+ * X and W coordinates below will be 8 pixel
+ * aligned as well. Do the math, it works. -DaveM
+ */
+
+ FFBFifo(pFfb, 5 + (nfixups * 5));
+ ffb->by = FFB_FASTFILL_COLOR_BLK;
+ FFB_WRITE64(&ffb->dy, 0, 0);
+ FFB_WRITE64_2(&ffb->bh, ffp->fastfill_height, (ffp->fastfill_width * 4));
+
+ while(--nfixups >= 0) {
+ register int xx, yy, ww, hh;
+
+ xx = pFfb->Pf_Fixups[nfixups].x;
+ yy = pFfb->Pf_Fixups[nfixups].y;
+ FFB_WRITE64(&ffb->dy, yy, xx);
+ ww = (pFfb->Pf_Fixups[nfixups].width +
+ (xx & (ffp->fastfill_width - 1)));
+ hh = (pFfb->Pf_Fixups[nfixups].height +
+ (yy & (ffp->fastfill_height - 1)));
+ FFBLOG(("FIXUP(%08x:%08x:%08x:%08x) ",
+ xx, yy, ww, hh));
+ if(nfixups != 0) {
+ ffb->by = FFB_FASTFILL_BLOCK;
+ FFB_WRITE64_2(&ffb->bh, hh, ww);
+ } else {
+ ffb->bh = hh;
+ FFB_WRITE64(&ffb->by, FFB_FASTFILL_BLOCK, ww);
+ }
+ }
+ }
+ }
+ }
+ next_rect:
+ ;
+ }
+ FFBLOG(("\n"));
+}
+
+void
+CreatorFillBoxSolid (DrawablePtr pDrawable, int nBox, BoxPtr pBox, unsigned long pixel)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pDrawable->pScreen);
+ WindowPtr pWin = (WindowPtr) pDrawable;
+
+ FFBLOG(("CreatorFillBoxSolid: nbox(%d)\n", nBox));
+ FFB_ATTR_FFWIN(pFfb, pWin,
+ FFB_PPC_APE_DISABLE | FFB_PPC_CS_CONST,
+ pixel);
+ if (PAGEFILL_DISABLED(pFfb))
+ CreatorBoxFillNormal(pFfb, nBox, pBox);
+ else
+ CreatorBoxFillPage(pFfb, nBox, pBox);
+
+ pFfb->rp_active = 1;
+ FFBSync(pFfb, pFfb->regs);
+}
+
+static void
+FFBSetStippleFast(FFBPtr pFfb, ffb_fbcPtr ffb,
+ CreatorStipplePtr stipple,
+ unsigned int ppc, unsigned int ppc_mask)
+{
+ ppc |= FFB_PPC_APE_ENABLE | FFB_PPC_TBE_TRANSPARENT | FFB_PPC_XS_WID;
+ ppc_mask |= FFB_PPC_APE_MASK | FFB_PPC_TBE_MASK | FFB_PPC_XS_MASK;
+ FFB_WRITE_PPC(pFfb, ffb, ppc, ppc_mask);
+ FFB_WRITE_ROP(pFfb, ffb, (FFB_ROP_EDIT_BIT|stipple->alu)|(FFB_ROP_NEW<<8));
+ FFB_WRITE_FG(pFfb, ffb, stipple->fg);
+ FFBFifo(pFfb, 32);
+ FFB_STIPPLE_LOAD(&ffb->pattern[0], &stipple->bits[0]);
+}
+
+static void
+FFBSetStippleFastIdentity(FFBPtr pFfb,
+ ffb_fbcPtr ffb,
+ CreatorStipplePtr stipple)
+{
+ int i;
+
+ FFB_WRITE_FG(pFfb, ffb, stipple->bg);
+ FFBFifo(pFfb, 32);
+ for(i = 0; i < 32; i++)
+ ffb->pattern[i] = ~stipple->bits[i];
+ stipple->inhw = 0;
+ pFfb->laststipple = NULL;
+}
+
+void
+CreatorPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill, xRectangle *prectInit)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pDrawable->pScreen);
+ ffb_fbcPtr ffb = pFfb->regs;
+ xRectangle *prect;
+ RegionPtr prgnClip;
+ register BoxPtr pbox;
+ register BoxPtr pboxClipped;
+ BoxPtr pboxClippedBase;
+ BoxPtr pextent;
+ CreatorPrivGCPtr gcPriv;
+ int numRects;
+ int n;
+ int xorg, yorg;
+
+ /* No garbage please. */
+ if (nrectFill <= 0)
+ return;
+
+ gcPriv = CreatorGetGCPrivate (pGC);
+ FFBLOG(("CreatorPolyFillRect: nrect(%d) ALU(%x) STIP(%p) pmsk(%08x)\n",
+ nrectFill, pGC->alu, gcPriv->stipple, pGC->planemask));
+ prgnClip = cfbGetCompositeClip(pGC);
+ prect = prectInit;
+ xorg = pDrawable->x;
+ yorg = pDrawable->y;
+ if (xorg || yorg) {
+ prect = prectInit;
+ n = nrectFill;
+ while (n--) {
+ prect->x += xorg;
+ prect->y += yorg;
+ prect++;
+ }
+ }
+
+ prect = prectInit;
+ numRects = REGION_NUM_RECTS (prgnClip) * nrectFill;
+ if (numRects > 64) {
+ pboxClippedBase = (BoxPtr)ALLOCATE_LOCAL(numRects * sizeof(BoxRec));
+ if (!pboxClippedBase)
+ return;
+ } else
+ pboxClippedBase = pFfb->ClippedBoxBuf;
+
+ pboxClipped = pboxClippedBase;
+ if (REGION_NUM_RECTS(prgnClip) == 1) {
+ int x1, y1, x2, y2, bx2, by2;
+
+ pextent = REGION_RECTS(prgnClip);
+ x1 = pextent->x1;
+ y1 = pextent->y1;
+ x2 = pextent->x2;
+ y2 = pextent->y2;
+ while (nrectFill--) {
+ if ((pboxClipped->x1 = prect->x) < x1)
+ pboxClipped->x1 = x1;
+
+ if ((pboxClipped->y1 = prect->y) < y1)
+ pboxClipped->y1 = y1;
+
+ bx2 = (int) prect->x + (int) prect->width;
+ if (bx2 > x2)
+ bx2 = x2;
+ pboxClipped->x2 = bx2;
+
+ by2 = (int) prect->y + (int) prect->height;
+ if (by2 > y2)
+ by2 = y2;
+ pboxClipped->y2 = by2;
+
+ prect++;
+ if ((pboxClipped->x1 < pboxClipped->x2) &&
+ (pboxClipped->y1 < pboxClipped->y2))
+ pboxClipped++;
+ }
+ } else {
+ int x1, y1, x2, y2, bx2, by2;
+
+ pextent = REGION_EXTENTS(pGC->pScreen, prgnClip);
+ x1 = pextent->x1;
+ y1 = pextent->y1;
+ x2 = pextent->x2;
+ y2 = pextent->y2;
+ while (nrectFill--) {
+ BoxRec box;
+
+ if ((box.x1 = prect->x) < x1)
+ box.x1 = x1;
+
+ if ((box.y1 = prect->y) < y1)
+ box.y1 = y1;
+
+ bx2 = (int) prect->x + (int) prect->width;
+ if (bx2 > x2)
+ bx2 = x2;
+ box.x2 = bx2;
+
+ by2 = (int) prect->y + (int) prect->height;
+ if (by2 > y2)
+ by2 = y2;
+ box.y2 = by2;
+
+ prect++;
+
+ if ((box.x1 >= box.x2) || (box.y1 >= box.y2))
+ continue;
+
+ n = REGION_NUM_RECTS (prgnClip);
+ pbox = REGION_RECTS(prgnClip);
+
+ /* Clip the rectangle to each box in the clip region
+ * this is logically equivalent to calling Intersect()
+ */
+ while(n--) {
+ pboxClipped->x1 = max(box.x1, pbox->x1);
+ pboxClipped->y1 = max(box.y1, pbox->y1);
+ pboxClipped->x2 = min(box.x2, pbox->x2);
+ pboxClipped->y2 = min(box.y2, pbox->y2);
+ pbox++;
+
+ /* see if clipping left anything */
+ if(pboxClipped->x1 < pboxClipped->x2 &&
+ pboxClipped->y1 < pboxClipped->y2)
+ pboxClipped++;
+ }
+ }
+ }
+ /* Now fill the pre-clipped boxes. */
+ if(pboxClipped != pboxClippedBase) {
+ enum ffb_fillrect_method how = fillrect_page;
+ int num = (pboxClipped - pboxClippedBase);
+ int f_w = pboxClippedBase->x2 - pboxClippedBase->x1;
+ int f_h = pboxClippedBase->y2 - pboxClippedBase->y1;
+ WindowPtr pWin = (WindowPtr) pDrawable;
+ unsigned int fbc = FFB_FBC_WIN(pWin);
+ unsigned int drawop = FFB_DRAWOP_FASTFILL;
+
+ if (PAGEFILL_DISABLED(pFfb) ||
+ pGC->alu != GXcopy ||
+ BOX_AREA(f_w, f_h) < 128) {
+ drawop = FFB_DRAWOP_RECTANGLE;
+ how = fillrect_normal;
+ } else if (gcPriv->stipple != NULL) {
+ if (FASTFILL_AP_DISABLED(pFfb)) {
+ drawop = FFB_DRAWOP_RECTANGLE;
+ how = fillrect_normal;
+ } else {
+ if ((gcPriv->stipple->alu & FFB_ROP_EDIT_BIT) != 0)
+ how = fillrect_fast;
+ else
+ how = fillrect_fast_opaque;
+ }
+ } else {
+ int all_planes;
+
+ /* Plane masks are not controllable with page fills. */
+ if (pGC->depth == 8)
+ all_planes = 0xff;
+ else
+ all_planes = 0xffffff;
+ if ((pGC->planemask & all_planes) != all_planes)
+ how = fillrect_fast;
+ }
+
+ if (how == fillrect_page) {
+ fbc &= ~(FFB_FBC_XE_MASK | FFB_FBC_RGBE_MASK);
+ fbc |= FFB_FBC_XE_ON | FFB_FBC_RGBE_ON;
+ }
+
+ /* In the high-resolution modes, the Creator3D transforms
+ * the framebuffer such that the dual-buffers present become
+ * one large single buffer. As such you need to enable both
+ * A and B write buffers for page/fast fills to work properly
+ * under this configuration. -DaveM
+ */
+ if (pFfb->ffb_res == ffb_res_high)
+ fbc |= FFB_FBC_WB_B;
+
+ /* Setup the attributes. */
+ if (gcPriv->stipple == NULL) {
+ FFB_ATTR_RAW(pFfb,
+ FFB_PPC_APE_DISABLE|FFB_PPC_CS_CONST|FFB_PPC_XS_WID,
+ FFB_PPC_APE_MASK|FFB_PPC_CS_MASK|FFB_PPC_XS_MASK,
+ pGC->planemask,
+ ((FFB_ROP_EDIT_BIT|pGC->alu)|(FFB_ROP_NEW<<8)),
+ drawop,
+ pGC->fgPixel,
+ fbc, FFB_WID_WIN(pWin));
+ } else {
+ if (how == fillrect_fast_opaque) {
+ FFBSetStippleFast(pFfb, ffb, gcPriv->stipple,
+ FFB_PPC_CS_CONST|FFB_PPC_XS_WID,
+ FFB_PPC_CS_MASK|FFB_PPC_XS_MASK);
+ } else {
+ FFBSetStipple(pFfb, ffb, gcPriv->stipple,
+ FFB_PPC_CS_CONST|FFB_PPC_XS_WID,
+ FFB_PPC_CS_MASK|FFB_PPC_XS_MASK);
+ }
+ FFB_WRITE_DRAWOP(pFfb, ffb, drawop);
+ FFB_WRITE_FBC(pFfb, ffb, fbc);
+ FFB_WRITE_WID(pFfb, ffb, FFB_WID_WIN(pWin));
+ }
+
+ /* Now render. */
+ if(how == fillrect_normal)
+ CreatorBoxFillNormal(pFfb, num, pboxClippedBase);
+ else if(how == fillrect_fast || how == fillrect_fast_opaque)
+ CreatorBoxFillFast(pFfb, num, pboxClippedBase);
+ else
+ CreatorBoxFillPage(pFfb, num, pboxClippedBase);
+
+ if(how == fillrect_fast_opaque) {
+ FFBSetStippleFastIdentity(pFfb, ffb, gcPriv->stipple);
+ CreatorBoxFillFast(pFfb, num, pboxClippedBase);
+ }
+
+ pFfb->rp_active = 1;
+ FFBSync(pFfb, ffb);
+ }
+ if (pboxClippedBase != pFfb->ClippedBoxBuf)
+ DEALLOCATE_LOCAL (pboxClippedBase);
+}
diff --git a/src/ffb_fspans.c b/src/ffb_fspans.c
new file mode 100644
index 0000000..4599015
--- /dev/null
+++ b/src/ffb_fspans.c
@@ -0,0 +1,121 @@
+/*
+ * Acceleration for the Creator and Creator3D framebuffer - Fill spans.
+ *
+ * Copyright (C) 1998,1999 Jakub Jelinek (jakub@redhat.com)
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * JAKUB JELINEK OR DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_fspans.c,v 1.2 2000/05/23 04:47:44 dawes Exp $ */
+
+#include "ffb.h"
+#include "ffb_regs.h"
+#include "ffb_rcache.h"
+#include "ffb_fifo.h"
+#include "ffb_stip.h"
+#include "ffb_loops.h"
+
+#include "pixmapstr.h"
+#include "scrnintstr.h"
+
+#include "mi.h"
+#include "mispans.h"
+
+#define PSZ 8
+#include "cfb.h"
+#undef PSZ
+#include "cfb32.h"
+
+void
+CreatorFillSpans (DrawablePtr pDrawable, GCPtr pGC,
+ int n, DDXPointPtr ppt,
+ int *pwidth, int fSorted)
+{
+ WindowPtr pWin = (WindowPtr) pDrawable;
+ CreatorPrivGCPtr gcPriv = CreatorGetGCPrivate (pGC);
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pGC->pScreen);
+ ffb_fbcPtr ffb = pFfb->regs;
+ int *pwidthFree;
+ DDXPointPtr pptFree;
+ RegionPtr clip = cfbGetCompositeClip(pGC);
+ int nTmp = n * miFindMaxBand(clip);
+
+ FFBLOG(("CreatorFillSpans: n(%d) fsorted(%d)\n", n, fSorted));
+ pwidthFree = (int *)ALLOCATE_LOCAL(nTmp * sizeof(int));
+ pptFree = (DDXPointRec *)ALLOCATE_LOCAL(nTmp * sizeof(DDXPointRec));
+ if (!pptFree || !pwidthFree) {
+ if (pptFree) DEALLOCATE_LOCAL(pptFree);
+ if (pwidthFree) DEALLOCATE_LOCAL(pwidthFree);
+ return;
+ }
+ n = miClipSpans(clip,
+ ppt, pwidth, n,
+ pptFree, pwidthFree, fSorted);
+ pwidth = pwidthFree;
+ ppt = pptFree;
+ if(gcPriv->stipple == NULL) {
+ FFB_ATTR_GC(pFfb, pGC, pWin,
+ FFB_PPC_APE_DISABLE | FFB_PPC_CS_CONST,
+ FFB_DRAWOP_BRLINEOPEN);
+ } else {
+ unsigned int fbc;
+
+ FFBSetStipple(pFfb, ffb, gcPriv->stipple,
+ FFB_PPC_CS_CONST, FFB_PPC_CS_MASK);
+ FFB_WRITE_PMASK(pFfb, ffb, pGC->planemask);
+ FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_BRLINEOPEN);
+ fbc = FFB_FBC_WIN(pWin);
+ fbc = (fbc & ~FFB_FBC_XE_MASK) | FFB_FBC_XE_OFF;
+ FFB_WRITE_FBC(pFfb, ffb, fbc);
+ }
+ FFBFifo(pFfb, 1);
+ ffb->lpat = 0;
+
+ if (pFfb->has_brline_bug) {
+ while(n--) {
+ register int x, y, w;
+
+ x = ppt->x;
+ y = ppt->y;
+ w = *pwidth++;
+ FFBFifo(pFfb, 5);
+ ffb->ppc = 0;
+ FFB_WRITE64(&ffb->by, y, x);
+ FFB_WRITE64_2(&ffb->bh, y, (x + w));
+ ppt++;
+ }
+ } else {
+ while(n--) {
+ register int x, y, w;
+
+ x = ppt->x;
+ y = ppt->y;
+ w = *pwidth++;
+ FFBFifo(pFfb, 4);
+ FFB_WRITE64(&ffb->by, y, x);
+ FFB_WRITE64_2(&ffb->bh, y, (x + w));
+ ppt++;
+ }
+ }
+
+ DEALLOCATE_LOCAL(pptFree);
+ DEALLOCATE_LOCAL(pwidthFree);
+ pFfb->rp_active = 1;
+ FFBSync(pFfb, ffb);
+}
diff --git a/src/ffb_gc.c b/src/ffb_gc.c
new file mode 100644
index 0000000..235f649
--- /dev/null
+++ b/src/ffb_gc.c
@@ -0,0 +1,754 @@
+/*
+ * Acceleration for the Creator and Creator3D framebuffer - GC implementation.
+ *
+ * Copyright (C) 1998,1999,2000 Jakub Jelinek (jakub@redhat.com)
+ * Copyright (C) 1998 Michal Rehacek (majkl@iname.com)
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * JAKUB JELINEK, MICHAL REHACEK, OR DAVID MILLER BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_gc.c,v 1.3 2000/12/01 00:24:34 dawes Exp $ */
+
+#include "ffb.h"
+#include "ffb_regs.h"
+#include "ffb_rcache.h"
+#include "ffb_fifo.h"
+#include "ffb_loops.h"
+#include "ffb_gc.h"
+
+#include "scrnintstr.h"
+#include "pixmapstr.h"
+#include "fontstruct.h"
+#include "dixfontstr.h"
+
+#define PSZ 8
+#include "cfb.h"
+#undef PSZ
+#include "cfb32.h"
+
+#include "migc.h"
+#include "mi.h"
+#include "mispans.h"
+
+GCOps CreatorTEOps1Rect8 = {
+ CreatorFillSpans,
+ CreatorSetSpans,
+ cfbPutImage,
+ CreatorCopyArea,
+ CreatorCopyPlane,
+ CreatorPolyPoint,
+ CreatorPolylines,
+ CreatorPolySegment,
+ miPolyRectangle,
+ CreatorZeroPolyArc,
+ CreatorFillPolygon,
+ CreatorPolyFillRect,
+ CreatorPolyFillArcSolid,
+ miPolyText8,
+ miPolyText16,
+ miImageText8,
+ miImageText16,
+ CreatorTEGlyphBlt,
+ CreatorPolyTEGlyphBlt,
+ miPushPixels
+#ifdef NEED_LINEHELPER
+ ,NULL
+#endif
+};
+
+GCOps CreatorTEOps1Rect32 = {
+ CreatorFillSpans,
+ CreatorSetSpans,
+ cfb32PutImage,
+ CreatorCopyArea,
+ CreatorCopyPlane,
+ CreatorPolyPoint,
+ CreatorPolylines,
+ CreatorPolySegment,
+ miPolyRectangle,
+ CreatorZeroPolyArc,
+ CreatorFillPolygon,
+ CreatorPolyFillRect,
+ CreatorPolyFillArcSolid,
+ miPolyText8,
+ miPolyText16,
+ miImageText8,
+ miImageText16,
+ CreatorTEGlyphBlt,
+ CreatorPolyTEGlyphBlt,
+ miPushPixels
+#ifdef NEED_LINEHELPER
+ ,NULL
+#endif
+};
+
+GCOps CreatorTEOps8 = {
+ CreatorFillSpans,
+ CreatorSetSpans,
+ cfbPutImage,
+ CreatorCopyArea,
+ CreatorCopyPlane,
+ CreatorPolyPoint,
+ CreatorLineSSStub,
+ CreatorSegmentSSStub,
+ miPolyRectangle,
+ CreatorZeroPolyArc,
+ CreatorFillPolygon,
+ CreatorPolyFillRect,
+ CreatorPolyFillArcSolid,
+ miPolyText8,
+ miPolyText16,
+ miImageText8,
+ miImageText16,
+ CreatorTEGlyphBlt,
+ CreatorPolyTEGlyphBlt,
+ miPushPixels
+#ifdef NEED_LINEHELPER
+ ,NULL
+#endif
+};
+
+GCOps CreatorTEOps32 = {
+ CreatorFillSpans,
+ CreatorSetSpans,
+ cfb32PutImage,
+ CreatorCopyArea,
+ CreatorCopyPlane,
+ CreatorPolyPoint,
+ CreatorLineSSStub,
+ CreatorSegmentSSStub,
+ miPolyRectangle,
+ CreatorZeroPolyArc,
+ CreatorFillPolygon,
+ CreatorPolyFillRect,
+ CreatorPolyFillArcSolid,
+ miPolyText8,
+ miPolyText16,
+ miImageText8,
+ miImageText16,
+ CreatorTEGlyphBlt,
+ CreatorPolyTEGlyphBlt,
+ miPushPixels
+#ifdef NEED_LINEHELPER
+ ,NULL
+#endif
+};
+
+GCOps CreatorNonTEOps1Rect8 = {
+ CreatorFillSpans,
+ CreatorSetSpans,
+ cfbPutImage,
+ CreatorCopyArea,
+ CreatorCopyPlane,
+ CreatorPolyPoint,
+ CreatorPolylines,
+ CreatorPolySegment,
+ miPolyRectangle,
+ CreatorZeroPolyArc,
+ CreatorFillPolygon,
+ CreatorPolyFillRect,
+ CreatorPolyFillArcSolid,
+ miPolyText8,
+ miPolyText16,
+ miImageText8,
+ miImageText16,
+ miImageGlyphBlt,
+ CreatorPolyGlyphBlt,
+ miPushPixels
+#ifdef NEED_LINEHELPER
+ ,NULL
+#endif
+};
+
+GCOps CreatorNonTEOps1Rect32 = {
+ CreatorFillSpans,
+ CreatorSetSpans,
+ cfb32PutImage,
+ CreatorCopyArea,
+ CreatorCopyPlane,
+ CreatorPolyPoint,
+ CreatorPolylines,
+ CreatorPolySegment,
+ miPolyRectangle,
+ CreatorZeroPolyArc,
+ CreatorFillPolygon,
+ CreatorPolyFillRect,
+ CreatorPolyFillArcSolid,
+ miPolyText8,
+ miPolyText16,
+ miImageText8,
+ miImageText16,
+ miImageGlyphBlt,
+ CreatorPolyGlyphBlt,
+ miPushPixels
+#ifdef NEED_LINEHELPER
+ ,NULL
+#endif
+};
+
+GCOps CreatorNonTEOps8 = {
+ CreatorFillSpans,
+ CreatorSetSpans,
+ cfbPutImage,
+ CreatorCopyArea,
+ CreatorCopyPlane,
+ CreatorPolyPoint,
+ CreatorLineSSStub,
+ CreatorSegmentSSStub,
+ miPolyRectangle,
+ CreatorZeroPolyArc,
+ CreatorFillPolygon,
+ CreatorPolyFillRect,
+ CreatorPolyFillArcSolid,
+ miPolyText8,
+ miPolyText16,
+ miImageText8,
+ miImageText16,
+ miImageGlyphBlt,
+ CreatorPolyGlyphBlt,
+ miPushPixels
+#ifdef NEED_LINEHELPER
+ ,NULL
+#endif
+};
+
+GCOps CreatorNonTEOps32 = {
+ CreatorFillSpans,
+ CreatorSetSpans,
+ cfb32PutImage,
+ CreatorCopyArea,
+ CreatorCopyPlane,
+ CreatorPolyPoint,
+ CreatorLineSSStub,
+ CreatorSegmentSSStub,
+ miPolyRectangle,
+ CreatorZeroPolyArc,
+ CreatorFillPolygon,
+ CreatorPolyFillRect,
+ CreatorPolyFillArcSolid,
+ miPolyText8,
+ miPolyText16,
+ miImageText8,
+ miImageText16,
+ miImageGlyphBlt,
+ CreatorPolyGlyphBlt,
+ miPushPixels
+#ifdef NEED_LINEHELPER
+ ,NULL
+#endif
+};
+
+#define FONTWIDTH(font) (FONTMAXBOUNDS(font,rightSideBearing) - \
+ FONTMINBOUNDS(font,leftSideBearing))
+#define FONTHEIGHT(font) (FONTMAXBOUNDS(font,ascent) + \
+ FONTMINBOUNDS(font,descent))
+
+static GCOps *
+CreatorMatchCommon (GCPtr pGC, cfbPrivGCPtr devPriv)
+{
+ int depth = pGC->depth;
+
+ if (pGC->lineWidth != 0) return 0;
+ if (pGC->lineStyle != LineSolid) return 0;
+ if (pGC->fillStyle != FillSolid) return 0;
+ if (devPriv->rop != GXcopy) return 0;
+ if (pGC->font &&
+ FONTWIDTH (pGC->font) <= 32 &&
+ FONTHEIGHT (pGC->font) <= 100 &&
+ FONTMINBOUNDS(pGC->font,characterWidth) >= 0) {
+ if (TERMINALFONT(pGC->font)) {
+ if (devPriv->oneRect) {
+ return (depth == 8 ?
+ &CreatorTEOps1Rect8 :
+ &CreatorTEOps1Rect32);
+ } else {
+ return (depth == 8 ?
+ &CreatorTEOps8 :
+ &CreatorTEOps32);
+ }
+ } else {
+ if (devPriv->oneRect) {
+ return (depth == 8 ?
+ &CreatorNonTEOps1Rect8 :
+ &CreatorNonTEOps1Rect32);
+ } else {
+ return (depth == 8 ?
+ &CreatorNonTEOps8 :
+ &CreatorNonTEOps32);
+ }
+ }
+ }
+ return 0;
+}
+
+static void
+CreatorDestroyGC (GCPtr pGC)
+{
+ CreatorPrivGCPtr gcPriv = CreatorGetGCPrivate (pGC);
+
+ if (gcPriv->stipple)
+ xfree (gcPriv->stipple);
+ miDestroyGC (pGC);
+}
+
+static __inline__ void
+CreatorNewLine(GCPtr pGC, cfbPrivGCPtr devPriv, CreatorPrivGCPtr gcPriv, int accel)
+{
+ pGC->ops->FillPolygon = miFillPolygon;
+ pGC->ops->PolyRectangle = miPolyRectangle;
+ if (pGC->lineWidth == 0)
+ pGC->ops->PolyArc = miZeroPolyArc;
+ else
+ pGC->ops->PolyArc = miPolyArc;
+ if (accel) {
+ pGC->ops->FillPolygon = CreatorFillPolygon;
+ if (pGC->lineWidth == 0 && pGC->capStyle != CapNotLast)
+ pGC->ops->PolyArc = CreatorZeroPolyArc;
+ }
+ pGC->ops->PolySegment = miPolySegment;
+ gcPriv->linepat = 0;
+
+ /* Segment and Line ops are only accelerated if there is
+ * one clipping region.
+ */
+ if (accel && !devPriv->oneRect)
+ accel = 0;
+
+ if (pGC->lineStyle == LineSolid) {
+ if(pGC->lineWidth == 0) {
+ if (pGC->fillStyle == FillSolid) {
+ pGC->ops->Polylines = CreatorLineSSStub;
+ pGC->ops->PolySegment = CreatorSegmentSSStub;
+ } else
+ pGC->ops->Polylines = miZeroLine;
+ if (accel) {
+ gcPriv->PolySegment = pGC->ops->PolySegment;
+ gcPriv->Polylines = pGC->ops->Polylines;
+ pGC->ops->PolySegment = CreatorPolySegment;
+ pGC->ops->Polylines = CreatorPolylines;
+ }
+ } else {
+ pGC->ops->Polylines = miWideLine;
+ }
+ } else if(pGC->lineStyle == LineOnOffDash) {
+ if (pGC->lineWidth == 0 && pGC->fillStyle == FillSolid) {
+ pGC->ops->Polylines = CreatorLineSDStub;
+ pGC->ops->PolySegment = CreatorSegmentSDStub;
+ if(accel &&
+ CreatorCheckLinePattern(pGC, gcPriv)) {
+ gcPriv->PolySegment = pGC->ops->PolySegment;
+ gcPriv->Polylines = pGC->ops->Polylines;
+ pGC->ops->PolySegment = CreatorPolySegment;
+ pGC->ops->Polylines = CreatorPolylines;
+ }
+ } else {
+ pGC->ops->Polylines = miWideDash;
+ }
+ } else if(pGC->lineStyle == LineDoubleDash) {
+ if (pGC->lineWidth == 0 && pGC->fillStyle == FillSolid) {
+ pGC->ops->Polylines = CreatorLineSDStub;
+ pGC->ops->PolySegment = CreatorSegmentSDStub;
+ } else {
+ pGC->ops->Polylines = miWideDash;
+ }
+ }
+}
+
+static __inline__ void
+CreatorNewGlyph(GCPtr pGC, CreatorPrivGCPtr gcPriv)
+{
+ if (FONTWIDTH(pGC->font) > 32 ||
+ FONTHEIGHT(pGC->font) > 100 ||
+ FONTMINBOUNDS(pGC->font,characterWidth) < 0) {
+ pGC->ops->PolyGlyphBlt = miPolyGlyphBlt;
+ pGC->ops->ImageGlyphBlt = miImageGlyphBlt;
+ } else {
+ if (pGC->fillStyle == FillSolid) {
+ if (TERMINALFONT (pGC->font)) {
+ pGC->ops->PolyGlyphBlt = CreatorPolyTEGlyphBlt;
+ } else {
+ pGC->ops->PolyGlyphBlt = CreatorPolyGlyphBlt;
+ }
+ } else {
+ pGC->ops->PolyGlyphBlt = miPolyGlyphBlt;
+ }
+
+ /* special case ImageGlyphBlt for terminal emulator fonts */
+ if (TERMINALFONT(pGC->font))
+ pGC->ops->ImageGlyphBlt = CreatorTEGlyphBlt;
+ else
+ pGC->ops->ImageGlyphBlt = miImageGlyphBlt;
+ }
+}
+
+static __inline__ void
+CreatorNewFillSpans(GCPtr pGC, cfbPrivGCPtr devPriv, CreatorPrivGCPtr gcPriv, int accel)
+{
+ if (pGC->fillStyle == FillSolid) {
+ pGC->ops->FillSpans = CreatorSolidSpansGeneralStub;
+ } else if(pGC->fillStyle == FillTiled) {
+ if (pGC->pRotatedPixmap) {
+ int pmsk = (pGC->depth == 8 ? 0xff : 0xffffff);
+ if (pGC->alu == GXcopy && (pGC->planemask & pmsk) == pmsk)
+ pGC->ops->FillSpans = CreatorTile32FSCopyStub;
+ else
+ pGC->ops->FillSpans = CreatorTile32FSGeneralStub;
+ } else
+ pGC->ops->FillSpans = CreatorUnnaturalTileFSStub;
+ } else if(pGC->fillStyle == FillStippled) {
+ if (pGC->pRotatedPixmap)
+ pGC->ops->FillSpans = Creator8Stipple32FSStub;
+ else
+ pGC->ops->FillSpans = CreatorUnnaturalStippleFSStub;
+ } else if(pGC->fillStyle == FillOpaqueStippled) {
+ if (pGC->pRotatedPixmap)
+ pGC->ops->FillSpans = Creator8OpaqueStipple32FSStub;
+ else
+ pGC->ops->FillSpans = CreatorUnnaturalStippleFSStub;
+ } else
+ FatalError("CreatorValidateGC: illegal fillStyle\n");
+ if (accel)
+ pGC->ops->FillSpans = CreatorFillSpans;
+}
+
+static __inline__ void
+CreatorNewFillArea(GCPtr pGC, cfbPrivGCPtr devPriv, CreatorPrivGCPtr gcPriv, int accel)
+{
+ if (accel) {
+ pGC->ops->PolyFillRect = CreatorPolyFillRect;
+ pGC->ops->PolyFillArc = CreatorPolyFillArcSolid;
+ } else {
+ pGC->ops->PolyFillRect = miPolyFillRect;
+ if(pGC->fillStyle == FillSolid || pGC->fillStyle == FillTiled)
+ pGC->ops->PolyFillRect = CreatorPolyFillRectStub;
+ pGC->ops->PolyFillArc = miPolyFillArc;
+ }
+ pGC->ops->PushPixels = mfbPushPixels;
+}
+
+void
+CreatorValidateGC (GCPtr pGC, Mask changes, DrawablePtr pDrawable)
+{
+ int mask; /* stateChanges */
+ int new_rrop;
+ int new_line, new_text, new_fillspans, new_fillarea;
+ int new_rotate;
+ int xrot, yrot;
+ /* flags for changing the proc vector */
+ cfbPrivGCPtr devPriv;
+ CreatorPrivGCPtr gcPriv;
+ int oneRect, type;
+ int accel, drawableChanged;
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN(pDrawable->pScreen);
+
+ gcPriv = CreatorGetGCPrivate (pGC);
+ type = pFfb->vtSema ? -1 : pDrawable->type;
+ if (type != DRAWABLE_WINDOW) {
+ if (gcPriv->type == DRAWABLE_WINDOW) {
+ extern GCOps cfbNonTEOps;
+ extern GCOps cfb32NonTEOps;
+
+ miDestroyGCOps (pGC->ops);
+
+ if (pGC->depth == 8)
+ pGC->ops = &cfbNonTEOps;
+ else
+ pGC->ops = &cfb32NonTEOps;
+
+ changes = (1 << (GCLastBit+1)) - 1;
+ pGC->stateChanges = changes;
+ gcPriv->type = type;
+ }
+ if (pGC->depth == 8)
+ cfbValidateGC (pGC, changes, pDrawable);
+ else
+ cfb32ValidateGC (pGC, changes, pDrawable);
+
+ /* Our high speed VIS copyarea can
+ * be used on pixmaps too.
+ * But don't clobber someones ops prototype!!
+ */
+ if (!pGC->ops->devPrivate.val) {
+ pGC->ops = miCreateGCOps(pGC->ops);
+ pGC->ops->devPrivate.val = 1;
+ }
+ pGC->ops->CopyArea = CreatorCopyArea;
+ return;
+ }
+
+ if (gcPriv->type != DRAWABLE_WINDOW) {
+ changes = (1 << (GCLastBit+1)) - 1;
+ gcPriv->type = DRAWABLE_WINDOW;
+ }
+
+ new_rotate = pGC->lastWinOrg.x != pDrawable->x ||
+ pGC->lastWinOrg.y != pDrawable->y;
+ if(new_rotate != 0) {
+ pGC->lastWinOrg.x = pDrawable->x;
+ pGC->lastWinOrg.y = pDrawable->y;
+ }
+
+ devPriv = cfbGetGCPrivate(pGC);
+ new_rrop = FALSE;
+ new_line = FALSE;
+ new_text = FALSE;
+ new_fillspans = FALSE;
+ new_fillarea = FALSE;
+
+ drawableChanged = (pDrawable->serialNumber !=
+ (pGC->serialNumber & (DRAWABLE_SERIAL_BITS)));
+#define CLIP_BITS (GCClipXOrigin|GCClipYOrigin|GCClipMask|GCSubwindowMode)
+ /* If the client clip is different or moved OR the subwindowMode has
+ * changed OR the window's clip has changed since the last validation,
+ * we need to recompute the composite clip .
+ */
+ if ((changes & CLIP_BITS) != 0 || drawableChanged) {
+ miComputeCompositeClip(pGC, pDrawable);
+ oneRect = REGION_NUM_RECTS(cfbGetCompositeClip(pGC)) == 1;
+ if (oneRect != devPriv->oneRect) {
+ new_line = TRUE;
+ devPriv->oneRect = oneRect;
+ }
+ }
+
+ /* A while loop with a switch statement inside? No thanks. -DaveM */
+ mask = changes;
+ if((mask & (GCFunction | GCForeground | GCBackground | GCPlaneMask)) != 0)
+ new_rrop = TRUE;
+ if((mask & (GCPlaneMask | GCFillStyle | GCFont)) != 0)
+ new_text = TRUE;
+ if((mask & (GCLineStyle | GCLineWidth | GCFillStyle | GCCapStyle)) != 0)
+ new_line = TRUE;
+ if((mask & (GCFillStyle | GCTile | GCStipple)) != 0)
+ new_fillspans = new_fillarea = TRUE;
+ if(new_rotate == FALSE &&
+ (mask & (GCTileStipXOrigin | GCTileStipYOrigin)) != 0)
+ new_rotate = TRUE;
+ if((mask & GCStipple) != 0) {
+ if(pGC->stipple) {
+ int width = pGC->stipple->drawable.width;
+ PixmapPtr nstipple;
+
+ if ((width <= 32) && !(width & (width - 1))) {
+ int depth = pGC->depth;
+ nstipple = (depth == 8 ?
+ cfbCopyPixmap(pGC->stipple) :
+ cfb32CopyPixmap(pGC->stipple));
+ if (nstipple) {
+ if (depth == 8)
+ cfbPadPixmap(nstipple);
+ else
+ cfb32PadPixmap(nstipple);
+ (*pGC->pScreen->DestroyPixmap)(pGC->stipple);
+ pGC->stipple = nstipple;
+ }
+ }
+ }
+ }
+
+ /* If the drawable has changed, check its depth and ensure suitable
+ * entries are in the proc vector.
+ */
+ if (drawableChanged)
+ new_fillspans = TRUE; /* deal with FillSpans later */
+
+ if (new_rotate || new_fillspans) {
+ Bool new_pix = FALSE;
+
+ xrot = pGC->patOrg.x + pDrawable->x;
+ yrot = pGC->patOrg.y + pDrawable->y;
+ if (!CreatorCheckFill (pGC, pDrawable)) {
+ switch (pGC->fillStyle) {
+ case FillTiled:
+ if (!pGC->tileIsPixel)
+ {
+ int width = pGC->tile.pixmap->drawable.width;
+
+ if (pGC->depth == 8)
+ width *= 8;
+ else
+ width *= 32;
+
+ if ((width <= 32) && !(width & (width - 1))) {
+ if (pGC->depth == 8)
+ cfbCopyRotatePixmap(pGC->tile.pixmap,
+ &pGC->pRotatedPixmap,
+ xrot, yrot);
+ else
+ cfb32CopyRotatePixmap(pGC->tile.pixmap,
+ &pGC->pRotatedPixmap,
+ xrot, yrot);
+ new_pix = TRUE;
+ }
+ }
+ break;
+ case FillStippled:
+ case FillOpaqueStippled:
+ {
+ int width = pGC->stipple->drawable.width;
+
+ if ((width <= 32) && !(width & (width - 1)))
+ {
+ mfbCopyRotatePixmap(pGC->stipple,
+ &pGC->pRotatedPixmap, xrot, yrot);
+ new_pix = TRUE;
+ }
+ }
+ break;
+ }
+ }
+ if (!new_pix && pGC->pRotatedPixmap) {
+ (*pGC->pScreen->DestroyPixmap)(pGC->pRotatedPixmap);
+ pGC->pRotatedPixmap = (PixmapPtr) NULL;
+ }
+ }
+
+ if (new_rrop) {
+ int old_rrop;
+
+ if (gcPriv->stipple) {
+ if (pGC->fillStyle == FillStippled)
+ gcPriv->stipple->alu = pGC->alu | FFB_ROP_EDIT_BIT;
+ else
+ gcPriv->stipple->alu = pGC->alu;
+ if (pGC->fillStyle != FillTiled) {
+ gcPriv->stipple->fg = pGC->fgPixel;
+ gcPriv->stipple->bg = pGC->bgPixel;
+ }
+ }
+
+ old_rrop = devPriv->rop;
+ if (pGC->depth == 8)
+ devPriv->rop = cfbReduceRasterOp (pGC->alu, pGC->fgPixel,
+ pGC->planemask,
+ &devPriv->and, &devPriv->xor);
+ else
+ devPriv->rop = cfb32ReduceRasterOp (pGC->alu, pGC->fgPixel,
+ pGC->planemask,
+ &devPriv->and, &devPriv->xor);
+ if (old_rrop == devPriv->rop)
+ new_rrop = FALSE;
+ else {
+ new_line = TRUE;
+ new_text = TRUE;
+ new_fillspans = TRUE;
+ new_fillarea = TRUE;
+ }
+ }
+
+ if (new_rrop || new_fillspans || new_text || new_fillarea || new_line) {
+ GCOps *newops;
+ int using_creator_ops = 0;
+
+ if ((newops = CreatorMatchCommon (pGC, devPriv))) {
+ if (pGC->ops->devPrivate.val)
+ miDestroyGCOps (pGC->ops);
+ pGC->ops = newops;
+ new_rrop = new_line = new_fillspans = new_text = new_fillarea = 0;
+ using_creator_ops = 1;
+ } else {
+ if (!pGC->ops->devPrivate.val) {
+ pGC->ops = miCreateGCOps (pGC->ops);
+ pGC->ops->devPrivate.val = 1;
+ }
+
+ /* We have to make sure the copyarea op always
+ * points to our special routine as it maintains the
+ * synchronization between the raster processor and direct
+ * access to the frame buffer.
+ */
+ pGC->ops->CopyArea = CreatorCopyArea;
+ }
+ if (pGC->depth == 8)
+ newops = cfbMatchCommon(pGC, devPriv);
+ else
+ newops = cfb32MatchCommon(pGC, devPriv);
+
+ if (newops) {
+ gcPriv->PolySegment = newops->PolySegment;
+ gcPriv->Polylines = newops->Polylines;
+
+ if (using_creator_ops) {
+ /* Fixup line/segment backup ops. */
+ if (pGC->ops->PolySegment == CreatorPolySegment)
+ gcPriv->PolySegment = CreatorSegmentSSStub;
+ if (pGC->ops->Polylines == CreatorPolylines)
+ gcPriv->Polylines = CreatorLineSSStub;
+ }
+ }
+ }
+
+ accel = pGC->fillStyle == FillSolid || gcPriv->stipple;
+
+ /* deal with the changes we've collected */
+ if (new_line)
+ CreatorNewLine(pGC, devPriv, gcPriv, accel);
+
+ if (new_text && pGC->font)
+ CreatorNewGlyph(pGC, gcPriv);
+
+ if (new_fillspans)
+ CreatorNewFillSpans(pGC, devPriv, gcPriv, accel);
+
+ if (new_fillarea)
+ CreatorNewFillArea(pGC, devPriv, gcPriv, accel);
+}
+
+GCFuncs CreatorGCFuncs = {
+ CreatorValidateGC,
+ miChangeGC,
+ miCopyGC,
+ CreatorDestroyGC,
+ miChangeClip,
+ miDestroyClip,
+ miCopyClip
+};
+
+Bool
+CreatorCreateGC (GCPtr pGC)
+{
+ CreatorPrivGCPtr gcPriv;
+
+ if (pGC->depth == 1)
+ return mfbCreateGC(pGC);
+
+ if (pGC->depth == 8) {
+ if (!cfbCreateGC(pGC))
+ return FALSE;
+ } else {
+ if (!cfb32CreateGC(pGC))
+ return FALSE;
+ }
+
+ if (pGC->depth == 8)
+ pGC->ops = &CreatorNonTEOps8;
+ else
+ pGC->ops = &CreatorNonTEOps32;
+
+ pGC->funcs = &CreatorGCFuncs;
+ gcPriv = CreatorGetGCPrivate(pGC);
+ gcPriv->type = DRAWABLE_WINDOW;
+ gcPriv->linepat = 0;
+ gcPriv->stipple = 0;
+ gcPriv->PolySegment = CreatorSegmentSSStub;
+ gcPriv->Polylines = CreatorLineSSStub;
+
+ return TRUE;
+}
diff --git a/src/ffb_gc.h b/src/ffb_gc.h
new file mode 100644
index 0000000..3e62269
--- /dev/null
+++ b/src/ffb_gc.h
@@ -0,0 +1,151 @@
+/*
+ * Acceleration for the Creator and Creator3D framebuffer - Accel func declarations.
+ *
+ * Copyright (C) 1998,1999 Jakub Jelinek (jakub@redhat.com)
+ * Copyright (C) 1998 Michal Rehacek (majkl@iname.com)
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * JAKUB JELINEK, MICHAL REHACEK, OR DAVID MILLER BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_gc.h,v 1.2 2000/05/23 04:47:44 dawes Exp $ */
+
+#ifndef FFBGC_H
+#define FFBGC_H
+
+extern void CreatorDoBitblt(DrawablePtr pSrc, DrawablePtr pDst, int alu, RegionPtr prgnDst,
+ DDXPointPtr pptSrc, unsigned long planemask);
+
+extern void CreatorDoVertBitblt(DrawablePtr pSrc, DrawablePtr pDst, int alu, RegionPtr prgnDst,
+ DDXPointPtr pptSrc, unsigned long planemask);
+
+extern RegionPtr CreatorCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
+ GCPtr pGC, int srcx, int srcy, int width, int height,
+ int dstx, int dsty);
+
+extern RegionPtr CreatorCopyPlane(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
+ GCPtr pGC, int srcx, int srcy, int width, int height,
+ int dstx, int dsty, unsigned long bitPlane);
+
+extern void CreatorFillBoxSolid (DrawablePtr pDrawable, int nBox,
+ BoxPtr pBox, unsigned long pixel);
+
+extern void CreatorFillBoxStipple (DrawablePtr pDrawable,
+ int nBox, BoxPtr pBox, CreatorStipplePtr stipple);
+
+extern void CreatorPolyFillRect(DrawablePtr pDrawable, GCPtr pGC,
+ int nrectFill, xRectangle *prectInit);
+
+extern void CreatorFillSpans (DrawablePtr pDrawable, GCPtr pGC,
+ int n, DDXPointPtr ppt,
+ int *pwidth, int fSorted);
+
+extern void CreatorPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode,
+ int npt, xPoint *pptInit);
+
+extern void CreatorPolySegment (DrawablePtr pDrawable, GCPtr pGC,
+ int nseg, xSegment *pSeg);
+
+extern void CreatorFillPolygon (DrawablePtr pDrawable, GCPtr pGC,
+ int shape, int mode, int count, DDXPointPtr ppt);
+
+extern void CreatorPolylines (DrawablePtr pDrawable, GCPtr pGC,
+ int mode, int npt, DDXPointPtr ppt);
+
+extern void CreatorPolyGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, int x, int y,
+ unsigned int nglyph, CharInfoPtr *ppci, pointer pGlyphBase);
+
+extern void CreatorTEGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, int x, int y,
+ unsigned int nglyph, CharInfoPtr *ppci, pointer pGlyphBase);
+
+extern void CreatorPolyTEGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, int x, int y,
+ unsigned int nglyph, CharInfoPtr *ppci, pointer pGlyphBase);
+
+extern void CreatorPolyFillArcSolid (DrawablePtr pDrawable, GCPtr pGC,
+ int narcs, xArc *parcs);
+
+extern void CreatorZeroPolyArc(DrawablePtr pDrawable, GCPtr pGC,
+ int narcs, xArc *parcs);
+
+extern int CreatorCheckTile (PixmapPtr pPixmap, CreatorStipplePtr stipple,
+ int ox, int oy, int ph);
+
+extern int CreatorCheckStipple (PixmapPtr pPixmap, CreatorStipplePtr stipple,
+ int ox, int oy, int ph);
+
+extern int CreatorCheckLinePattern(GCPtr pGC, CreatorPrivGCPtr gcPriv);
+
+extern int CreatorCheckFill (GCPtr pGC, DrawablePtr pDrawable);
+
+extern void CreatorSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *pcharsrc,
+ DDXPointPtr ppt, int *pwidth, int nspans, int fSorted);
+
+/* Stuff still not accelerated fully. */
+extern void CreatorSegmentSSStub (DrawablePtr pDrawable, GCPtr pGC,
+ int nseg, xSegment *pSeg);
+
+extern void CreatorLineSSStub (DrawablePtr pDrawable, GCPtr pGC,
+ int mode, int npt, DDXPointPtr ppt);
+
+extern void CreatorSegmentSDStub (DrawablePtr pDrawable, GCPtr pGC,
+ int nseg, xSegment *pSeg);
+
+extern void CreatorLineSDStub (DrawablePtr pDrawable, GCPtr pGC,
+ int mode, int npt, DDXPointPtr ppt);
+
+extern void CreatorSolidSpansGeneralStub (DrawablePtr pDrawable, GCPtr pGC,
+ int nInit, DDXPointPtr pptInit,
+ int *pwidthInit, int fSorted);
+
+extern void CreatorPolyGlyphBlt8Stub (DrawablePtr pDrawable, GCPtr pGC,
+ int x, int y, unsigned int nglyph, CharInfoPtr *ppci,
+ pointer pglyphBase);
+
+extern void CreatorImageGlyphBlt8Stub (DrawablePtr pDrawable, GCPtr pGC,
+ int x, int y, unsigned int nglyph,
+ CharInfoPtr *ppci, pointer pglyphBase);
+
+extern void CreatorTile32FSCopyStub(DrawablePtr pDrawable, GCPtr pGC,
+ int nInit, DDXPointPtr pptInit,
+ int *pwidthInit, int fSorted);
+
+extern void CreatorTile32FSGeneralStub(DrawablePtr pDrawable, GCPtr pGC,
+ int nInit, DDXPointPtr pptInit,
+ int *pwidthInit, int fSorted);
+
+extern void CreatorUnnaturalTileFSStub(DrawablePtr pDrawable, GCPtr pGC,
+ int nInit, DDXPointPtr pptInit,
+ int *pwidthInit, int fSorted);
+
+extern void Creator8Stipple32FSStub(DrawablePtr pDrawable, GCPtr pGC,
+ int nInit, DDXPointPtr pptInit,
+ int *pwidthInit, int fSorted);
+
+extern void CreatorUnnaturalStippleFSStub(DrawablePtr pDrawable, GCPtr pGC,
+ int nInit, DDXPointPtr pptInit,
+ int *pwidthInit, int fSorted);
+
+extern void Creator8OpaqueStipple32FSStub(DrawablePtr pDrawable, GCPtr pGC,
+ int nInit, DDXPointPtr pptInit,
+ int *pwidthInit, int fSorted);
+
+extern void CreatorPolyFillRectStub(DrawablePtr pDrawable, GCPtr pGC,
+ int nrectFill, xRectangle *prectInit);
+
+#endif /* FFBGC_H */
diff --git a/src/ffb_glyph.c b/src/ffb_glyph.c
new file mode 100644
index 0000000..76668e3
--- /dev/null
+++ b/src/ffb_glyph.c
@@ -0,0 +1,380 @@
+/*
+ * Acceleration for the Creator and Creator3D framebuffer - Glyph rops.
+ *
+ * Copyright (C) 1998,1999 Jakub Jelinek (jakub@redhat.com)
+ * Copyright (C) 1998 Michal Rehacek (majkl@iname.com)
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * JAKUB JELINEK, MICHAL REHACEK, OR DAVID MILLER BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_glyph.c,v 1.2 2000/05/23 04:47:45 dawes Exp $ */
+
+#include "ffb.h"
+#include "ffb_regs.h"
+#include "ffb_rcache.h"
+#include "ffb_fifo.h"
+#include "ffb_loops.h"
+
+#include "pixmapstr.h"
+#include "scrnintstr.h"
+#include "fontstruct.h"
+#include "dixfontstr.h"
+
+#define PSZ 8
+#include "cfb.h"
+#undef PSZ
+#include "cfb32.h"
+
+void
+CreatorPolyGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, int x, int y,
+ unsigned int nglyph, CharInfoPtr *ppci, pointer pGlyphBase)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pGC->pScreen);
+ ffb_fbcPtr ffb = pFfb->regs;
+ FontPtr pfont = pGC->font;
+ RegionPtr clip = cfbGetCompositeClip(pGC);
+ BoxPtr pbox = REGION_RECTS(clip);
+ int nbox = REGION_NUM_RECTS(clip);
+ int skippix, skipglyph, width, n, i;
+ int Left, Right, Top, Bottom, LeftEdge, RightEdge;
+
+ FFBLOG(("CreatorPolyGlyphBlt: xy[%08x:%08x] nglyph(%d)\n", x, y, nglyph));
+ x += pDrawable->x;
+ y += pDrawable->y;
+
+ width = 0;
+ for(i = 0; i < (nglyph - 1); i++)
+ width += (ppci[i])->metrics.characterWidth;
+
+ Left = x + (ppci[0])->metrics.leftSideBearing;
+ Right = x + (width + (ppci[nglyph - 1])->metrics.rightSideBearing);
+ Top = y - FONTMAXBOUNDS(pfont, ascent);
+ Bottom = y + FONTMAXBOUNDS(pfont, descent);
+
+ while(nbox && (Top >= pbox->y2)) {
+ pbox++;
+ nbox--;
+ }
+
+ if(!nbox || Bottom < pbox->y1)
+ return;
+
+ /* Ok, setup the chip. */
+ {
+ unsigned int ppc = (FFB_PPC_APE_DISABLE | FFB_PPC_TBE_TRANSPARENT |
+ FFB_PPC_CS_CONST);
+ unsigned int ppc_mask = (FFB_PPC_APE_MASK | FFB_PPC_TBE_MASK |
+ FFB_PPC_CS_MASK);
+ unsigned int pmask = pGC->planemask;
+ unsigned int rop = (FFB_ROP_EDIT_BIT | pGC->alu) | (FFB_ROP_NEW << 8);
+ unsigned int fg = pGC->fgPixel;
+ WindowPtr pWin = (WindowPtr) pDrawable;
+ unsigned int fbc = FFB_FBC_WIN(pWin);
+
+ fbc = (fbc & ~FFB_FBC_XE_MASK) | FFB_FBC_XE_OFF;
+
+ if((pFfb->ppc_cache & ppc_mask) != ppc ||
+ pFfb->fg_cache != fg ||
+ pFfb->fbc_cache != fbc ||
+ pFfb->rop_cache != rop ||
+ pFfb->pmask_cache != pmask ||
+ pFfb->fontinc_cache != ((1<<16) | 0)) {
+ pFfb->ppc_cache &= ~ppc_mask;
+ pFfb->ppc_cache |= ppc;
+ pFfb->fg_cache = fg;
+ pFfb->fbc_cache = fbc;
+ pFfb->rop_cache = rop;
+ pFfb->pmask_cache = pmask;
+ pFfb->fontinc_cache = ((1<<16) | 0);
+ pFfb->rp_active = 1;
+ FFBFifo(pFfb, 6);
+ ffb->ppc = ppc;
+ ffb->fg = fg;
+ ffb->fbc = fbc;
+ ffb->rop = rop;
+ ffb->pmask = pmask;
+ ffb->fontinc = ((1 << 16) | 0);
+ }
+ }
+
+ while(nbox && (Bottom >= pbox->y1)) {
+ LeftEdge = max(Left, pbox->x1);
+ RightEdge = min(Right, pbox->x2);
+ if(RightEdge > LeftEdge) {
+ int walk, x_start;
+
+ skippix = LeftEdge - x;
+ skipglyph = walk = 0;
+ while(skippix >= (walk + (ppci[skipglyph])->metrics.rightSideBearing)) {
+ walk += (ppci[skipglyph])->metrics.characterWidth;
+ skipglyph++;
+ }
+ x_start = x + walk;
+ skippix = RightEdge - x;
+ n = 0;
+ i = skipglyph;
+ while((i < nglyph) &&
+ (skippix > (walk + (ppci[i])->metrics.leftSideBearing))) {
+ walk += (ppci[i])->metrics.characterWidth;
+ i++;
+ n++;
+ }
+ if(n) {
+ CharInfoPtr *ppci_iter = ppci + skipglyph;
+ CharInfoPtr pci;
+ unsigned int *bits;
+ int w, h, x0, y0, xskip, yskip;
+
+ while(n--) {
+ pci = *ppci_iter++;
+ w = GLYPHWIDTHPIXELS(pci);
+ h = GLYPHHEIGHTPIXELS(pci);
+ if(!w || !h)
+ goto next_glyph;
+
+ x0 = x_start + pci->metrics.leftSideBearing;
+ y0 = y - pci->metrics.ascent;
+ bits = (unsigned int *) pci->bits;
+
+ /* Now clip it to the bits we should actually
+ * render.
+ */
+ xskip = yskip = 0;
+ if(pbox->x1 > x0) {
+ xskip = pbox->x1 - x0;
+ w -= xskip;
+ x0 = pbox->x1;
+ if(w <= 0)
+ goto next_glyph;
+ }
+ if(pbox->y1 > y0) {
+ yskip = pbox->y1 - y0;
+ h -= yskip;
+ y0 = pbox->y1;
+ if(h <= 0)
+ goto next_glyph;
+ }
+ if(pbox->x2 < (x0 + w)) {
+ w = pbox->x2 - x0;
+ if(w <= 0)
+ goto next_glyph;
+ }
+ if(pbox->y2 < (y0 + h)) {
+ h = pbox->y2 - y0;
+ if(h <= 0)
+ goto next_glyph;
+ }
+
+ FFB_WRITE_FONTW(pFfb, ffb, w);
+ FFBFifo(pFfb, 1 + h);
+ ffb->fontxy = ((y0 << 16) | x0);
+ for(i = 0; i < h; i++)
+ ffb->font = bits[yskip + i] << xskip;
+
+ next_glyph:
+ x_start += pci->metrics.characterWidth;
+ }
+ }
+ }
+ nbox--;
+ pbox++;
+ }
+ pFfb->rp_active = 1;
+ FFBSync(pFfb, ffb);
+}
+
+void
+CreatorTEGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, int x, int y,
+ unsigned int nglyph, CharInfoPtr *ppci, pointer pGlyphBase)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pGC->pScreen);
+ ffb_fbcPtr ffb = pFfb->regs;
+ RegionPtr clip = cfbGetCompositeClip(pGC);
+ int nbox = REGION_NUM_RECTS(clip);
+ BoxPtr pbox = REGION_RECTS(clip);
+ FontPtr pfont = pGC->font;
+ int glyphWidth = FONTMAXBOUNDS(pfont, characterWidth);
+ int skippix, skipglyphs, Left, Right, Top, Bottom;
+ int LeftEdge, RightEdge, ytop, ybot, h, w;
+
+ FFBLOG(("CreatorTEGlyphBlt: xy[%08x:%08x] nglyph(%d) pgbase(%p)\n",
+ x, y, nglyph, pGlyphBase));
+
+ Left = x + pDrawable->x;
+ Right = Left + (glyphWidth * nglyph);
+ y += pDrawable->y;
+ Top = y - FONTASCENT(pfont);
+ Bottom = y + FONTDESCENT(pfont);
+
+ while(nbox && (Top >= pbox->y2)) {
+ pbox++;
+ nbox--;
+ }
+
+ if(!nbox || Bottom <= pbox->y1)
+ return;
+
+ /* Ok, setup the chip. */
+ {
+ unsigned int ppc = FFB_PPC_APE_DISABLE|FFB_PPC_CS_CONST;
+ unsigned int ppc_mask = FFB_PPC_APE_MASK|FFB_PPC_TBE_MASK|FFB_PPC_CS_MASK;
+ unsigned int pmask = pGC->planemask;
+ unsigned int rop;
+ unsigned int fg = pGC->fgPixel;
+ unsigned int bg = pGC->bgPixel;
+ WindowPtr pWin = (WindowPtr) pDrawable;
+ unsigned int fbc = FFB_FBC_WIN(pWin);
+
+ fbc = (fbc & ~FFB_FBC_XE_MASK) | FFB_FBC_XE_OFF;
+
+ if(pGlyphBase) {
+ ppc |= FFB_PPC_TBE_TRANSPARENT;
+ rop = FFB_ROP_EDIT_BIT | pGC->alu;
+ } else {
+ ppc |= FFB_PPC_TBE_OPAQUE;
+ rop = FFB_ROP_EDIT_BIT | GXcopy;
+ }
+ rop |= (FFB_ROP_NEW << 8);
+ if((pFfb->ppc_cache & ppc_mask) != ppc ||
+ pFfb->fg_cache != fg ||
+ pFfb->fbc_cache != fbc ||
+ pFfb->rop_cache != rop ||
+ pFfb->pmask_cache != pmask ||
+ pFfb->fontinc_cache != ((1<<16) | 0) ||
+ (!pGlyphBase && pFfb->bg_cache != bg)) {
+ pFfb->ppc_cache &= ~ppc_mask;
+ pFfb->ppc_cache |= ppc;
+ pFfb->fg_cache = fg;
+ pFfb->fbc_cache = fbc;
+ pFfb->rop_cache = rop;
+ pFfb->pmask_cache = pmask;
+ pFfb->fontinc_cache = ((1<<16) | 0);
+ if(!pGlyphBase)
+ pFfb->bg_cache = bg;
+ FFBFifo(pFfb, (!pGlyphBase ? 7 : 6));
+ ffb->ppc = ppc;
+ ffb->fg = fg;
+ ffb->fbc = fbc;
+ ffb->rop = rop;
+ ffb->pmask = pmask;
+ ffb->fontinc = ((1 << 16) | 0);
+ if(!pGlyphBase)
+ ffb->bg = bg;
+ }
+ }
+
+ while(nbox && (Bottom > pbox->y1)) {
+ LeftEdge = max(Left, pbox->x1);
+ RightEdge = min(Right, pbox->x2);
+
+ if(RightEdge > LeftEdge) {
+ ytop = max(Top, pbox->y1);
+ ybot = min(Bottom, pbox->y2);
+
+ if((skippix = LeftEdge - Left)) {
+ skipglyphs = skippix / glyphWidth;
+ skippix %= glyphWidth;
+ } else
+ skipglyphs = 0;
+ w = RightEdge - LeftEdge;
+
+ /* Get aligned onto a character. */
+ if(skippix) {
+ unsigned int *gbits = (unsigned int *) ppci[skipglyphs++]->bits;
+ int chunk_size = (glyphWidth - skippix);
+
+ if (chunk_size > w)
+ chunk_size = w;
+
+ FFB_WRITE_FONTW(pFfb, ffb, chunk_size);
+ FFBFifo(pFfb, 1 + (ybot - ytop));
+ ffb->fontxy = ((ytop << 16) | LeftEdge);
+ for(h = (ytop - Top); h < (ybot - Top); h++)
+ ffb->font = gbits[h] << skippix;
+ LeftEdge += chunk_size;
+ w -= chunk_size;
+ }
+ /* And now blit the rest with unrolled loops. */
+#define LoopIt(chunkW, loadup, fetch) \
+ FFB_WRITE_FONTW(pFfb, ffb, chunkW); \
+ while (w >= chunkW) { \
+ loadup \
+ FFBFifo(pFfb, 1 + (ybot - ytop)); \
+ ffb->fontxy = ((ytop << 16) | LeftEdge); \
+ for(h = (ytop - Top); h < (ybot - Top); h++) \
+ ffb->font = fetch; \
+ LeftEdge += chunkW; \
+ w -= chunkW; \
+ }
+ if(glyphWidth <= 8) {
+ int chunk_size = glyphWidth << 2;
+ LoopIt(chunk_size,
+ unsigned int *char1 = ((unsigned int *)ppci[skipglyphs++]->bits)+(ytop-Top);
+ unsigned int *char2 = ((unsigned int *)ppci[skipglyphs++]->bits)+(ytop-Top);
+ unsigned int *char3 = ((unsigned int *)ppci[skipglyphs++]->bits)+(ytop-Top);
+ unsigned int *char4 = ((unsigned int *)ppci[skipglyphs++]->bits)+(ytop-Top);,
+ (*char1++ | ((*char2++ | ((*char3++ | (*char4++ >> glyphWidth))
+ >> glyphWidth))
+ >> glyphWidth)))
+ } else if(glyphWidth <= 10) {
+ int chunk_size = (glyphWidth << 1) + glyphWidth;
+ LoopIt(chunk_size,
+ unsigned int *char1 = ((unsigned int *)ppci[skipglyphs++]->bits)+(ytop-Top);
+ unsigned int *char2 = ((unsigned int *)ppci[skipglyphs++]->bits)+(ytop-Top);
+ unsigned int *char3 = ((unsigned int *)ppci[skipglyphs++]->bits)+(ytop-Top);,
+ (*char1++ | ((*char2++ | (*char3++ >> glyphWidth)) >> glyphWidth)));
+ } else if(glyphWidth <= 16) {
+ int chunk_size = glyphWidth << 1;
+ LoopIt(chunk_size,
+ unsigned int *char1 = ((unsigned int *)ppci[skipglyphs++]->bits)+(ytop-Top);
+ unsigned int *char2 = ((unsigned int *)ppci[skipglyphs++]->bits)+(ytop-Top);,
+ (*char1++ | (*char2++ >> glyphWidth)));
+ }
+#undef LoopIt
+ /* Take care of any final glyphs. */
+ while(w > 0) {
+ unsigned int *gbits = (unsigned int *) ppci[skipglyphs++]->bits;
+ int pix = glyphWidth;
+
+ if(w < pix)
+ pix = w;
+ FFB_WRITE_FONTW(pFfb, ffb, pix);
+ FFBFifo(pFfb, 1 + (ybot - ytop));
+ ffb->fontxy = ((ytop << 16) | LeftEdge);
+ for(h = (ytop - Top); h < (ybot - Top); h++)
+ ffb->font = gbits[h];
+ LeftEdge += pix;
+ w -= pix;
+ }
+ }
+ nbox--;
+ pbox++;
+ }
+
+ pFfb->rp_active = 1;
+ FFBSync(pFfb, ffb);
+}
+
+void
+CreatorPolyTEGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, int x, int y,
+ unsigned int nglyph, CharInfoPtr *ppci, pointer pGlyphBase)
+{
+ CreatorTEGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, (char *) 1);
+}
diff --git a/src/ffb_gspans.c b/src/ffb_gspans.c
new file mode 100644
index 0000000..5c00cb7
--- /dev/null
+++ b/src/ffb_gspans.c
@@ -0,0 +1,130 @@
+/*
+ * Acceleration for the Creator and Creator3D framebuffer - Get spans.
+ *
+ * Copyright (C) 1998,1999 Jakub Jelinek (jakub@redhat.com)
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * JAKUB JELINEK OR DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_gspans.c,v 1.2 2000/05/23 04:47:45 dawes Exp $ */
+
+#include "ffb.h"
+#include "ffb_regs.h"
+#include "ffb_rcache.h"
+#include "ffb_fifo.h"
+
+#include "pixmapstr.h"
+#include "scrnintstr.h"
+
+#define PSZ 8
+#include "cfb.h"
+#undef PSZ
+#include "cfb32.h"
+
+void
+CreatorGetSpans(DrawablePtr pDrawable, int wMax, DDXPointPtr ppt,
+ int *pwidth, int nspans, char *pchardstStart)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pDrawable->pScreen);
+ ffb_fbcPtr ffb = pFfb->regs;
+ char *addrp;
+
+ FFBLOG(("CreatorGetSpans: wmax(%d) nspans(%d)\n", wMax, nspans));
+
+ /* Punt early for this case. */
+ if(pDrawable->bitsPerPixel == 1) {
+ mfbGetSpans(pDrawable, wMax, ppt, pwidth,
+ nspans, pchardstStart);
+ return;
+ }
+
+ /* This code only works when sucking bits directly from
+ * the framebuffer.
+ */
+ if(pDrawable->type != DRAWABLE_WINDOW) {
+ if (pDrawable->bitsPerPixel == 8)
+ cfbGetSpans(pDrawable, wMax, ppt, pwidth,
+ nspans, pchardstStart);
+ else
+ cfb32GetSpans(pDrawable, wMax, ppt, pwidth,
+ nspans, pchardstStart);
+ return;
+ }
+
+ /*
+ * XFree86 DDX empties the root borderClip when the VT is
+ * switched away; this checks for that case
+ */
+ if (!cfbDrawableEnabled(pDrawable))
+ return;
+
+ /* We're just reading pixels from SFB, but we could be using
+ * a different read buffer when double-buffering.
+ */
+ FFB_ATTR_SFB_VAR_WIN(pFfb, 0x00ffffff, GXcopy, (WindowPtr)pDrawable);
+ FFBWait(pFfb, ffb);
+
+ if (pDrawable->bitsPerPixel == 32) {
+ unsigned int *pdst = (unsigned int *)pchardstStart;
+
+ addrp = (char *) pFfb->sfb32;
+
+ if ((nspans == 1) && (*pwidth == 1)) {
+ *pdst = *(unsigned int *)(addrp + (ppt->y << 13) + (ppt->x << 2));
+ return;
+ }
+
+ while(nspans--) {
+ int w = min(ppt->x + *pwidth, 2048) - ppt->x;
+ unsigned int *psrc = (unsigned int *) (addrp +
+ (ppt->y << 13) +
+ (ppt->x << 2));
+ unsigned int *pdstNext = pdst + w;
+
+ while (w--)
+ *psrc++ = *pdst++;
+ pdst = pdstNext;
+ ppt++;
+ pwidth++;
+ }
+ } else {
+ unsigned char *pdst = (unsigned char *)pchardstStart;
+
+ addrp = (char *) pFfb->sfb8r;
+
+ if ((nspans == 1) && (*pwidth == 1)) {
+ *pdst = *(unsigned char *)(addrp + (ppt->y << 11) + (ppt->x << 0));
+ return;
+ }
+
+ while(nspans--) {
+ int w = min(ppt->x + *pwidth, 2048) - ppt->x;
+ unsigned char *psrc = (unsigned char *) (addrp +
+ (ppt->y << 11) +
+ (ppt->x << 0));
+ unsigned char *pdstNext = pdst + w;
+
+ while (w--)
+ *psrc++ = *pdst++;
+ pdst = pdstNext;
+ ppt++;
+ pwidth++;
+ }
+ }
+}
diff --git a/src/ffb_line.c b/src/ffb_line.c
new file mode 100644
index 0000000..e94fd03
--- /dev/null
+++ b/src/ffb_line.c
@@ -0,0 +1,195 @@
+/*
+ * Acceleration for the Creator and Creator3D framebuffer - Line rops.
+ *
+ * Copyright (C) 1998,1999 Jakub Jelinek (jakub@redhat.com)
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * JAKUB JELINEK OR DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_line.c,v 1.2 2000/05/23 04:47:45 dawes Exp $ */
+
+#include "ffb.h"
+#include "ffb_regs.h"
+#include "ffb_rcache.h"
+#include "ffb_fifo.h"
+#include "ffb_stip.h"
+
+#include "pixmapstr.h"
+#include "scrnintstr.h"
+
+#define PSZ 8
+#include "cfb.h"
+#undef PSZ
+#include "cfb32.h"
+
+#include "miline.h"
+
+/* The scheme here is similar as for segments, except that
+ * if there are any out of range coordinate, we fully punt
+ * and do all of the pieces in software. This is as to
+ * avoid complexity in final line capping, sloped lines, line
+ * patterns etc.
+ */
+#define IN_RANGE(_extent, _x, _y) \
+ ((_x) >= (_extent)->x1 && (_x) < (_extent)->x2 && \
+ (_y) >= (_extent)->y1 && (_y) < (_extent)->y2)
+
+
+void
+CreatorPolylines (DrawablePtr pDrawable, GCPtr pGC, int mode, int nptInit, DDXPointPtr pptInit)
+{
+ WindowPtr pWin = (WindowPtr) pDrawable;
+ CreatorPrivGCPtr gcPriv = CreatorGetGCPrivate (pGC);
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pGC->pScreen);
+ ffb_fbcPtr ffb = pFfb->regs;
+ DDXPointPtr ppt;
+ BoxPtr extent;
+ int x, y, xorg, yorg, npt, capLast;
+
+ npt = nptInit;
+ if (npt <= 1)
+ return;
+ ppt = pptInit;
+ xorg = pDrawable->x;
+ yorg = pDrawable->y;
+ x = ppt->x + xorg;
+ y = ppt->y + yorg;
+ extent = REGION_RECTS(cfbGetCompositeClip(pGC));
+ if (!IN_RANGE(extent, x, y))
+ goto punt_rest;
+ ppt++;
+ while(npt--) {
+ if (mode == CoordModeOrigin) {
+ x = ppt->x + xorg;
+ y = ppt->y + yorg;
+ } else {
+ x += ppt->x;
+ y += ppt->y;
+ }
+ if (!IN_RANGE(extent, x, y))
+ goto punt_rest;
+ ppt++;
+ }
+ FFBLOG(("CreatorPolylines: npt(%d) lpat(%08x) alu(%x) pmsk(%08x)\n",
+ npt, gcPriv->linepat, pGC->alu, pGC->planemask));
+ if(gcPriv->stipple == NULL) {
+ FFB_ATTR_GC(pFfb, pGC, pWin,
+ FFB_PPC_APE_DISABLE | FFB_PPC_CS_CONST,
+ FFB_DRAWOP_BRLINEOPEN);
+ } else {
+ unsigned int fbc;
+
+ FFBSetStipple(pFfb, ffb, gcPriv->stipple,
+ FFB_PPC_CS_CONST, FFB_PPC_CS_MASK);
+ FFB_WRITE_PMASK(pFfb, ffb, pGC->planemask);
+ FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_BRLINEOPEN);
+ fbc = FFB_FBC_WIN(pWin);
+ fbc = (fbc & ~FFB_FBC_XE_MASK) | FFB_FBC_XE_OFF;
+ FFB_WRITE_FBC(pFfb, ffb, fbc);
+ }
+ pFfb->rp_active = 1;
+
+ ppt = pptInit;
+ npt = nptInit;
+ x = ppt->x + xorg;
+ y = ppt->y + yorg;
+
+ FFBFifo(pFfb, 3);
+ ffb->lpat = gcPriv->linepat;
+ ffb->by = y;
+ ffb->bx = x;
+ ppt++;
+ npt--;
+ capLast = pGC->capStyle != CapNotLast;
+ if (mode == CoordModeOrigin) {
+ if (capLast)
+ npt--;
+ if (pFfb->has_brline_bug) {
+ while (npt--) {
+ x = ppt->x + xorg;
+ y = ppt->y + yorg;
+ ppt++;
+ FFBFifo(pFfb, 3);
+ ffb->ppc = 0;
+ FFB_WRITE64(&ffb->bh, y, x);
+ }
+ } else {
+ while (npt--) {
+ x = ppt->x + xorg;
+ y = ppt->y + yorg;
+ ppt++;
+ FFBFifo(pFfb, 2);
+ FFB_WRITE64(&ffb->bh, y, x);
+ }
+ }
+ if (capLast) {
+ register int x2, y2;
+
+ x2 = ppt->x + xorg;
+ y2 = ppt->y + yorg;
+
+ FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_BRLINECAP);
+ FFBFifo(pFfb, 5);
+ ffb->ppc = 0;
+ FFB_WRITE64(&ffb->by, y, x);
+ FFB_WRITE64_2(&ffb->bh, y2, x2);
+ }
+ } else {
+ if (capLast)
+ npt--;
+ if (pFfb->has_brline_bug) {
+ while (npt--) {
+ x += ppt->x;
+ y += ppt->y;
+ ppt++;
+
+ FFBFifo(pFfb, 3);
+ ffb->ppc = 0;
+ FFB_WRITE64(&ffb->bh, y, x);
+ }
+ } else {
+ while (npt--) {
+ x += ppt->x;
+ y += ppt->y;
+ ppt++;
+
+ FFBFifo(pFfb, 2);
+ FFB_WRITE64(&ffb->bh, y, x);
+ }
+ }
+ if (capLast) {
+ register int x2, y2;
+
+ x2 = x + ppt->x;
+ y2 = y + ppt->y;
+
+ FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_BRLINECAP);
+ FFBFifo(pFfb, 5);
+ ffb->ppc = 0;
+ FFB_WRITE64(&ffb->by, y, x);
+ FFB_WRITE64_2(&ffb->bh, y2, x2);
+ }
+ }
+ FFBSync(pFfb, ffb);
+ return;
+
+punt_rest:
+ gcPriv->Polylines(pDrawable, pGC, mode, nptInit, pptInit);
+ return;
+}
diff --git a/src/ffb_loops.h b/src/ffb_loops.h
new file mode 100644
index 0000000..efb14c3
--- /dev/null
+++ b/src/ffb_loops.h
@@ -0,0 +1,212 @@
+/*
+ * Acceleration for the Creator and Creator3D framebuffer - fast inner loops.
+ *
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * JAKUB JELINEK OR DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_loops.h,v 1.1 2000/05/18 23:21:37 dawes Exp $ */
+
+#ifndef FFBLOOPS_H
+#define FFBLOOPS_H
+
+#ifdef USE_VIS
+extern void FFB_STIPPLE_LOAD(volatile unsigned int *d,
+ unsigned int *s);
+
+extern void FFB_PPT_BOX_LOOP(FFBPtr ffbpriv,
+ ffb_fbcPtr ffb,
+ BoxPtr pbox, BoxPtr pbox_last,
+ DDXPointPtr ppt);
+
+extern void FFB_BOX_LOOP(FFBPtr ffbpriv,
+ ffb_fbcPtr ffb,
+ BoxPtr pbox,
+ BoxPtr pbox_last);
+
+extern void FFB_RECT_LOOP(FFBPtr ffbpriv,
+ ffb_fbcPtr ffb,
+ xRectangle *prect,
+ xRectangle *prect_last,
+ int xOrg, int yOrg);
+
+extern void FFB_PPT_WIDTH_LOOP(FFBPtr ffbpriv,
+ ffb_fbcPtr ffb,
+ DDXPointPtr ppt, DDXPointPtr ppt_last,
+ int *pwidth);
+
+extern DDXPointPtr FFB_PPT_LOOP1(FFBPtr ffbpriv,
+ ffb_fbcPtr ffb,
+ DDXPointPtr ppt, DDXPointPtr ppt_last,
+ int xOrg, int yOrg);
+
+extern DDXPointPtr FFB_PPT_LOOP2(FFBPtr ffbpriv,
+ ffb_fbcPtr ffb,
+ DDXPointPtr ppt, DDXPointPtr ppt_last,
+ int x, int y);
+
+extern DDXPointPtr FFB_LINE_LOOP1(FFBPtr ffbpriv,
+ ffb_fbcPtr ffb,
+ DDXPointPtr ppt, DDXPointPtr ppt_last,
+ int xOrg, int yOrg);
+
+extern DDXPointPtr FFB_LINE_LOOP2(FFBPtr ffbpriv,
+ ffb_fbcPtr ffb,
+ DDXPointPtr ppt, DDXPointPtr ppt_last,
+ int *x, int *y);
+
+#else /* !USE_VIS */
+
+#define FFB_STIPPLE_LOAD(_d,_s) \
+do { \
+ volatile unsigned int *d = (_d); \
+ unsigned int *s = (_s); \
+ int i; \
+ \
+ for (i = 0; i < (32 / 2); i++, d+=2, s+=2) \
+ FFB_WRITE64(d, s[0], s[1]); \
+} while (0)
+
+#define FFB_PPT_BOX_LOOP(pFfb, ffb, pbox, _pbox_last, ppt) \
+do { \
+ BoxPtr pbox_last = (BoxPtr)(_pbox_last); \
+ while (pbox <= pbox_last) { \
+ FFBFifo(pFfb, 7); \
+ ffb->drawop = FFB_DRAWOP_VSCROLL; \
+ FFB_WRITE64(&ffb->by, ppt->y, ppt->x); \
+ FFB_WRITE64_2(&ffb->dy, pbox->y1, pbox->x1); \
+ FFB_WRITE64_3(&ffb->bh, (pbox->y2 - pbox->y1), (pbox->x2 - pbox->x1)); \
+ pbox++; ppt++; \
+ } \
+} while (0)
+
+#define FFB_BOX_LOOP(pFfb, ffb, pbox, _pbox_last) \
+do { \
+ BoxPtr pbox_last = (BoxPtr)(_pbox_last); \
+ while (pbox <= pbox_last) { \
+ FFBFifo(pFfb, 4); \
+ FFB_WRITE64(&ffb->by, pbox->y1, pbox->x1); \
+ FFB_WRITE64_2(&ffb->bh, (pbox->y2 - pbox->y1), (pbox->x2 - pbox->x1)); \
+ pbox++; \
+ } \
+} while (0)
+
+#define FFB_RECT_LOOP(pFfb, ffb, prect, _prect_last, xOrg, yOrg) \
+do { \
+ xRectangle *prect_last = (xRectangle *)(_prect_last); \
+ for (; prect <= prect_last; prect++) { \
+ register int x, y, w, h; \
+ x = prect->x + xOrg; \
+ y = prect->y + yOrg; \
+ w = prect->width; \
+ h = prect->height; \
+ if (extents->x2 <= x || \
+ extents->x1 >= x + w || \
+ extents->y2 <= y || \
+ extents->y1 >= y + h) \
+ continue; \
+ FFBFifo(pFfb, 4); \
+ FFB_WRITE64(&ffb->by, y, x); \
+ FFB_WRITE64_2(&ffb->bh, h, w); \
+ } \
+} while (0)
+
+#define FFB_PPT_WIDTH_LOOP(pFfb, ffb, ppt, _ppt_last, pwidth) \
+do { \
+ DDXPointPtr ppt_last = (DDXPointPtr)(_ppt_last); \
+ while (ppt <= ppt_last) { \
+ register int x, y, w; \
+ x = ppt->x; \
+ y = ppt->y; \
+ w = *pwidth++; \
+ FFBFifo(pFfb, 5); \
+ ffb->ppc = 0; \
+ FFB_WRITE64(&ffb->by, y, x); \
+ FFB_WRITE64_2(&ffb->bh, y, (x + w)); \
+ ppt++; \
+ } \
+} while (0)
+
+static __inline__ DDXPointPtr FFB_PPT_LOOP1(FFBPtr pFfb,
+ ffb_fbcPtr ffb,
+ DDXPointPtr ppt, DDXPointPtr ppt_last,
+ int xOrg, int yOrg)
+{
+ while (ppt <= ppt_last) {
+ FFBFifo(pFfb, 2);
+ FFB_WRITE64_2(&ffb->bh, (ppt->y + yOrg), (ppt->x + xOrg));
+ ppt++;
+ }
+ return ppt;
+}
+
+static __inline__ DDXPointPtr FFB_PPT_LOOP2(FFBPtr pFfb,
+ ffb_fbcPtr ffb,
+ DDXPointPtr ppt, DDXPointPtr ppt_last,
+ int x, int y)
+{
+ register int __x = x, __y = y;
+ while (ppt <= ppt_last) {
+ FFBFifo(pFfb, 2);
+ __x += ppt->x;
+ __y += ppt->y;
+ FFB_WRITE64_2(&ffb->bh, __y, __x);
+ ppt++;
+ }
+ return ppt;
+}
+
+static __inline__ DDXPointPtr FFB_LINE_LOOP1(FFBPtr pFfb,
+ ffb_fbcPtr ffb,
+ DDXPointPtr ppt, DDXPointPtr ppt_last,
+ int xOrg, int yOrg)
+{
+ while (ppt <= ppt_last) {
+ FFBFifo(pFfb, 3);
+ ffb->ppc = 0;
+ FFB_WRITE64_2(&ffb->bh, (ppt->y + yOrg), (ppt->x + xOrg));
+ ppt++;
+ }
+ return ppt;
+}
+
+static __inline__ DDXPointPtr FFB_LINE_LOOP2(FFBPtr pFfb,
+ ffb_fbcPtr ffb,
+ DDXPointPtr ppt, DDXPointPtr ppt_last,
+ int *x, int *y)
+{
+ register int __x = *x, __y = *y;
+ while (ppt <= ppt_last) {
+ FFBFifo(pFfb, 3);
+ ffb->ppc = 0;
+ __x += ppt->x;
+ __y += ppt->y;
+ FFB_WRITE64_2(&ffb->bh, __y, __x);
+ ppt++;
+ }
+ *x = __x;
+ *y = __y;
+ return ppt;
+}
+
+#endif /* !USE_VIS */
+
+#endif /* FFBLOOPS_H */
diff --git a/src/ffb_plygon.c b/src/ffb_plygon.c
new file mode 100644
index 0000000..933b15f
--- /dev/null
+++ b/src/ffb_plygon.c
@@ -0,0 +1,167 @@
+/*
+ * Acceleration for the Creator and Creator3D framebuffer - Polygon rops.
+ *
+ * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com)
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * JAKUB JELINEK OR DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_plygon.c,v 1.2 2000/05/23 04:47:45 dawes Exp $ */
+
+#include "ffb.h"
+#include "ffb_regs.h"
+#include "ffb_rcache.h"
+#include "ffb_fifo.h"
+#include "ffb_stip.h"
+
+#include "pixmapstr.h"
+#include "scrnintstr.h"
+
+#define PSZ 8
+#include "cfb.h"
+#undef PSZ
+#include "cfb32.h"
+
+#include "mi.h"
+
+void
+CreatorFillPolygon (DrawablePtr pDrawable, GCPtr pGC, int shape, int mode, int count, DDXPointPtr ppt)
+{
+ WindowPtr pWin = (WindowPtr) pDrawable;
+ CreatorPrivGCPtr gcPriv = CreatorGetGCPrivate (pGC);
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pGC->pScreen);
+ ffb_fbcPtr ffb = pFfb->regs;
+ BoxRec box;
+ int lx, rx, ty, by;
+ int t, b, i, j, k, l, tt;
+ int xy[12] FFB_ALIGN64;
+ int xOrg, yOrg;
+
+ FFBLOG(("CreatorFillPolygon: ALU(%x) PMSK(%08x) shape(%d) mode(%d) count(%d)\n",
+ pGC->alu, pGC->planemask, shape, mode, count));
+ if (count < 3)
+ return;
+
+ if (shape != Convex && count > 3) {
+ miFillPolygon (pDrawable, pGC, shape, mode, count, ppt);
+ return;
+ }
+
+ xOrg = pDrawable->x;
+ yOrg = pDrawable->y;
+
+ ppt->x += xOrg;
+ ppt->y += yOrg;
+ lx = ppt->x;
+ rx = ppt->x;
+ ty = ppt->y;
+ by = ppt->y;
+ t = b = 0;
+ tt = 1;
+ for (i = 1; i < count; i++) {
+ if (mode == CoordModeOrigin) {
+ ppt[i].x += xOrg;
+ ppt[i].y += yOrg;
+ } else {
+ ppt[i].x += ppt[i-1].x;
+ ppt[i].y += ppt[i-1].y;
+ }
+ if (ppt[i].x < lx)
+ lx = ppt[i].x;
+ if (ppt[i].x > rx)
+ rx = ppt[i].x;
+ if (ppt[i].y < ty) {
+ ty = ppt[i].y;
+ t = i;
+ tt = 1;
+ } else if (ppt[i].y == ty)
+ tt++;
+ if (ppt[i].y > by) {
+ by = ppt[i].y;
+ b = i;
+ }
+ }
+ if (tt > 2) {
+ miFillConvexPoly(pDrawable, pGC, count, ppt);
+ return;
+ } else if (tt == 2) {
+ i = t - 1;
+ if (i < 0)
+ i = count - 1;
+ if (ppt[i].y == ppt[t].y)
+ t = i;
+ }
+ box.x1 = lx;
+ box.x2 = rx + 1;
+ box.y1 = ty;
+ box.y2 = by + 1;
+
+ switch (RECT_IN_REGION(pGC->pScreen, cfbGetCompositeClip(pGC), &box)) {
+ case rgnPART:
+ miFillConvexPoly(pDrawable, pGC, count, ppt);
+ case rgnOUT:
+ return;
+ }
+ if(gcPriv->stipple == NULL) {
+ FFB_ATTR_GC(pFfb, pGC, pWin,
+ FFB_PPC_APE_DISABLE | FFB_PPC_CS_CONST,
+ FFB_DRAWOP_POLYGON);
+ } else {
+ unsigned int fbc;
+
+ FFBSetStipple(pFfb, ffb, gcPriv->stipple,
+ FFB_PPC_CS_CONST, FFB_PPC_CS_MASK);
+ FFB_WRITE_PMASK(pFfb, ffb, pGC->planemask);
+ FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_POLYGON);
+ fbc = FFB_FBC_WIN(pWin);
+ fbc = (fbc & ~FFB_FBC_XE_MASK) | FFB_FBC_XE_OFF;
+ FFB_WRITE_FBC(pFfb, ffb, fbc);
+ }
+ xy[0] = ppt[t].y;
+ xy[1] = ppt[t].x;
+ j = t + 1;
+ if (j == count) j = 0;
+ xy[2] = ppt[j].y;
+ xy[3] = ppt[j].x;
+ j = t + 2;
+ if (j >= count)
+ j -= count;
+ for (i = 2 * count - 4; i; i -= k) {
+ b = 2;
+ for (k = 0; k < i && k < 8; k+=2) {
+ xy[4 + k] = ppt[j].y;
+ xy[4 + k + 1] = ppt[j].x;
+ if (xy[4 + k] > xy[b])
+ b = 4 + k;
+ j++; if (j == count) j = 0;
+ }
+ FFBFifo(pFfb, 4 + k);
+ for (l = 0; l < b - 2; l+=2)
+ FFB_WRITE64P(&ffb->by, &xy[l]);
+ FFB_WRITE64P(&ffb->bh, &xy[l]);
+ for (l+=2; l <= k; l+=2)
+ FFB_WRITE64P(&ffb->by, &xy[l]);
+ FFB_WRITE64P(&ffb->ebyi, &xy[l]);
+ xy[2] = xy[l];
+ xy[3] = xy[l+1];
+ }
+ pFfb->rp_active = 1;
+ FFBSync(pFfb, ffb);
+}
diff --git a/src/ffb_point.c b/src/ffb_point.c
new file mode 100644
index 0000000..407f22c
--- /dev/null
+++ b/src/ffb_point.c
@@ -0,0 +1,108 @@
+/*
+ * Acceleration for the Creator and Creator3D framebuffer - Point rops.
+ *
+ * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com)
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * JAKUB JELINEK OR DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_point.c,v 1.2 2000/05/23 04:47:45 dawes Exp $ */
+
+#include "ffb.h"
+#include "ffb_regs.h"
+#include "ffb_rcache.h"
+#include "ffb_fifo.h"
+#include "ffb_loops.h"
+
+#include "pixmapstr.h"
+#include "scrnintstr.h"
+
+#define PSZ 8
+#include "cfb.h"
+#undef PSZ
+#include "cfb32.h"
+
+void
+CreatorPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode,
+ int npt, xPoint *pptInit)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pGC->pScreen);
+ WindowPtr pWin = (WindowPtr) pDrawable;
+ ffb_fbcPtr ffb = pFfb->regs;
+ RegionPtr clip;
+ int numRects;
+ register int off, c1, c2;
+ register char *addrp;
+ register int *ppt, pt, i;
+ BoxPtr pbox;
+ xPoint *pptPrev;
+
+ FFBLOG(("CreatorPolyPoint: ALU(%x) PMSK(%08x) mode(%d) npt(%d)\n",
+ pGC->alu, pGC->planemask, mode, npt));
+
+ if (pGC->alu == GXnoop)
+ return;
+
+ clip = cfbGetCompositeClip(pGC);
+ numRects = REGION_NUM_RECTS(clip);
+ off = *(int *)&pDrawable->x;
+ off -= (off & 0x8000) << 1;
+ if (mode == CoordModePrevious && npt > 1) {
+ for (pptPrev = pptInit + 1, i = npt - 1; --i >= 0; pptPrev++) {
+ pptPrev->x += pptPrev[-1].x;
+ pptPrev->y += pptPrev[-1].y;
+ }
+ }
+
+ FFB_ATTR_GC(pFfb, pGC, pWin,
+ FFB_PPC_APE_DISABLE | FFB_PPC_CS_CONST,
+ pFfb->drawop_cache);
+ FFBWait(pFfb, ffb);
+
+ if (pGC->depth == 8) {
+ addrp = (char *)pFfb->sfb8r + (pDrawable->y << 11) + (pDrawable->x << 0);
+ pbox = REGION_RECTS(clip);
+ while (numRects--) {
+ c1 = *(int *)&pbox->x1 - off;
+ c2 = *(int *)&pbox->x2 - off - 0x00010001;
+ for (ppt = (int *)pptInit, i = npt; --i >= 0; ) {
+ pt = *ppt++;
+ if (!(((pt - c1) | (c2 - pt)) & 0x80008000))
+ *(unsigned char *)(addrp + ((pt << 11) & 0x3ff800) +
+ ((pt >> 16) & 0x07ff)) = 0;
+ }
+ pbox++;
+ }
+ } else {
+ addrp = (char *)pFfb->sfb32 + (pDrawable->y << 13) + (pDrawable->x << 2);
+ pbox = REGION_RECTS(clip);
+ while (numRects--) {
+ c1 = *(int *)&pbox->x1 - off;
+ c2 = *(int *)&pbox->x2 - off - 0x00010001;
+ for (ppt = (int *)pptInit, i = npt; --i >= 0; ) {
+ pt = *ppt++;
+ if (!(((pt - c1) | (c2 - pt)) & 0x80008000))
+ *(unsigned int *)(addrp + ((pt << 13) & 0xffe000) +
+ ((pt >> 14) & 0x1ffc)) = 0;
+ }
+ pbox++;
+ }
+ }
+}
diff --git a/src/ffb_rcache.h b/src/ffb_rcache.h
new file mode 100644
index 0000000..5beb23e
--- /dev/null
+++ b/src/ffb_rcache.h
@@ -0,0 +1,333 @@
+/*
+ * Acceleration for the Creator and Creator3D framebuffer - register caching.
+ *
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * JAKUB JELINEK OR DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_rcache.h,v 1.2 2000/05/23 04:47:45 dawes Exp $ */
+
+#ifndef FFBRCACHE_H
+#define FFBRCACHE_H
+
+/* We only need to write the bits which actually change,
+ * writing unnessary bits causes the operation to go more
+ * slowly. -DaveM
+ *
+ * We used to have some hairy code here which tried to
+ * avoid writing attribute bits unnecessarily. It has been
+ * removed because various two bit fields have different
+ * semantics. For example, for some the higher bit is the
+ * edit bit, for others there are three state patterns
+ * and zero is a special "no edit" value. Ho hum, it was
+ * a nice idea...
+ */
+#define FFB_WRITE_PPC(__fpriv, __ffb, __val, __chg_mask) \
+do { unsigned int oldval = (__fpriv)->ppc_cache; \
+ unsigned int __t; \
+ __t = (oldval & (__chg_mask)) ^ (__val); \
+ if (__t) { \
+ unsigned int newval = oldval & ~(__chg_mask); \
+ newval |= (__val); \
+ (__fpriv)->ppc_cache = newval; \
+ FFBFifo((__fpriv), 1); \
+ (__ffb)->ppc = (__val); \
+ } \
+} while(0)
+
+#define FFB_WRITE_PMASK(__fpriv, __ffb, __val) \
+do { if((__fpriv)->pmask_cache != (__val)) { \
+ (__fpriv)->pmask_cache = (__val); \
+ FFBFifo((__fpriv), 1); \
+ (__ffb)->pmask = (__val); \
+ } \
+} while(0)
+
+#define FFB_WRITE_ROP(__fpriv, __ffb, __val) \
+do { if((__fpriv)->rop_cache != (__val)) { \
+ (__fpriv)->rop_cache = (__val); \
+ FFBFifo((__fpriv), 1); \
+ (__ffb)->rop = (__val); \
+ } \
+} while(0)
+
+#define FFB_WRITE_DRAWOP(__fpriv, __ffb, __val) \
+do { if((__fpriv)->drawop_cache != (__val)) { \
+ (__fpriv)->drawop_cache = (__val); \
+ FFBFifo((__fpriv), 1); \
+ (__ffb)->drawop = (__val); \
+ } \
+} while(0)
+
+#define FFB_WRITE_FG(__fpriv, __ffb, __val) \
+do { if((__fpriv)->fg_cache != (__val)) { \
+ (__fpriv)->fg_cache = (__val); \
+ FFBFifo((__fpriv), 1); \
+ (__ffb)->fg = (__val); \
+ } \
+} while(0)
+
+#define FFB_WRITE_BG(__fpriv, __ffb, __val) \
+do { if((__fpriv)->bg_cache != (__val)) { \
+ (__fpriv)->bg_cache = (__val); \
+ FFBFifo((__fpriv), 1); \
+ (__ffb)->bg = (__val); \
+ } \
+} while(0)
+
+#define FFB_WRITE_FONTW(__fpriv, __ffb, __val) \
+do { if((__fpriv)->fontw_cache != (__val)) { \
+ (__fpriv)->fontw_cache = (__val); \
+ FFBFifo((__fpriv), 1); \
+ (__ffb)->fontw = (__val); \
+ } \
+} while(0)
+
+#define FFB_WRITE_FONTINC(__fpriv, __ffb, __val) \
+do { if((__fpriv)->fontinc_cache != (__val)) { \
+ (__fpriv)->fontinc_cache = (__val); \
+ FFBFifo((__fpriv), 1); \
+ (__ffb)->fontinc = (__val); \
+ } \
+} while(0)
+
+#define FFB_WRITE_FBC(__fpriv, __ffb, __val) \
+do { if((__fpriv)->fbc_cache != (__val)) { \
+ (__fpriv)->fbc_cache = (__val); \
+ FFBFifo((__fpriv), 1); \
+ (__ffb)->fbc = (__val); \
+ } \
+} while(0)
+
+#define FFB_WRITE_WID(__fpriv, __ffb, __val) \
+do { if((__fpriv)->wid_cache != (__val)) { \
+ (__fpriv)->wid_cache = (__val); \
+ FFBFifo((__fpriv), 1); \
+ (__ffb)->wid = (__val); \
+ } \
+} while(0)
+
+extern void __FFB_Attr_Raw(FFBPtr pFfb,
+ unsigned int ppc,
+ unsigned int ppc_mask,
+ unsigned int pmask,
+ unsigned int rop,
+ int drawop, int fg,
+ unsigned int fbc,
+ unsigned int wid);
+
+#define FFB_ATTR_RAW(__fpriv, __ppc, __ppc_mask, __pmask, __rop, __drawop, __fg, __fbc, __wid) \
+ if((((__fpriv)->ppc_cache & (__ppc_mask)) != (__ppc)) || \
+ ((__fpriv)->pmask_cache != (__pmask)) || \
+ ((__fpriv)->rop_cache != (__rop)) || \
+ (((__drawop) != -1) && ((__fpriv)->drawop_cache != (__drawop))) || \
+ ((__fpriv)->fg_cache != (__fg)) || \
+ ((__fpriv)->fbc_cache != (__fbc)) || \
+ ((__fpriv)->wid_cache != (__wid))) \
+ __FFB_Attr_Raw((__fpriv), (__ppc), (__ppc_mask), (__pmask), \
+ (__rop), (__drawop), (__fg), (__fbc), (__wid))
+
+#define FFB_PPC_GCMASK (FFB_PPC_APE_MASK | FFB_PPC_CS_MASK)
+
+/* This is for loading the FFB attributes for the case where
+ * where most of the values come directly from the graphics
+ * context and only the PPC and DRAWOP are variable.
+ */
+extern void __FFB_Attr_GC(FFBPtr pFfb, GCPtr pGC, WindowPtr pWin,
+ unsigned int ppc, int drawop);
+
+#define FFB_ATTR_GC(__fpriv, __pgc, __pwin, __ppc, __drawop) \
+do { CreatorPrivWinPtr __winpriv = CreatorGetWindowPrivate(__pwin); \
+ unsigned int __rop = ((__pgc)->alu | FFB_ROP_EDIT_BIT); \
+ unsigned int __fbc = ((__winpriv)->fbc_base); \
+ __fbc &= ~FFB_FBC_XE_MASK; \
+ __fbc |= FFB_FBC_XE_OFF; \
+ __rop |= (FFB_ROP_NEW << 8); \
+ if ((((__fpriv)->ppc_cache & FFB_PPC_GCMASK) != (__ppc))|| \
+ ((__fpriv)->pmask_cache != ((__pgc)->planemask)) || \
+ ((__fpriv)->rop_cache != (__rop)) || \
+ ((__fpriv)->drawop_cache != (__drawop)) || \
+ ((__fpriv)->fg_cache != ((__pgc)->fgPixel)) || \
+ ((__fpriv)->fbc_cache != __fbc)) \
+ __FFB_Attr_GC(__fpriv, __pgc, __pwin, __ppc, __drawop); \
+} while(0)
+
+#define FFB_PPC_WINMASK (FFB_PPC_APE_MASK | FFB_PPC_CS_MASK | FFB_PPC_XS_MASK)
+
+extern void __FFB_Attr_FastfillWin(FFBPtr pFfb, WindowPtr pWin,
+ unsigned int ppc, unsigned int pixel);
+
+#define FFB_ATTR_FFWIN(__fpriv, __pwin, __ppc, __pixel) \
+do { CreatorPrivWinPtr __winpriv = CreatorGetWindowPrivate(__pwin); \
+ unsigned int ___ppc = (__ppc) | FFB_PPC_XS_WID; \
+ unsigned int fbc = (__winpriv)->fbc_base; \
+ unsigned int rop = (FFB_ROP_NEW|(FFB_ROP_NEW<<8)); \
+ if((__fpriv)->has_double_buffer) { \
+ fbc &= ~FFB_FBC_WB_MASK; \
+ fbc |= FFB_FBC_WB_AB; \
+ } \
+ fbc &= ~(FFB_FBC_XE_MASK | FFB_FBC_RGBE_MASK); \
+ fbc |= FFB_FBC_XE_ON | FFB_FBC_RGBE_ON; \
+ if (pFfb->ffb_res == ffb_res_high) \
+ fbc |= FFB_FBC_WB_B; \
+ if ((((__fpriv)->ppc_cache & FFB_PPC_WINMASK) != (___ppc))|| \
+ ((__fpriv)->pmask_cache != 0x00ffffff) || \
+ ((__fpriv)->rop_cache!= rop) || \
+ ((__fpriv)->drawop_cache != FFB_DRAWOP_FASTFILL) || \
+ ((__fpriv)->fg_cache != (__pixel)) || \
+ ((__fpriv)->fbc_cache != fbc) || \
+ ((__fpriv)->wid_cache != ((__winpriv)->wid))) \
+ __FFB_Attr_FastfillWin(__fpriv, __pwin, ___ppc, __pixel);\
+} while (0)
+
+/* We have to be careful when copying windows around. For that
+ * case we will use either VIS copies or hw accelerated VSCROLL.
+ * All of the planes needs to be copied in the framebuffer from
+ * src to dst in order to handle child windows using different WIDs
+ * than the parent window being copied.
+ */
+
+/* Setup to access the smart frame buffer (SFB) directly where the
+ * pixel color comes from the cpu on writes.
+ */
+#define FFB_PPC_WINCOPY (FFB_PPC_APE_DISABLE | FFB_PPC_XS_VAR | FFB_PPC_CS_VAR)
+#define FFB_PPC_WINCOPY_MASK (FFB_PPC_APE_MASK | FFB_PPC_XS_MASK | FFB_PPC_CS_MASK)
+#define FFB_FBC_WINCOPY (FFB_FBC_WB_A | FFB_FBC_WM_COMBINED | FFB_FBC_WE_FORCEON | \
+ FFB_FBC_RB_A | FFB_FBC_SB_BOTH | FFB_FBC_XE_ON | \
+ FFB_FBC_ZE_OFF | FFB_FBC_YE_OFF | FFB_FBC_RGBE_ON)
+
+#define FFB_ATTR_SFB_VAR_WINCOPY(__fpriv) \
+do { unsigned int ppc = FFB_PPC_WINCOPY; \
+ unsigned int ppc_mask = FFB_PPC_WINCOPY_MASK; \
+ unsigned int rop = FFB_ROP_NEW|(FFB_ROP_NEW<<8); \
+ unsigned int fbc = FFB_FBC_WINCOPY; \
+ if((__fpriv)->has_double_buffer) { \
+ fbc &= ~FFB_FBC_WB_MASK; \
+ fbc |= FFB_FBC_WB_AB; \
+ } \
+ if (((__fpriv)->ppc_cache & ppc_mask) != ppc || \
+ (__fpriv)->fbc_cache != fbc || \
+ (__fpriv)->rop_cache != rop || \
+ (__fpriv)->pmask_cache != 0xffffffff) { \
+ ffb_fbcPtr __ffb = (__fpriv)->regs; \
+ (__fpriv)->ppc_cache &= ~ppc_mask; \
+ (__fpriv)->ppc_cache |= ppc; \
+ (__fpriv)->fbc_cache = fbc; \
+ (__fpriv)->rop_cache = rop; \
+ (__fpriv)->pmask_cache = 0xffffffff; \
+ (__fpriv)->rp_active = 1; \
+ FFBFifo(__fpriv, 4); \
+ (__ffb)->ppc = ppc; \
+ (__ffb)->fbc = fbc; \
+ (__ffb)->rop = rop; \
+ (__ffb)->pmask = 0xffffffff; \
+ (__fpriv)->rp_active = 1; \
+ } \
+} while(0)
+
+extern void __FFB_Attr_SFB_VAR(FFBPtr pFfb, unsigned int ppc, unsigned int ppc_mask, unsigned int fbc,
+ unsigned int wid, unsigned int rop, unsigned int pmask);
+
+#define FFB_ATTR_SFB_VAR_WIN(__fpriv, __pmask, __alu, __pwin) \
+do { unsigned int ppc = FFB_PPC_APE_DISABLE | FFB_PPC_CS_VAR | FFB_PPC_XS_WID; \
+ unsigned int ppc_mask = FFB_PPC_APE_MASK | FFB_PPC_CS_MASK | FFB_PPC_XS_MASK; \
+ unsigned int rop = (FFB_ROP_EDIT_BIT | (__alu))|(FFB_ROP_NEW<<8); \
+ unsigned int fbc = FFB_FBC_WIN(__pwin); \
+ if((__fpriv)->has_double_buffer) { \
+ fbc &= ~FFB_FBC_WB_MASK; \
+ fbc |= FFB_FBC_WB_AB; \
+ } \
+ if(((__fpriv)->ppc_cache & ppc_mask) != ppc || \
+ (__fpriv)->fbc_cache != fbc || \
+ (__fpriv)->wid_cache != FFB_WID_WIN(__pwin) || \
+ (__fpriv)->rop_cache != rop || \
+ (__fpriv)->pmask_cache != (__pmask)) \
+ __FFB_Attr_SFB_VAR(__fpriv, ppc, ppc_mask, fbc, \
+ FFB_WID_WIN(__pwin), rop, (__pmask)); \
+} while(0)
+
+/* VSCROLL Attributes:
+ *
+ * PPC) VCE_DISABLE must be set, all other attributes are effectively
+ * ignored since this drawop just copies pixels within the ram
+ * chips and bypasses the pixel processor entirely. So you
+ * end up with a PPC color source behavior of {ZS,YS,XS,CS}_VAR.
+ * FBC) all options are allowed, but the SRC/DST buffers are determined
+ * solely by the WB_* setting, that is, the RB_* setting is effectively
+ * ignored since the pixels are copied directly through the write buffer
+ * ROP) must be FFB_ROP_OLD (even for the X plane!)
+ * PMASK) all options allowed
+ */
+#define FFB_ATTR_VSCROLL_WINCOPY(__fpriv) \
+do { unsigned int rop = (FFB_ROP_OLD | (FFB_ROP_OLD << 8)); \
+ unsigned int fbc = FFB_FBC_WINCOPY; \
+ if((__fpriv)->has_double_buffer) { \
+ fbc &= ~FFB_FBC_WB_MASK; \
+ fbc |= FFB_FBC_WB_AB; \
+ } \
+ if((__fpriv)->fbc_cache != fbc || \
+ (__fpriv)->rop_cache != rop || \
+ (__fpriv)->pmask_cache != 0xffffffff || \
+ (__fpriv)->drawop_cache != FFB_DRAWOP_VSCROLL) { \
+ ffb_fbcPtr __ffb = (__fpriv)->regs; \
+ (__fpriv)->fbc_cache = fbc; \
+ (__fpriv)->rop_cache = rop; \
+ (__fpriv)->pmask_cache = 0xffffffff; \
+ (__fpriv)->drawop_cache = FFB_DRAWOP_VSCROLL; \
+ (__fpriv)->rp_active = 1; \
+ FFBFifo(__fpriv, 4); \
+ (__ffb)->fbc = fbc; \
+ (__ffb)->rop = rop; \
+ (__ffb)->pmask = 0xffffffff; \
+ (__ffb)->drawop = FFB_DRAWOP_VSCROLL; \
+ (__fpriv)->rp_active = 1; \
+ } \
+} while(0)
+
+#define FFB_ATTR_VSCROLL_WIN(__fpriv, __pmask, __pwin) \
+do { unsigned int rop = (FFB_ROP_OLD | (FFB_ROP_OLD << 8)); \
+ unsigned int fbc = FFB_FBC_WIN(__pwin); \
+ if((__fpriv)->has_double_buffer) { \
+ fbc &= ~FFB_FBC_WB_MASK; \
+ fbc |= FFB_FBC_WB_AB; \
+ } \
+ if((__fpriv)->fbc_cache != fbc || \
+ (__fpriv)->rop_cache != rop || \
+ (__fpriv)->pmask_cache != (__pmask) || \
+ (__fpriv)->drawop_cache != FFB_DRAWOP_VSCROLL) { \
+ ffb_fbcPtr __ffb = (__fpriv)->regs; \
+ (__fpriv)->fbc_cache = fbc; \
+ (__fpriv)->rop_cache = rop; \
+ (__fpriv)->pmask_cache = (__pmask); \
+ (__fpriv)->drawop_cache = FFB_DRAWOP_VSCROLL; \
+ (__fpriv)->rp_active = 1; \
+ FFBFifo(__fpriv, 4); \
+ (__ffb)->fbc = fbc; \
+ (__ffb)->rop = rop; \
+ (__ffb)->pmask = (__pmask); \
+ (__ffb)->drawop = FFB_DRAWOP_VSCROLL; \
+ } \
+} while(0)
+
+#define FFB_FBC_WIN(pWin) CreatorGetWindowPrivate(pWin)->fbc_base
+#define FFB_WID_WIN(pWin) CreatorGetWindowPrivate(pWin)->wid
+
+#endif /* FFBRCACHE_H */
diff --git a/src/ffb_rect.c b/src/ffb_rect.c
new file mode 100644
index 0000000..30ef015
--- /dev/null
+++ b/src/ffb_rect.c
@@ -0,0 +1,207 @@
+/*
+ * Acceleration for the Creator and Creator3D framebuffer - Non-filled rects.
+ *
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_rect.c,v 1.2 2000/05/23 04:47:45 dawes Exp $ */
+
+#define PSZ 32
+
+#include "ffb.h"
+#include "ffb_regs.h"
+#include "ffb_rcache.h"
+#include "ffb_fifo.h"
+#include "ffb_loops.h"
+#include "ffb_clip.h"
+
+#include "pixmapstr.h"
+#include "scrnintstr.h"
+
+#include "cfb.h"
+
+#error If we start using this again, need to fixup FFB_WRITE_ATTRIBUTES for wids -DaveM
+
+/* Heavily derived from mipolyrect.c code, see there for authors. */
+
+/* This about it, capping makes not a single difference ever,
+ * always the upper left corner coordinate will be pixelated.
+ */
+void
+CreatorPolyRectangle(DrawablePtr pDrawable, GCPtr pGC,
+ int nrects, xRectangle *pRects)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pDrawable->pScreen);
+ CreatorPrivGCPtr gcPriv = CreatorGetGCPrivate (pGC);
+ ffb_fbcPtr ffb = pFfb->regs;
+ xRectangle *pR = pRects;
+ RegionPtr clip;
+ unsigned int ppc, line_drawop;
+ int bound_tmp, i, numRects;
+
+ if(nrects <= 0)
+ return;
+ clip = ((cfbPrivGC *)(pGC->devPrivates[cfbGCPrivateIndex].ptr))->pCompositeClip;
+ numRects = REGION_NUM_RECTS(clip);
+ if (!numRects)
+ return;
+ if(!(ppc = FFBSetClip(pFfb, ffb, clip, numRects))) {
+ miPolyRectangle(pDrawable, pGC, nrects, pRects);
+ return;
+ }
+ if(pGC->lineStyle == LineDoubleDash)
+ line_drawop = FFB_DRAWOP_DDLINE;
+ else
+ line_drawop = FFB_DRAWOP_BRLINECAP;
+ if(gcPriv->stipple == NULL) {
+ FFB_WRITE_ATTRIBUTES(pFfb,
+ ppc|FFB_PPC_APE_DISABLE|FFB_PPC_TBE_OPAQUE|
+ FFB_PPC_XS_CONST|FFB_PPC_YS_CONST|FFB_PPC_ZS_CONST|FFB_PPC_CS_CONST,
+ FFB_PPC_VCE_MASK|FFB_PPC_ACE_MASK|FFB_PPC_APE_MASK|FFB_PPC_TBE_MASK|
+ FFB_PPC_XS_MASK|FFB_PPC_YS_MASK|FFB_PPC_ZS_MASK|FFB_PPC_CS_MASK,
+ pGC->planemask,
+ FFB_ROP_EDIT_BIT|pGC->alu,
+ -1, pGC->fgPixel,
+ FFB_FBC_DEFAULT);
+ if(pGC->lineStyle == LineDoubleDash)
+ FFB_WRITE_BG(pFfb, ffb, pGC->bgPixel);
+ } else {
+ FFBSetStipple(pFfb, ffb, gcPriv->stipple,
+ ppc|
+ FFB_PPC_XS_CONST|FFB_PPC_YS_CONST|FFB_PPC_ZS_CONST|FFB_PPC_CS_CONST,
+ FFB_PPC_VCE_MASK|FFB_PPC_ACE_MASK|
+ FFB_PPC_XS_MASK|FFB_PPC_YS_MASK|FFB_PPC_ZS_MASK|FFB_PPC_CS_MASK);
+ FFB_WRITE_PMASK(pFfb, ffb, pGC->planemask);
+ FFB_WRITE_FBC(pFfb, ffb, FFB_FBC_DEFAULT);
+ }
+
+#define MINBOUND(dst,eqn) bound_tmp = eqn; \
+ if (bound_tmp < -32768) \
+ bound_tmp = -32768; \
+ dst = bound_tmp;
+
+#define MAXBOUND(dst,eqn) bound_tmp = eqn; \
+ if (bound_tmp > 32767) \
+ bound_tmp = 32767; \
+ dst = bound_tmp;
+
+#define MAXUBOUND(dst,eqn) bound_tmp = eqn; \
+ if (bound_tmp > 65535) \
+ bound_tmp = 65535; \
+ dst = bound_tmp;
+
+ if (pGC->lineStyle == LineSolid &&
+ pGC->joinStyle == JoinMiter &&
+ pGC->lineWidth != 0) {
+ int ntmp;
+ int offset1, offset2, offset3;
+ int x, y, width, height;
+ int tx, ty, tw, th;
+
+ ntmp = (nrects << 2);
+ offset2 = pGC->lineWidth;
+ offset1 = offset2 >> 1;
+ offset3 = offset2 - offset1;
+ for (i = 0; i < nrects; i++) {
+ x = pR->x;
+ y = pR->y;
+ width = pR->width;
+ height = pR->height;
+ pR++;
+ if (width == 0 && height == 0) {
+ FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_DOT);
+ FFBFifo(pFfb, 2);
+ FFB_WRITE64(&ffb->bh, y + pDrawable->y, x + pDrawable->x);
+ continue;
+ }
+ FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_RECTANGLE);
+ if (height < offset2 || width < offset1) {
+ if (height == 0) {
+ tx = x;
+ tw = width;
+ } else {
+ MINBOUND (tx, x - offset1);
+ MAXUBOUND (tw, width + offset2);
+ }
+ if (width == 0) {
+ ty = y;
+ th = height;
+ } else {
+ MINBOUND (ty, y - offset1);
+ MAXUBOUND (th, height + offset2);
+ }
+ FFBFifo(pFfb, 4);
+ FFB_WRITE64(&ffb->by, ty + pDrawable->y, tx + pDrawable->x);
+ FFB_WRITE64_2(&ffb->bh, th, tw);
+ } else {
+ MINBOUND(tx, x - offset1);
+ MINBOUND(ty, y - offset1);
+ MAXUBOUND(tw, width + offset2);
+ th = offset2;
+ FFBFifo(pFfb, 13);
+ FFB_WRITE64(&ffb->by, ty + pDrawable->y, tx + pDrawable->x);
+ FFB_WRITE64_2(&ffb->bh, th, tw);
+ MAXBOUND(ty, y + offset3);
+ tw = offset2;
+ th = height - offset2;
+ ffb->by = ty + pDrawable->y;
+ FFB_WRITE64_2(&ffb->bh, th, tw);
+ MAXBOUND(tx, x + width - offset1);
+ ffb->bx = tx + pDrawable->x;
+ ffb->bw = tw;
+ MINBOUND(tx, x - offset1);
+ MAXBOUND(ty, y + height - offset1);
+ MAXUBOUND(tw, width + offset2);
+ th = offset2;
+ FFB_WRITE64(&ffb->by, ty + pDrawable->y, tx + pDrawable->x);
+ FFB_WRITE64_2(&ffb->bh, th, tw);
+ }
+ }
+ } else {
+ int xOrg = pDrawable->x;
+ int yOrg = pDrawable->y;
+ unsigned int linepat = gcPriv->linepat;
+
+ FFB_WRITE_DRAWOP(pFfb, ffb, line_drawop);
+ if(linepat == 0) {
+ FFBFifo(pFfb, 1);
+ ffb->lpat = 0;
+ }
+ for (i=0; i < nrects; i++) {
+ register int x0, xCoord, y0, yCoord;
+
+ x0 = xCoord = pR->x;
+ y0 = yCoord = pR->y;
+ FFBFifo(pFfb, 11);
+ if(linepat)
+ ffb->lpat = linepat;
+ else
+ ffb->ppc = 0;
+ FFB_WRITE64(&ffb->by, (yCoord + yOrg), (xCoord + xOrg));
+ MAXBOUND(xCoord, pR->x + (int) pR->width);
+ FFB_WRITE64(&ffb->bh, (yCoord + yOrg), (xCoord + xOrg));
+ MAXBOUND(yCoord, pR->y + (int) pR->height);
+ FFB_WRITE64_2(&ffb->bh, (yCoord + yOrg), (xCoord + xOrg));
+ FFB_WRITE64_3(&ffb->bh, (yCoord + yOrg), (x0 + xOrg));
+ FFB_WRITE64(&ffb->bh, (y0 + yOrg), (x0 + xOrg));
+ pR++;
+ }
+ }
+}
diff --git a/src/ffb_regs.h b/src/ffb_regs.h
new file mode 100644
index 0000000..7f383d3
--- /dev/null
+++ b/src/ffb_regs.h
@@ -0,0 +1,509 @@
+/*
+ * Acceleration for the Creator and Creator3D framebuffer - register layout.
+ *
+ * Copyright (C) 1998,1999,2000 Jakub Jelinek (jakub@redhat.com)
+ * Copyright (C) 1998 Michal Rehacek (majkl@iname.com)
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * JAKUB JELINEK, MICHAL REHACEK, OR DAVID MILLER BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_regs.h,v 1.1 2000/05/18 23:21:37 dawes Exp $ */
+
+#ifndef FFBREGS_H
+#define FFBREGS_H
+
+/* Auxilliary clips. */
+typedef struct {
+ volatile unsigned int min;
+ volatile unsigned int max;
+} ffb_auxclip, *ffb_auxclipPtr;
+
+/* FFB register set. */
+typedef struct _ffb_fbc {
+ /* Next vertex registers, on the right we list which drawops
+ * use said register and the logical name the register has in
+ * that context.
+ */ /* DESCRIPTION DRAWOP(NAME) */
+/*0x00*/unsigned int pad1[3]; /* Reserved */
+/*0x0c*/volatile unsigned int alpha; /* ALPHA Transparency */
+/*0x10*/volatile unsigned int red; /* RED */
+/*0x14*/volatile unsigned int green; /* GREEN */
+/*0x18*/volatile unsigned int blue; /* BLUE */
+/*0x1c*/volatile unsigned int z; /* DEPTH */
+/*0x20*/volatile unsigned int y; /* Y triangle(DOYF) */
+ /* aadot(DYF) */
+ /* ddline(DYF) */
+ /* aaline(DYF) */
+/*0x24*/volatile unsigned int x; /* X triangle(DOXF) */
+ /* aadot(DXF) */
+ /* ddline(DXF) */
+ /* aaline(DXF) */
+/*0x28*/unsigned int pad2[2]; /* Reserved */
+/*0x30*/volatile unsigned int ryf; /* Y (alias to DOYF) ddline(RYF) */
+ /* aaline(RYF) */
+ /* triangle(RYF) */
+/*0x34*/volatile unsigned int rxf; /* X ddline(RXF) */
+ /* aaline(RXF) */
+ /* triangle(RXF) */
+/*0x38*/unsigned int pad3[2]; /* Reserved */
+/*0x40*/volatile unsigned int dmyf; /* Y (alias to DOYF) triangle(DMYF) */
+/*0x44*/volatile unsigned int dmxf; /* X triangle(DMXF) */
+/*0x48*/unsigned int pad4[2]; /* Reserved */
+/*0x50*/volatile unsigned int ebyi; /* Y (alias to RYI) polygon(EBYI) */
+/*0x54*/volatile unsigned int ebxi; /* X polygon(EBXI) */
+/*0x58*/unsigned int pad5[2]; /* Reserved */
+/*0x60*/volatile unsigned int by; /* Y brline(RYI) */
+ /* fastfill(OP) */
+ /* polygon(YI) */
+ /* rectangle(YI) */
+ /* bcopy(SRCY) */
+ /* vscroll(SRCY) */
+/*0x64*/volatile unsigned int bx; /* X brline(RXI) */
+ /* polygon(XI) */
+ /* rectangle(XI) */
+ /* bcopy(SRCX) */
+ /* vscroll(SRCX) */
+ /* fastfill(GO) */
+/*0x68*/volatile unsigned int dy; /* destination Y fastfill(DSTY) */
+ /* bcopy(DSRY) */
+ /* vscroll(DSRY) */
+/*0x6c*/volatile unsigned int dx; /* destination X fastfill(DSTX) */
+ /* bcopy(DSTX) */
+ /* vscroll(DSTX) */
+/*0x70*/volatile unsigned int bh; /* Y (alias to RYI) brline(DYI) */
+ /* dot(DYI) */
+ /* polygon(ETYI) */
+ /* Height fastfill(H) */
+ /* bcopy(H) */
+ /* vscroll(H) */
+ /* Y count fastfill(NY) */
+/*0x74*/volatile unsigned int bw; /* X dot(DXI) */
+ /* brline(DXI) */
+ /* polygon(ETXI) */
+ /* fastfill(W) */
+ /* bcopy(W) */
+ /* vscroll(W) */
+ /* fastfill(NX) */
+/*0x78*/unsigned int pad6[2]; /* Reserved */
+/*0x80*/unsigned int pad7[32]; /* Reserved */
+
+ /* Setup Unit's vertex state register */
+/*100*/ volatile unsigned int suvtx;
+/*104*/ unsigned int pad8[63]; /* Reserved */
+
+ /* Frame Buffer Control Registers */
+/*200*/ volatile unsigned int ppc; /* Pixel Processor Control */
+/*204*/ volatile unsigned int wid; /* Current WID */
+/*208*/ volatile unsigned int fg; /* FG data */
+/*20c*/ volatile unsigned int bg; /* BG data */
+/*210*/ volatile unsigned int consty; /* Constant Y */
+/*214*/ volatile unsigned int constz; /* Constant Z */
+/*218*/ volatile unsigned int xclip; /* X Clip */
+/*21c*/ volatile unsigned int dcss; /* Depth Cue Scale Slope */
+/*220*/ volatile unsigned int vclipmin; /* Viewclip XY Min Bounds */
+/*224*/ volatile unsigned int vclipmax; /* Viewclip XY Max Bounds */
+/*228*/ volatile unsigned int vclipzmin; /* Viewclip Z Min Bounds */
+/*22c*/ volatile unsigned int vclipzmax; /* Viewclip Z Max Bounds */
+/*230*/ volatile unsigned int dcsf; /* Depth Cue Scale Front Bound */
+/*234*/ volatile unsigned int dcsb; /* Depth Cue Scale Back Bound */
+/*238*/ volatile unsigned int dczf; /* Depth Cue Z Front */
+/*23c*/ volatile unsigned int dczb; /* Depth Cue Z Back */
+/*240*/ unsigned int pad9; /* Reserved */
+/*244*/ volatile unsigned int blendc; /* Alpha Blend Control */
+/*248*/ volatile unsigned int blendc1; /* Alpha Blend Color 1 */
+/*24c*/ volatile unsigned int blendc2; /* Alpha Blend Color 2 */
+/*250*/ volatile unsigned int fbramitc; /* FB RAM Interleave Test Control */
+/*254*/ volatile unsigned int fbc; /* Frame Buffer Control */
+/*258*/ volatile unsigned int rop; /* Raster OPeration */
+/*25c*/ volatile unsigned int cmp; /* Frame Buffer Compare */
+/*260*/ volatile unsigned int matchab; /* Buffer AB Match Mask */
+/*264*/ volatile unsigned int matchc; /* Buffer C(YZ) Match Mask */
+/*268*/ volatile unsigned int magnab; /* Buffer AB Magnitude Mask */
+/*26c*/ volatile unsigned int magnc; /* Buffer C(YZ) Magnitude Mask */
+/*270*/ volatile unsigned int fbcfg0; /* Frame Buffer Config 0 */
+/*274*/ volatile unsigned int fbcfg1; /* Frame Buffer Config 1 */
+/*278*/ volatile unsigned int fbcfg2; /* Frame Buffer Config 2 */
+/*27c*/ volatile unsigned int fbcfg3; /* Frame Buffer Config 3 */
+/*280*/ volatile unsigned int ppcfg; /* Pixel Processor Config */
+/*284*/ volatile unsigned int pick; /* Picking Control */
+/*288*/ volatile unsigned int fillmode; /* FillMode */
+/*28c*/ volatile unsigned int fbramwac; /* FB RAM Write Address Control */
+/*290*/ volatile unsigned int pmask; /* RGB PlaneMask */
+/*294*/ volatile unsigned int xpmask; /* X PlaneMask */
+/*298*/ volatile unsigned int ypmask; /* Y PlaneMask */
+/*29c*/ volatile unsigned int zpmask; /* Z PlaneMask */
+/*2a0*/ ffb_auxclip auxclip[4]; /* Auxilliary Viewport Clip */
+
+ /* New 3dRAM III support regs */
+/*2c0*/ volatile unsigned int rawblend2;
+/*2c4*/ volatile unsigned int rawpreblend;
+/*2c8*/ volatile unsigned int rawstencil;
+/*2cc*/ volatile unsigned int rawstencilctl;
+/*2d0*/ volatile unsigned int threedram1;
+/*2d4*/ volatile unsigned int threedram2;
+/*2d8*/ volatile unsigned int passin;
+/*2dc*/ volatile unsigned int rawclrdepth;
+/*2e0*/ volatile unsigned int rawpmask;
+/*2e4*/ volatile unsigned int rawcsrc;
+/*2e8*/ volatile unsigned int rawmatch;
+/*2ec*/ volatile unsigned int rawmagn;
+/*2f0*/ volatile unsigned int rawropblend;
+/*2f4*/ volatile unsigned int rawcmp;
+/*2f8*/ volatile unsigned int rawwac;
+/*2fc*/ volatile unsigned int fbramid;
+
+/*300*/ volatile unsigned int drawop; /* Draw OPeration */
+/*304*/ unsigned int pad10[2]; /* Reserved */
+/*30c*/ volatile unsigned int lpat; /* Line Pattern control */
+/*310*/ unsigned int pad11; /* Reserved */
+/*314*/ volatile unsigned int fontxy; /* XY Font coordinate */
+/*318*/ volatile unsigned int fontw; /* Font Width */
+/*31c*/ volatile unsigned int fontinc; /* Font Increment */
+/*320*/ volatile unsigned int font; /* Font bits */
+/*324*/ unsigned int pad12[3]; /* Reserved */
+/*330*/ volatile unsigned int blend2;
+/*334*/ volatile unsigned int preblend;
+/*338*/ volatile unsigned int stencil;
+/*33c*/ volatile unsigned int stencilctl;
+
+/*340*/ unsigned int pad13[4]; /* Reserved */
+/*350*/ volatile unsigned int dcss1; /* Depth Cue Scale Slope 1 */
+/*354*/ volatile unsigned int dcss2; /* Depth Cue Scale Slope 2 */
+/*358*/ volatile unsigned int dcss3; /* Depth Cue Scale Slope 3 */
+/*35c*/ volatile unsigned int widpmask;
+/*360*/ volatile unsigned int dcs2;
+/*364*/ volatile unsigned int dcs3;
+/*368*/ volatile unsigned int dcs4;
+/*36c*/ unsigned int pad14; /* Reserved */
+/*370*/ volatile unsigned int dcd2;
+/*374*/ volatile unsigned int dcd3;
+/*378*/ volatile unsigned int dcd4;
+/*37c*/ unsigned int pad15; /* Reserved */
+/*380*/ volatile unsigned int pattern[32]; /* area Pattern */
+/*400*/ unsigned int pad16[8]; /* Reserved */
+/*420*/ volatile unsigned int reset; /* chip RESET */
+/*424*/ unsigned int pad17[247]; /* Reserved */
+/*800*/ volatile unsigned int devid; /* Device ID */
+/*804*/ unsigned int pad18[63]; /* Reserved */
+/*900*/ volatile unsigned int ucsr; /* User Control & Status Register */
+/*904*/ unsigned int pad19[31]; /* Reserved */
+/*980*/ volatile unsigned int mer; /* Mode Enable Register */
+/*984*/ unsigned int pad20[1439]; /* Reserved */
+} ffb_fbc, *ffb_fbcPtr;
+
+/* Draw operations */
+#define FFB_DRAWOP_DOT 0x00
+#define FFB_DRAWOP_AADOT 0x01
+#define FFB_DRAWOP_BRLINECAP 0x02
+#define FFB_DRAWOP_BRLINEOPEN 0x03
+#define FFB_DRAWOP_DDLINE 0x04
+#define FFB_DRAWOP_AALINE 0x05
+#define FFB_DRAWOP_TRIANGLE 0x06
+#define FFB_DRAWOP_POLYGON 0x07
+#define FFB_DRAWOP_RECTANGLE 0x08
+#define FFB_DRAWOP_FASTFILL 0x09
+#define FFB_DRAWOP_BCOPY 0x0a /* Not implemented in any FFB, VIS is faster */
+#define FFB_DRAWOP_VSCROLL 0x0b /* Up to 12x faster than BCOPY, 3-4x faster than VIS */
+
+/* FastFill operation codes. */
+#define FFB_FASTFILL_PAGE 0x01
+#define FFB_FASTFILL_BLOCK 0x02
+#define FFB_FASTFILL_COLOR_BLK 0x03
+#define FFB_FASTFILL_BLOCK_X 0x04
+
+/* Spanfill Unit Line Pattern */
+#define FFB_LPAT_SCALEPTR 0xf0000000
+#define FFB_LPAT_SCALEPTR_SHIFT 28
+#define FFB_LPAT_PATPTR 0x0f000000
+#define FFB_LPAT_PATPTR_SHIFT 24
+#define FFB_LPAT_SCALEVAL 0x00f00000
+#define FFB_LPAT_SCALEVAL_SHIFT 20
+#define FFB_LPAT_PATLEN 0x000f0000
+#define FFB_LPAT_PATLEN_SHIFT 16
+#define FFB_LPAT_PATTERN 0x0000ffff
+#define FFB_LPAT_PATTERN_SHIFT 0
+
+/* Pixel processor control */
+/* Force WID */
+#define FFB_PPC_FW_DISABLE 0x800000
+#define FFB_PPC_FW_ENABLE 0xc00000
+#define FFB_PPC_FW_MASK 0xc00000
+/* Auxiliary clip */
+#define FFB_PPC_ACE_DISABLE 0x040000
+#define FFB_PPC_ACE_AUX_SUB 0x080000
+#define FFB_PPC_ACE_AUX_ADD 0x0c0000
+#define FFB_PPC_ACE_MASK 0x0c0000
+/* Depth cue */
+#define FFB_PPC_DCE_DISABLE 0x020000
+#define FFB_PPC_DCE_ENABLE 0x030000
+#define FFB_PPC_DCE_MASK 0x030000
+/* Alpha blend */
+#define FFB_PPC_ABE_DISABLE 0x008000
+#define FFB_PPC_ABE_ENABLE 0x00c000
+#define FFB_PPC_ABE_MASK 0x00c000
+/* View clip */
+#define FFB_PPC_VCE_DISABLE 0x001000
+#define FFB_PPC_VCE_2D 0x002000
+#define FFB_PPC_VCE_3D 0x003000
+#define FFB_PPC_VCE_MASK 0x003000
+/* Area pattern */
+#define FFB_PPC_APE_DISABLE 0x000800
+#define FFB_PPC_APE_ENABLE 0x000c00
+#define FFB_PPC_APE_MASK 0x000c00
+/* Transparent background */
+#define FFB_PPC_TBE_OPAQUE 0x000200
+#define FFB_PPC_TBE_TRANSPARENT 0x000300
+#define FFB_PPC_TBE_MASK 0x000300
+/* Z source */
+#define FFB_PPC_ZS_VAR 0x000080
+#define FFB_PPC_ZS_CONST 0x0000c0
+#define FFB_PPC_ZS_MASK 0x0000c0
+/* Y source */
+#define FFB_PPC_YS_VAR 0x000020
+#define FFB_PPC_YS_CONST 0x000030
+#define FFB_PPC_YS_MASK 0x000030
+/* X source */
+#define FFB_PPC_XS_WID 0x000004
+#define FFB_PPC_XS_VAR 0x000008
+#define FFB_PPC_XS_CONST 0x00000c
+#define FFB_PPC_XS_MASK 0x00000c
+/* Color (BGR) source */
+#define FFB_PPC_CS_VAR 0x000002
+#define FFB_PPC_CS_CONST 0x000003
+#define FFB_PPC_CS_MASK 0x000003
+
+/* X Clip */
+#define FFB_XCLIP_XREF 0x000000ff
+#define FFB_XCLIP_TEST_MASK 0x00070000
+#define FFB_XCLIP_TEST_ALWAYS 0x00000000
+#define FFB_XCLIP_TEST_GT 0x00010000
+#define FFB_XCLIP_TEST_EQ 0x00020000
+#define FFB_XCLIP_TEST_GE 0x00030000
+#define FFB_XCLIP_TEST_NEVER 0x00040000
+#define FFB_XCLIP_TEST_LE 0x00050000
+#define FFB_XCLIP_TEST_NE 0x00060000
+#define FFB_XCLIP_TEST_LT 0x00070000
+
+/* FB Control register */
+/* Write buffer dest */
+#define FFB_FBC_WB_A 0x20000000
+#define FFB_FBC_WB_B 0x40000000
+#define FFB_FBC_WB_AB 0x60000000
+#define FFB_FBC_WB_C 0x80000000
+#define FFB_FBC_WB_AC 0xa0000000
+#define FFB_FBC_WB_BC 0xc0000000
+#define FFB_FBC_WB_ABC 0xe0000000
+#define FFB_FBC_WB_MASK 0xe0000000
+/* Write enable */
+#define FFB_FBC_WE_FORCEOFF 0x00100000
+#define FFB_FBC_WE_FORCEON 0x00200000
+#define FFB_FBC_WE_USE_WMASK 0x00300000
+#define FFB_FBC_WE_MASK 0x00300000
+/* Write group mode */
+#define FFB_FBC_WM_RSVD 0x00040000
+#define FFB_FBC_WM_COMBINED 0x00080000
+#define FFB_FBC_WM_SEPARATE 0x000c0000
+#define FFB_FBC_WM_MASK 0x000c0000
+/* Read buffer src */
+#define FFB_FBC_RB_A 0x00004000
+#define FFB_FBC_RB_B 0x00008000
+#define FFB_FBC_RB_C 0x0000c000
+#define FFB_FBC_RB_MASK 0x0000c000
+/* Stereo buf dest */
+#define FFB_FBC_SB_LEFT 0x00001000
+#define FFB_FBC_SB_RIGHT 0x00002000
+#define FFB_FBC_SB_BOTH 0x00003000
+#define FFB_FBC_SB_MASK 0x00003000
+/* Z plane group enable */
+#define FFB_FBC_ZE_OFF 0x00000400
+#define FFB_FBC_ZE_ON 0x00000800
+#define FFB_FBC_ZE_MASK 0x00000c00
+/* Y plane group enable */
+#define FFB_FBC_YE_OFF 0x00000100
+#define FFB_FBC_YE_ON 0x00000200
+#define FFB_FBC_YE_MASK 0x00000300
+/* X plane group enable */
+#define FFB_FBC_XE_OFF 0x00000040
+#define FFB_FBC_XE_ON 0x00000080
+#define FFB_FBC_XE_MASK 0x000000c0
+/* B plane group enable */
+#define FFB_FBC_BE_OFF 0x00000010
+#define FFB_FBC_BE_ON 0x00000020
+#define FFB_FBC_BE_MASK 0x00000030
+/* G plane group enable */
+#define FFB_FBC_GE_OFF 0x00000004
+#define FFB_FBC_GE_ON 0x00000008
+#define FFB_FBC_GE_MASK 0x0000000c
+/* R plane group enable */
+#define FFB_FBC_RE_OFF 0x00000001
+#define FFB_FBC_RE_ON 0x00000002
+#define FFB_FBC_RE_MASK 0x00000003
+/* Combined */
+#define FFB_FBC_RGBE_OFF 0x00000015
+#define FFB_FBC_RGBE_ON 0x0000002a
+#define FFB_FBC_RGBE_MASK 0x0000003f
+
+/* Raster OP */
+#define FFB_ROP_YZ_MASK 0x008f0000
+#define FFB_ROP_X_MASK 0x00008f00
+#define FFB_ROP_RGB_MASK 0x0000008f
+
+/* Now the rops themselves which get shifted into the
+ * above fields.
+ */
+#define FFB_ROP_EDIT_BIT 0x80
+#define FFB_ROP_ZERO 0x80
+#define FFB_ROP_NEW_AND_OLD 0x81
+#define FFB_ROP_NEW_AND_NOLD 0x82
+#define FFB_ROP_NEW 0x83
+#define FFB_ROP_NNEW_AND_OLD 0x84
+#define FFB_ROP_OLD 0x85
+#define FFB_ROP_NEW_XOR_OLD 0x86
+#define FFB_ROP_NEW_OR_OLD 0x87
+#define FFB_ROP_NNEW_AND_NOLD 0x88
+#define FFB_ROP_NNEW_XOR_NOLD 0x89
+#define FFB_ROP_NOLD 0x8a
+#define FFB_ROP_NEW_OR_NOLD 0x8b
+#define FFB_ROP_NNEW 0x8c
+#define FFB_ROP_NNEW_OR_OLD 0x8d
+#define FFB_ROP_NNEW_OR_NOLD 0x8e
+#define FFB_ROP_ONES 0x8f
+
+/* FB Compare */
+#define FFB_CMP_MATCHC_MASK 0x8f000000
+#define FFB_CMP_MAGNC_MASK 0x00870000
+#define FFB_CMP_MATCHAB_MASK 0x0000ff00
+#define FFB_CMP_MAGNAB_MASK 0x000000ff
+
+/* Compare Match codes */
+#define FFB_CMP_MATCH_EDIT_BIT 0x80
+#define FFB_CMP_MATCH_ALWAYS 0x80
+#define FFB_CMP_MATCH_NEVER 0x81
+#define FFB_CMP_MATCH_EQ 0x82
+#define FFB_CMP_MATCH_NE 0x83
+#define FFB_CMP_MATCH_A_ALWAYS 0xc0
+#define FFB_CMP_MATCH_B_ALWAYS 0xa0
+
+/* Compare Magnitude codes */
+#define FFB_CMP_MAGN_EDIT_BIT 0x80
+#define FFB_CMP_MAGN_ALWAYS 0x80
+#define FFB_CMP_MAGN_GT 0x81
+#define FFB_CMP_MAGN_EQ 0x82
+#define FFB_CMP_MAGN_GE 0x83
+#define FFB_CMP_MAGN_NEVER 0x84
+#define FFB_CMP_MAGN_LE 0x85
+#define FFB_CMP_MAGN_NE 0x86
+#define FFB_CMP_MAGN_LT 0x87
+#define FFB_CMP_MAGN_A_ALWAYS 0xc0
+#define FFB_CMP_MAGN_B_ALWAYS 0xa0
+
+/* User Control and Status */
+#define FFB_UCSR_FIFO_MASK 0x00000fff
+#define FFB_UCSR_PICK_NO_HIT 0x00020000
+#define FFB_UCSR_PICK_HIT 0x00030000
+#define FFB_UCSR_PICK_DISABLE 0x00080000
+#define FFB_UCSR_PICK_ENABLE 0x000c0000
+#define FFB_UCSR_FB_BUSY 0x01000000
+#define FFB_UCSR_RP_BUSY 0x02000000
+#define FFB_UCSR_ALL_BUSY (FFB_UCSR_RP_BUSY|FFB_UCSR_FB_BUSY)
+#define FFB_UCSR_READ_ERR 0x40000000
+#define FFB_UCSR_FIFO_OVFL 0x80000000
+#define FFB_UCSR_ALL_ERRORS (FFB_UCSR_READ_ERR|FFB_UCSR_FIFO_OVFL)
+
+/* Mode Enable Register */
+#define FFB_MER_EIRA 0x00000080 /* Enable read-ahead, increasing */
+#define FFB_MER_EDRA 0x000000c0 /* Enable read-ahead, decreasing */
+#define FFB_MER_DRA 0x00000040 /* No read-ahead */
+
+/* FBram Config 0 */
+#define FFB_FBCFG0_RFTIME 0xff800000
+#define FFB_FBCFG0_XMAX 0x007c0000
+#define FFB_FBCFG0_YMAX 0x0003ffc0
+#define FFB_FBCFG0_RES_MASK 0x00000030
+#define FFB_FBCFG0_RES_HIGH 0x00000030 /* 1920x1360 */
+#define FFB_FBCFG0_RES_STD 0x00000020 /* 1280x1024 */
+#define FFB_FBCFG0_RES_STEREO 0x00000010 /* 960x580 */
+#define FFB_FBCFG0_RES_PRTRAIT 0x00000000 /* 1280x2048 */
+#define FFB_FBCFG0_ITRLACE 0x00000000
+#define FFB_FBCFG0_SEQUENTIAL 0x00000008
+#define FFB_FBCFG0_DRENA 0x00000004
+#define FFB_FBCFG0_BPMODE 0x00000002
+#define FFB_FBCFG0_RFRSH_RST 0x00000001
+
+typedef struct _ffb_dac {
+ volatile unsigned int cfg;
+ volatile unsigned int cfgdata;
+ volatile unsigned int cur;
+ volatile unsigned int curdata;
+} ffb_dac, *ffb_dacPtr;
+
+/* Writing 2 32-bit registers at a time using 64-bit stores. -DaveM */
+#if defined(__GNUC__) && defined(USE_VIS)
+/* 64-bit register writing support.
+ * Note: "lo" means "low address".
+ */
+#define FFB_WRITE64_COMMON(__regp, __lo32, __hi32, REG0, REG1) \
+do { __extension__ register unsigned int __r0 __asm__(""#REG0); \
+ __extension__ register unsigned int __r1 __asm__(""#REG1); \
+ __r0 = (__lo32); \
+ __r1 = (__hi32); \
+ __asm__ __volatile__ ("sllx\t%0, 32, %%g1\n\t" \
+ "srl\t%1, 0, %1\n\t" \
+ "or\t%%g1, %1, %%g1\n\t" \
+ "stx\t%%g1, %2" \
+ : : "r" (__r0), "r" (__r1), "m" (*(__regp)) : "g1"); \
+} while(0)
+
+#define FFB_WRITE64P(__regp, __srcp) \
+do { __asm__ __volatile__ ("ldx\t%0, %%g2;" \
+ "stx\t%%g2, %1" \
+ : : "m" (*(__srcp)), "m" (*(__regp)) \
+ : "g2"); \
+} while(0)
+
+#define FFB_WRITE64(__regp, __lo32, __hi32) \
+ FFB_WRITE64_COMMON(__regp, __lo32, __hi32, g2, g3)
+#define FFB_WRITE64_2(__regp, __lo32, __hi32) \
+ FFB_WRITE64_COMMON(__regp, __lo32, __hi32, g4, g5)
+#define FFB_WRITE64_3(__regp, __lo32, __hi32) \
+ FFB_WRITE64_COMMON(__regp, __lo32, __hi32, o4, o5)
+
+#else /* Do not use 64-bit writes. */
+
+#define FFB_WRITE64(__regp, __lo32, __hi32) \
+do { volatile unsigned int *__p = (__regp); \
+ *__p = (__lo32); \
+ *(__p + 1) = (__hi32); \
+} while(0)
+
+#define FFB_WRITE64P(__regp, __srcp) \
+do { volatile unsigned int *__p = (__regp); \
+ unsigned int *__q = (__srcp); \
+ *__p = *__q; \
+ *(__p + 1) = *(__q + 1); \
+} while(0)
+
+#define FFB_WRITE64_2(__regp, __lo32, __hi32) \
+ FFB_WRITE64(__regp, __lo32, __hi32)
+#define FFB_WRITE64_3(__regp, __lo32, __hi32) \
+ FFB_WRITE64(__regp, __lo32, __hi32)
+#endif
+
+#endif /* FFBREGS_H */
diff --git a/src/ffb_seg.c b/src/ffb_seg.c
new file mode 100644
index 0000000..930632f
--- /dev/null
+++ b/src/ffb_seg.c
@@ -0,0 +1,196 @@
+/*
+ * Acceleration for the Creator and Creator3D framebuffer - Segment rops.
+ *
+ * Copyright (C) 1998,1999,2000 Jakub Jelinek (jakub@redhat.com)
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * JAKUB JELINEK OR DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_seg.c,v 1.2 2000/05/23 04:47:45 dawes Exp $ */
+
+#include "ffb.h"
+#include "ffb_regs.h"
+#include "ffb_rcache.h"
+#include "ffb_fifo.h"
+#include "ffb_loops.h"
+#include "ffb_stip.h"
+
+#include "pixmapstr.h"
+#include "scrnintstr.h"
+
+#define PSZ 8
+#include "cfb.h"
+#undef PSZ
+#include "cfb32.h"
+
+#include "miline.h"
+
+/* The general strategy is to do the drawing completely in hardware
+ * iff:
+ * 1) Single region rect
+ * 2) Both ends of the segment lie within it
+ */
+#define SEG_DRAWOP(__pgc) ((__pgc)->capStyle == CapNotLast ? \
+ FFB_DRAWOP_BRLINEOPEN : \
+ FFB_DRAWOP_BRLINECAP)
+static void
+ReloadSegmentAttrs(FFBPtr pFfb, CreatorPrivGCPtr gcPriv, GCPtr pGC, WindowPtr pWin)
+{
+ if(gcPriv->stipple == NULL) {
+ FFB_ATTR_GC(pFfb, pGC, pWin,
+ FFB_PPC_APE_DISABLE | FFB_PPC_CS_CONST,
+ SEG_DRAWOP(pGC));
+ } else {
+ ffb_fbcPtr ffb = pFfb->regs;
+ unsigned int fbc;
+
+ FFBSetStipple(pFfb, ffb, gcPriv->stipple,
+ FFB_PPC_CS_CONST, FFB_PPC_CS_MASK);
+ FFB_WRITE_PMASK(pFfb, ffb, pGC->planemask);
+ FFB_WRITE_DRAWOP(pFfb, ffb, SEG_DRAWOP(pGC));
+ fbc = FFB_FBC_WIN(pWin);
+ fbc = (fbc & ~FFB_FBC_XE_MASK) | FFB_FBC_XE_OFF;
+ FFB_WRITE_FBC(pFfb, ffb, fbc);
+ }
+}
+
+void
+CreatorPolySegment (DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment *pSeg)
+{
+ WindowPtr pWin = (WindowPtr) pDrawable;
+ CreatorPrivGCPtr gcPriv = CreatorGetGCPrivate (pGC);
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pGC->pScreen);
+ ffb_fbcPtr ffb = pFfb->regs;
+ BoxPtr extent;
+ int xorg, yorg, lpat;
+
+ if (nseg == 0)
+ return;
+
+ FFBLOG(("CreatorPolySegment: ALU(%x) PMSK(%08x) nseg(%d) lpat(%08x)\n",
+ pGC->alu, pGC->planemask, nseg, gcPriv->linepat));
+
+ if (gcPriv->stipple == NULL) {
+ FFB_ATTR_GC(pFfb, pGC, pWin,
+ FFB_PPC_APE_DISABLE | FFB_PPC_CS_CONST,
+ SEG_DRAWOP(pGC));
+ } else {
+ unsigned int fbc;
+
+ FFBSetStipple(pFfb, ffb, gcPriv->stipple,
+ FFB_PPC_CS_CONST, FFB_PPC_CS_MASK);
+ FFB_WRITE_PMASK(pFfb, ffb, pGC->planemask);
+ FFB_WRITE_DRAWOP(pFfb, ffb, SEG_DRAWOP(pGC));
+ fbc = FFB_FBC_WIN(pWin);
+ fbc = (fbc & ~FFB_FBC_XE_MASK) | FFB_FBC_XE_OFF;
+ FFB_WRITE_FBC(pFfb, ffb, fbc);
+ }
+
+ pFfb->rp_active = 1;
+ xorg = pDrawable->x;
+ yorg = pDrawable->y;
+ extent = REGION_RECTS(cfbGetCompositeClip(pGC));
+ lpat = gcPriv->linepat;
+
+ if (lpat == 0) {
+ FFBFifo(pFfb, 1);
+ ffb->lpat = 0;
+ if (pFfb->has_brline_bug) {
+ while (nseg--) {
+ register int x1 = pSeg->x1 + xorg;
+ register int y1 = pSeg->y1 + yorg;
+ register int x2 = pSeg->x2 + xorg;
+ register int y2 = pSeg->y2 + yorg;
+
+ if (x1 >= extent->x1 &&
+ x2 >= extent->x1 &&
+ x1 < extent->x2 &&
+ x2 < extent->x2 &&
+ y1 >= extent->y1 &&
+ y2 >= extent->y1 &&
+ y1 < extent->y2 &&
+ y2 < extent->y2) {
+ FFBFifo(pFfb, 5);
+ ffb->ppc = 0;
+ FFB_WRITE64(&ffb->by, y1, x1);
+ FFB_WRITE64_2(&ffb->bh, y2, x2);
+ } else {
+ gcPriv->PolySegment(pDrawable, pGC, 1, pSeg);
+ ReloadSegmentAttrs(pFfb, gcPriv, pGC, pWin);
+ pFfb->rp_active = 1;
+ }
+ pSeg++;
+ }
+ } else {
+ while (nseg--) {
+ register int x1 = pSeg->x1 + xorg;
+ register int y1 = pSeg->y1 + yorg;
+ register int x2 = pSeg->x2 + xorg;
+ register int y2 = pSeg->y2 + yorg;
+
+ if (x1 >= extent->x1 &&
+ x2 >= extent->x1 &&
+ x1 < extent->x2 &&
+ x2 < extent->x2 &&
+ y1 >= extent->y1 &&
+ y2 >= extent->y1 &&
+ y1 < extent->y2 &&
+ y2 < extent->y2) {
+ FFBFifo(pFfb, 4);
+ FFB_WRITE64(&ffb->by, y1, x1);
+ FFB_WRITE64_2(&ffb->bh, y2, x2);
+ } else {
+ gcPriv->PolySegment(pDrawable, pGC, 1, pSeg);
+ ReloadSegmentAttrs(pFfb, gcPriv, pGC, pWin);
+ pFfb->rp_active = 1;
+ }
+ pSeg++;
+ }
+ }
+ } else {
+ /* No reason to optimize the non-brline bug case since
+ * we have to write the line pattern register each loop
+ * anyways.
+ */
+ while (nseg--) {
+ register int x1 = pSeg->x1 + xorg;
+ register int y1 = pSeg->y1 + yorg;
+ register int x2 = pSeg->x2 + xorg;
+ register int y2 = pSeg->y2 + yorg;
+
+ if (x1 >= extent->x1 && x2 >= extent->x1 &&
+ x1 < extent->x2 && x2 < extent->x2 &&
+ y1 >= extent->y1 && y2 >= extent->y1 &&
+ y1 < extent->y2 && y2 < extent->y2) {
+ FFBFifo(pFfb, 5);
+ ffb->lpat = lpat;
+ FFB_WRITE64(&ffb->by, y1, x1);
+ FFB_WRITE64_2(&ffb->bh, y2, x2);
+ } else {
+ gcPriv->PolySegment(pDrawable, pGC, 1, pSeg);
+ ReloadSegmentAttrs(pFfb, gcPriv, pGC, pWin);
+ pFfb->rp_active = 1;
+ }
+ pSeg++;
+ }
+ }
+
+ FFBSync(pFfb, ffb);
+}
diff --git a/src/ffb_sspans.c b/src/ffb_sspans.c
new file mode 100644
index 0000000..3d4b2ae
--- /dev/null
+++ b/src/ffb_sspans.c
@@ -0,0 +1,166 @@
+/*
+ * Acceleration for the Creator and Creator3D framebuffer - Set spans.
+ *
+ * Copyright (C) 1998,1999 Jakub Jelinek (jakub@redhat.com)
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * JAKUB JELINEK OR DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_sspans.c,v 1.2 2000/05/23 04:47:45 dawes Exp $ */
+
+#include "ffb.h"
+#include "ffb_regs.h"
+#include "ffb_rcache.h"
+#include "ffb_fifo.h"
+
+#include "pixmapstr.h"
+#include "scrnintstr.h"
+
+#define PSZ 8
+#include "cfb.h"
+#undef PSZ
+#include "cfb32.h"
+
+/* PPC does all of the planemask and ROP'ing on the written pixels,
+ * and we know various other things are constant, so this is easy.
+ */
+static void
+CreatorSetScanline(int y, int xOrigin, int xStart, int xEnd,
+ unsigned int *_psrc, char *sfb, int depth)
+{
+ if (depth == 8) {
+ unsigned char *psrc = (unsigned char *)_psrc;
+ unsigned char *pdst = (unsigned char *)(sfb +
+ (y << 11) +
+ (xStart << 0));
+ int w = xEnd - xStart;
+
+ psrc += (xStart - xOrigin);
+ while(w--)
+ *pdst++ = *psrc++;
+ } else {
+ unsigned int *psrc = (unsigned int *)_psrc;
+ unsigned int *pdst = (unsigned int *)(sfb +
+ (y << 13) +
+ (xStart << 2));
+ int w = xEnd - xStart;
+
+ psrc += (xStart - xOrigin);
+ while(w--)
+ *pdst++ = *psrc++;
+ }
+}
+
+void
+CreatorSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *pcharsrc,
+ DDXPointPtr ppt, int *pwidth, int nspans, int fSorted)
+{
+ WindowPtr pWin = (WindowPtr) pDrawable;
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pDrawable->pScreen);
+ ffb_fbcPtr ffb = pFfb->regs;
+ unsigned int *psrc = (unsigned int *)pcharsrc;
+ BoxPtr pbox, pboxLast, pboxTest;
+ DDXPointPtr pptLast;
+ RegionPtr prgnDst;
+ char *addrp;
+ int xStart, xEnd, yMax;
+
+ if(pDrawable->type != DRAWABLE_WINDOW) {
+ if (pDrawable->bitsPerPixel == 8)
+ cfbSetSpans(pDrawable, pGC, pcharsrc, ppt,
+ pwidth, nspans, fSorted);
+ else
+ cfb32SetSpans(pDrawable, pGC, pcharsrc, ppt,
+ pwidth, nspans, fSorted);
+ return;
+ }
+ FFBLOG(("CreatorSetSpans: ALU(%x) PMSK(%08x) nspans(%d) fsorted(%d)\n",
+ pGC->alu, pGC->planemask, nspans, fSorted));
+ if (pGC->alu == GXnoop)
+ return;
+
+ /* Get SFB ready. */
+ FFB_ATTR_SFB_VAR_WIN(pFfb, pGC->planemask, pGC->alu, pWin);
+ FFBWait(pFfb, ffb);
+
+ if (pGC->depth == 8)
+ addrp = (char *) pFfb->sfb8r;
+ else
+ addrp = (char *) pFfb->sfb32;
+
+ yMax = (int) pDrawable->y + (int) pDrawable->height;
+ prgnDst = cfbGetCompositeClip(pGC);
+ pbox = REGION_RECTS(prgnDst);
+ pboxLast = pbox + REGION_NUM_RECTS(prgnDst);
+ pptLast = ppt + nspans;
+ if(fSorted) {
+ pboxTest = pbox;
+ while(ppt < pptLast) {
+ pbox = pboxTest;
+ if(ppt->y >= yMax)
+ break;
+ while(pbox < pboxLast) {
+ if(pbox->y1 > ppt->y) {
+ break;
+ } else if(pbox->y2 <= ppt->y) {
+ pboxTest = ++pbox;
+ continue;
+ } else if(pbox->x1 > ppt->x + *pwidth) {
+ break;
+ } else if(pbox->x2 <= ppt->x) {
+ pbox++;
+ continue;
+ }
+ xStart = max(pbox->x1, ppt->x);
+ xEnd = min(ppt->x + *pwidth, pbox->x2);
+ CreatorSetScanline(ppt->y, ppt->x, xStart, xEnd,
+ psrc, addrp, pGC->depth);
+ if(ppt->x + *pwidth <= pbox->x2)
+ break;
+ else
+ pbox++;
+ }
+ ppt++;
+ psrc += *pwidth++;
+ }
+ } else {
+ while(ppt < pptLast) {
+ if(ppt->y >= 0 && ppt->y < yMax) {
+ for(pbox = REGION_RECTS(prgnDst); pbox < pboxLast; pbox++) {
+ if(pbox->y1 > ppt->y) {
+ break;
+ } else if(pbox->y2 <= ppt->y) {
+ pbox++;
+ break;
+ }
+ if(pbox->x1 <= ppt->x + *pwidth &&
+ pbox->x2 > ppt->x) {
+ xStart = max(pbox->x1, ppt->x);
+ xEnd = min(pbox->x2, ppt->x + *pwidth);
+ CreatorSetScanline(ppt->y, ppt->x,
+ xStart, xEnd,
+ psrc, addrp, pGC->depth);
+ }
+ }
+ }
+ ppt++;
+ psrc += *pwidth++;
+ }
+ }
+}
diff --git a/src/ffb_stip.c b/src/ffb_stip.c
new file mode 100644
index 0000000..d79b232
--- /dev/null
+++ b/src/ffb_stip.c
@@ -0,0 +1,64 @@
+/*
+ * Acceleration for the Creator and Creator3D framebuffer - stipple setting.
+ *
+ * Copyright (C) 1998,1999 Jakub Jelinek (jakub@redhat.com)
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * JAKUB JELINEK OR DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_stip.c,v 1.2 2000/05/23 04:47:45 dawes Exp $ */
+
+#include "ffb.h"
+#include "ffb_regs.h"
+#include "ffb_rcache.h"
+#include "ffb_fifo.h"
+#include "ffb_stip.h"
+#include "ffb_loops.h"
+
+void
+FFBSetStipple(FFBPtr pFfb, ffb_fbcPtr ffb,
+ CreatorStipplePtr stipple,
+ unsigned int ppc, unsigned int ppc_mask)
+{
+ int transparent = ((stipple->alu & FFB_ROP_EDIT_BIT) != 0);
+
+ if(transparent)
+ ppc |= FFB_PPC_APE_ENABLE|FFB_PPC_TBE_TRANSPARENT;
+ else
+ ppc |= FFB_PPC_APE_ENABLE|FFB_PPC_TBE_OPAQUE;
+ ppc_mask |= FFB_PPC_APE_MASK|FFB_PPC_TBE_MASK;
+ FFB_WRITE_PPC(pFfb, ffb, ppc, ppc_mask);
+ FFB_WRITE_ROP(pFfb, ffb,
+ (FFB_ROP_EDIT_BIT|stipple->alu)| (FFB_ROP_NEW<<8));
+
+ if (stipple->inhw && pFfb->laststipple == stipple) {
+ FFB_WRITE_FG(pFfb, ffb, stipple->fg);
+ if(!transparent)
+ FFB_WRITE_BG(pFfb, ffb, stipple->bg);
+ return;
+ }
+ FFBFifo(pFfb, 32);
+ FFB_STIPPLE_LOAD(&ffb->pattern[0], &stipple->bits[0]);
+ FFB_WRITE_FG(pFfb, ffb, stipple->fg);
+ if(!transparent)
+ FFB_WRITE_BG(pFfb, ffb, stipple->bg);
+ stipple->inhw = 1;
+ pFfb->laststipple = stipple;
+}
diff --git a/src/ffb_stip.h b/src/ffb_stip.h
new file mode 100644
index 0000000..3d490d0
--- /dev/null
+++ b/src/ffb_stip.h
@@ -0,0 +1,36 @@
+/*
+ * Acceleration for the Creator and Creator3D framebuffer - stipple defines.
+ *
+ * Copyright (C) 1998,1999 Jakub Jelinek (jakub@redhat.com)
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * JAKUB JELINEK OR DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_stip.h,v 1.1 2000/05/18 23:21:38 dawes Exp $ */
+
+#ifndef FFBSTIP_H
+#define FFBSTIP_H
+
+extern void FFBSetStipple(FFBPtr pFfb,
+ ffb_fbcPtr ffb,
+ CreatorStipplePtr stipple,
+ unsigned int ppc, unsigned int ppc_mask);
+
+#endif /* FFBSTIP_H */
diff --git a/src/ffb_stubs.c b/src/ffb_stubs.c
new file mode 100644
index 0000000..aa01018
--- /dev/null
+++ b/src/ffb_stubs.c
@@ -0,0 +1,544 @@
+/*
+ * Acceleration for the Creator and Creator3D framebuffer - Unaccelerated stuff.
+ *
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_stubs.c,v 1.2 2000/05/23 04:47:45 dawes Exp $ */
+
+#include "ffb.h"
+#include "ffb_regs.h"
+#include "ffb_rcache.h"
+#include "ffb_fifo.h"
+
+#include "pixmapstr.h"
+#include "scrnintstr.h"
+
+#define PSZ 8
+#include "cfb.h"
+#undef PSZ
+#include "cfb32.h"
+
+/* CFB is just too clever for it's own good. There are paths
+ * in cfb for 8bpp that just arbitrarily change the ROP of the
+ * GC and assume it just works even without revalidating that
+ * GC. So for now we turn this stuff off. -DaveM
+ */
+#undef USE_SFB_TRICKS
+
+#ifdef USE_SFB_TRICKS
+/* Sorry, have to expose some CFB internals to get the stubs right. -DaveM */
+struct cfb_gcstate {
+ unsigned long pmask;
+ int alu, rop, and, xor;
+};
+
+#define CFB_STATE_SAVE(__statep, __gcp, __privp) \
+do { (__statep)->pmask = (__gcp)->planemask; \
+ (__statep)->alu = (__gcp)->alu; \
+ (__statep)->rop = (__privp)->rop; \
+ (__statep)->and = (__privp)->and; \
+ (__statep)->xor = (__privp)->xor; \
+} while(0)
+
+#define CFB_STATE_RESTORE(__statep, __gcp, __privp) \
+do { (__gcp)->planemask = (__statep)->pmask; \
+ (__gcp)->alu = (__statep)->alu; \
+ (__privp)->rop = (__statep)->rop; \
+ (__privp)->and = (__statep)->and; \
+ (__privp)->xor = (__statep)->xor; \
+} while(0)
+
+#define CFB_STATE_SET_SFB(__gcp, __privp) \
+do { (__gcp)->alu = GXcopy; \
+ (__gcp)->planemask = (((__gcp)->depth==8)?0xff:0xffffff); \
+ (__privp)->rop = GXcopy; \
+ (__privp)->and = 0; \
+ (__privp)->xor = (__gcp)->fgPixel; \
+} while(0)
+#endif
+
+/* Stubs so we can wait for the raster processor to
+ * unbusy itself before we let the cfb code write
+ * directly to the framebuffer.
+ */
+void
+CreatorSolidSpansGeneralStub (DrawablePtr pDrawable, GCPtr pGC,
+ int nInit, DDXPointPtr pptInit,
+ int *pwidthInit, int fSorted)
+{
+ WindowPtr pWin = (WindowPtr) pDrawable;
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pDrawable->pScreen);
+ ffb_fbcPtr ffb = pFfb->regs;
+
+ FFBLOG(("STUB(%s:%d)\n", __FILE__, __LINE__));
+ FFB_ATTR_SFB_VAR_WIN(pFfb, 0xffffffff, GXcopy, pWin);
+ FFBWait(pFfb, ffb);
+ if (pGC->depth == 8)
+ cfbSolidSpansGeneral(pDrawable, pGC, nInit, pptInit,
+ pwidthInit, fSorted);
+ else
+ cfb32SolidSpansGeneral(pDrawable, pGC, nInit, pptInit,
+ pwidthInit, fSorted);
+}
+
+void
+CreatorSegmentSSStub (DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment *pSeg)
+{
+ WindowPtr pWin = (WindowPtr) pDrawable;
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pDrawable->pScreen);
+ ffb_fbcPtr ffb = pFfb->regs;
+ cfbPrivGCPtr devPriv = cfbGetGCPrivate(pGC);
+#ifdef USE_SFB_TRICKS
+ struct cfb_gcstate cfb_state;
+#endif
+
+ FFBLOG(("STUB(%s:%d)\n", __FILE__, __LINE__));
+#ifndef USE_SFB_TRICKS
+ FFB_ATTR_SFB_VAR_WIN(pFfb, 0xffffffff, GXcopy, pWin);
+ FFBWait(pFfb, ffb);
+ if (pGC->depth == 8) {
+ if (devPriv->oneRect &&
+ ((pDrawable->x >= pGC->pScreen->width - 32768) &&
+ (pDrawable->y >= pGC->pScreen->height - 32768)))
+ cfb8SegmentSS1Rect(pDrawable, pGC, nseg, pSeg);
+ else
+ cfbSegmentSS(pDrawable, pGC, nseg, pSeg);
+ } else
+ cfb32SegmentSS(pDrawable, pGC, nseg, pSeg);
+#else
+ CFB_STATE_SAVE(&cfb_state, pGC, devPriv);
+ FFB_ATTR_SFB_VAR_WIN(pFfb, cfb_state.pmask, cfb_state.alu, pWin);
+ FFBWait(pFfb, ffb);
+ CFB_STATE_SET_SFB(pGC, devPriv);
+ if (pGC->depth == 8) {
+ if (devPriv->oneRect &&
+ ((pDrawable->x >= pGC->pScreen->width - 32768) &&
+ (pDrawable->y >= pGC->pScreen->height - 32768)))
+ cfb8SegmentSS1Rect(pDrawable, pGC, nseg, pSeg);
+ else
+ cfbSegmentSS(pDrawable, pGC, nseg, pSeg);
+ } else
+ cfb32SegmentSS(pDrawable, pGC, nseg, pSeg);
+ CFB_STATE_RESTORE(&cfb_state, pGC, devPriv);
+#endif
+}
+
+void
+CreatorLineSSStub (DrawablePtr pDrawable, GCPtr pGC,
+ int mode, int npt, DDXPointPtr ppt)
+{
+ WindowPtr pWin = (WindowPtr) pDrawable;
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pDrawable->pScreen);
+ ffb_fbcPtr ffb = pFfb->regs;
+ cfbPrivGCPtr devPriv = cfbGetGCPrivate(pGC);
+#ifdef USE_SFB_TRICKS
+ struct cfb_gcstate cfb_state;
+#endif
+
+ FFBLOG(("STUB(%s:%d)\n", __FILE__, __LINE__));
+#ifndef USE_SFB_TRICKS
+ FFB_ATTR_SFB_VAR_WIN(pFfb, 0xffffffff, GXcopy, pWin);
+ FFBWait(pFfb, ffb);
+ if (pGC->depth == 8) {
+ if (devPriv->oneRect &&
+ ((pDrawable->x >= pGC->pScreen->width - 32768) &&
+ (pDrawable->y >= pGC->pScreen->height - 32768)))
+ cfb8LineSS1Rect(pDrawable, pGC, mode, npt, ppt);
+ else
+ cfbLineSS(pDrawable, pGC, mode, npt, ppt);
+ } else
+ cfb32LineSS(pDrawable, pGC, mode, npt, ppt);
+#else
+ CFB_STATE_SAVE(&cfb_state, pGC, devPriv);
+ FFB_ATTR_SFB_VAR_WIN(pFfb, cfb_state.pmask, cfb_state.alu, pWin);
+ FFBWait(pFfb, ffb);
+ CFB_STATE_SET_SFB(pGC, devPriv);
+ if (pGC->depth == 8) {
+ if (devPriv->oneRect &&
+ ((pDrawable->x >= pGC->pScreen->width - 32768) &&
+ (pDrawable->y >= pGC->pScreen->height - 32768)))
+ cfb8LineSS1Rect(pDrawable, pGC, mode, npt, ppt);
+ else
+ cfbLineSS(pDrawable, pGC, mode, npt, ppt);
+ } else
+ cfb32LineSS(pDrawable, pGC, mode, npt, ppt);
+ CFB_STATE_RESTORE(&cfb_state, pGC, devPriv);
+#endif
+}
+
+void
+CreatorSegmentSDStub (DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment *pSeg)
+{
+ WindowPtr pWin = (WindowPtr) pDrawable;
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pDrawable->pScreen);
+ ffb_fbcPtr ffb = pFfb->regs;
+#ifdef USE_SFB_TRICKS
+ struct cfb_gcstate cfb_state;
+ cfbPrivGCPtr devPriv = cfbGetGCPrivate(pGC);
+#endif
+
+ FFBLOG(("STUB(%s:%d)\n", __FILE__, __LINE__));
+#ifndef USE_SFB_TRICKS
+ FFB_ATTR_SFB_VAR_WIN(pFfb, 0xffffffff, GXcopy, pWin);
+ FFBWait(pFfb, ffb);
+ if (pGC->depth == 8)
+ cfbSegmentSD(pDrawable, pGC, nseg, pSeg);
+ else
+ cfb32SegmentSD(pDrawable, pGC, nseg, pSeg);
+#else
+ CFB_STATE_SAVE(&cfb_state, pGC, devPriv);
+ FFB_ATTR_SFB_VAR_WIN(pFfb, cfb_state.pmask, cfb_state.alu, pWin);
+ FFBWait(pFfb, ffb);
+ CFB_STATE_SET_SFB(pGC, devPriv);
+ if (pGC->depth == 8)
+ cfbSegmentSD(pDrawable, pGC, nseg, pSeg);
+ else
+ cfb32SegmentSD(pDrawable, pGC, nseg, pSeg);
+ CFB_STATE_RESTORE(&cfb_state, pGC, devPriv);
+#endif
+}
+
+void
+CreatorLineSDStub (DrawablePtr pDrawable, GCPtr pGC,
+ int mode, int npt, DDXPointPtr ppt)
+{
+ WindowPtr pWin = (WindowPtr) pDrawable;
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pDrawable->pScreen);
+ ffb_fbcPtr ffb = pFfb->regs;
+#ifdef USE_SFB_TRICKS
+ struct cfb_gcstate cfb_state;
+ cfbPrivGCPtr devPriv = cfbGetGCPrivate(pGC);
+#endif
+
+ FFBLOG(("STUB(%s:%d)\n", __FILE__, __LINE__));
+#ifndef USE_SFB_TRICKS
+ FFB_ATTR_SFB_VAR_WIN(pFfb, 0xffffffff, GXcopy, pWin);
+ FFBWait(pFfb, ffb);
+ if (pGC->depth == 8)
+ cfbLineSD(pDrawable, pGC, mode, npt, ppt);
+ else
+ cfb32LineSD(pDrawable, pGC, mode, npt, ppt);
+#else
+ CFB_STATE_SAVE(&cfb_state, pGC, devPriv);
+ FFB_ATTR_SFB_VAR_WIN(pFfb, cfb_state.pmask, cfb_state.alu, pWin);
+ FFBWait(pFfb, ffb);
+ CFB_STATE_SET_SFB(pGC, devPriv);
+ if (pGC->depth == 8)
+ cfbLineSD(pDrawable, pGC, mode, npt, ppt);
+ else
+ cfb32LineSD(pDrawable, pGC, mode, npt, ppt);
+ CFB_STATE_RESTORE(&cfb_state, pGC, devPriv);
+#endif
+}
+
+void
+CreatorPolyGlyphBlt8Stub (DrawablePtr pDrawable, GCPtr pGC,
+ int x, int y, unsigned int nglyph, CharInfoPtr *ppci,
+ pointer pglyphBase)
+{
+ WindowPtr pWin = (WindowPtr) pDrawable;
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pDrawable->pScreen);
+ ffb_fbcPtr ffb = pFfb->regs;
+#ifdef USE_SFB_TRICKS
+ struct cfb_gcstate cfb_state;
+ cfbPrivGCPtr devPriv = cfbGetGCPrivate(pGC);
+#endif
+
+ FFBLOG(("STUB(%s:%d)\n", __FILE__, __LINE__));
+#ifndef USE_SFB_TRICKS
+ FFB_ATTR_SFB_VAR_WIN(pFfb, 0xffffffff, GXcopy, pWin);
+ FFBWait(pFfb, ffb);
+ if (pGC->depth == 8)
+ cfbPolyGlyphBlt8(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
+ else
+ cfb32PolyGlyphBlt8(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
+#else
+ CFB_STATE_SAVE(&cfb_state, pGC, devPriv);
+ FFB_ATTR_SFB_VAR_WIN(pFfb, cfb_state.pmask, cfb_state.alu, pWin);
+ FFBWait(pFfb, ffb);
+ CFB_STATE_SET_SFB(pGC, devPriv);
+ if (pGC->depth == 8)
+ cfbPolyGlyphBlt8(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
+ else
+ cfb32PolyGlyphBlt8(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
+ CFB_STATE_RESTORE(&cfb_state, pGC, devPriv);
+#endif
+}
+
+void
+CreatorImageGlyphBlt8Stub (DrawablePtr pDrawable, GCPtr pGC,
+ int x, int y, unsigned int nglyph,
+ CharInfoPtr *ppci, pointer pglyphBase)
+{
+ WindowPtr pWin = (WindowPtr) pDrawable;
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pDrawable->pScreen);
+ ffb_fbcPtr ffb = pFfb->regs;
+#ifdef USE_SFB_TRICKS
+ struct cfb_gcstate cfb_state;
+ cfbPrivGCPtr devPriv = cfbGetGCPrivate(pGC);
+#endif
+
+ FFBLOG(("STUB(%s:%d)\n", __FILE__, __LINE__));
+#ifndef USE_SFB_TRICKS
+ FFB_ATTR_SFB_VAR_WIN(pFfb, 0xffffffff, GXcopy, pWin);
+ FFBWait(pFfb, ffb);
+ if (pGC->depth == 8)
+ cfbImageGlyphBlt8(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
+ else
+ cfb32ImageGlyphBlt8(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
+#else
+ CFB_STATE_SAVE(&cfb_state, pGC, devPriv);
+ FFB_ATTR_SFB_VAR_WIN(pFfb, cfb_state.pmask, cfb_state.alu, pWin);
+ FFBWait(pFfb, ffb);
+ CFB_STATE_SET_SFB(pGC, devPriv);
+ if (pGC->depth == 8)
+ cfbImageGlyphBlt8(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
+ else
+ cfb32ImageGlyphBlt8(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
+ CFB_STATE_RESTORE(&cfb_state, pGC, devPriv);
+#endif
+}
+
+void
+CreatorTile32FSCopyStub(DrawablePtr pDrawable, GCPtr pGC,
+ int nInit, DDXPointPtr pptInit,
+ int *pwidthInit, int fSorted)
+{
+ WindowPtr pWin = (WindowPtr) pDrawable;
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pDrawable->pScreen);
+ ffb_fbcPtr ffb = pFfb->regs;
+#ifdef USE_SFB_TRICKS
+ struct cfb_gcstate cfb_state;
+ cfbPrivGCPtr devPriv = cfbGetGCPrivate(pGC);
+#endif
+
+ FFBLOG(("STUB(%s:%d)\n", __FILE__, __LINE__));
+#ifndef USE_SFB_TRICKS
+ FFB_ATTR_SFB_VAR_WIN(pFfb, 0xffffffff, GXcopy, pWin);
+ FFBWait(pFfb, ffb);
+ if (pGC->depth == 8)
+ cfbTile32FSCopy(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted);
+ else
+ cfb32Tile32FSCopy(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted);
+#else
+ CFB_STATE_SAVE(&cfb_state, pGC, devPriv);
+ FFB_ATTR_SFB_VAR_WIN(pFfb, cfb_state.pmask, cfb_state.alu, pWin);
+ FFBWait(pFfb, ffb);
+ CFB_STATE_SET_SFB(pGC, devPriv);
+ if (pGC->depth == 8)
+ cfbTile32FSCopy(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted);
+ else
+ cfb32Tile32FSCopy(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted);
+ CFB_STATE_RESTORE(&cfb_state, pGC, devPriv);
+#endif
+}
+
+void
+CreatorTile32FSGeneralStub(DrawablePtr pDrawable, GCPtr pGC,
+ int nInit, DDXPointPtr pptInit,
+ int *pwidthInit, int fSorted)
+{
+ WindowPtr pWin = (WindowPtr) pDrawable;
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pDrawable->pScreen);
+ ffb_fbcPtr ffb = pFfb->regs;
+#ifdef USE_SFB_TRICKS
+ struct cfb_gcstate cfb_state;
+ cfbPrivGCPtr devPriv = cfbGetGCPrivate(pGC);
+#endif
+
+ FFBLOG(("STUB(%s:%d)\n", __FILE__, __LINE__));
+#ifndef USE_SFB_TRICKS
+ FFB_ATTR_SFB_VAR_WIN(pFfb, 0xffffffff, GXcopy, pWin);
+ FFBWait(pFfb, ffb);
+ if (pGC->depth == 8)
+ cfbTile32FSGeneral(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted);
+ else
+ cfb32Tile32FSGeneral(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted);
+#else
+ CFB_STATE_SAVE(&cfb_state, pGC, devPriv);
+ FFB_ATTR_SFB_VAR_WIN(pFfb, cfb_state.pmask, cfb_state.alu, pWin);
+ FFBWait(pFfb, ffb);
+ CFB_STATE_SET_SFB(pGC, devPriv);
+ if (pGC->depth == 8)
+ cfbTile32FSGeneral(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted);
+ else
+ cfb32Tile32FSGeneral(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted);
+ CFB_STATE_RESTORE(&cfb_state, pGC, devPriv);
+#endif
+}
+
+void
+CreatorUnnaturalTileFSStub(DrawablePtr pDrawable, GCPtr pGC,
+ int nInit, DDXPointPtr pptInit,
+ int *pwidthInit, int fSorted)
+{
+ WindowPtr pWin = (WindowPtr) pDrawable;
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pDrawable->pScreen);
+ ffb_fbcPtr ffb = pFfb->regs;
+#ifdef USE_SFB_TRICKS
+ struct cfb_gcstate cfb_state;
+ cfbPrivGCPtr devPriv = cfbGetGCPrivate(pGC);
+#endif
+
+ FFBLOG(("STUB(%s:%d)\n", __FILE__, __LINE__));
+#ifndef USE_SFB_TRICKS
+ FFB_ATTR_SFB_VAR_WIN(pFfb, 0xffffffff, GXcopy, pWin);
+ FFBWait(pFfb, ffb);
+ if (pGC->depth == 8)
+ cfbUnnaturalTileFS(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted);
+ else
+ cfb32UnnaturalTileFS(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted);
+#else
+ CFB_STATE_SAVE(&cfb_state, pGC, devPriv);
+ FFB_ATTR_SFB_VAR_WIN(pFfb, cfb_state.pmask, cfb_state.alu, pWin);
+ FFBWait(pFfb, ffb);
+ CFB_STATE_SET_SFB(pGC, devPriv);
+ if (pGC->depth == 8)
+ cfbUnnaturalTileFS(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted);
+ else
+ cfb32UnnaturalTileFS(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted);
+ CFB_STATE_RESTORE(&cfb_state, pGC, devPriv);
+#endif
+}
+
+void
+Creator8Stipple32FSStub(DrawablePtr pDrawable, GCPtr pGC,
+ int nInit, DDXPointPtr pptInit,
+ int *pwidthInit, int fSorted)
+{
+ WindowPtr pWin = (WindowPtr) pDrawable;
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pDrawable->pScreen);
+ ffb_fbcPtr ffb = pFfb->regs;
+#ifdef USE_SFB_TRICKS
+ struct cfb_gcstate cfb_state;
+ cfbPrivGCPtr devPriv = cfbGetGCPrivate(pGC);
+#endif
+
+ FFBLOG(("STUB(%s:%d)\n", __FILE__, __LINE__));
+#ifndef USE_SFB_TRICKS
+ FFB_ATTR_SFB_VAR_WIN(pFfb, 0xffffffff, GXcopy, pWin);
+ FFBWait(pFfb, ffb);
+ cfb8Stipple32FS(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted);
+#else
+ CFB_STATE_SAVE(&cfb_state, pGC, devPriv);
+ FFB_ATTR_SFB_VAR_WIN(pFfb, cfb_state.pmask, cfb_state.alu, pWin);
+ FFBWait(pFfb, ffb);
+ CFB_STATE_SET_SFB(pGC, devPriv);
+ cfb8Stipple32FS(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted);
+ CFB_STATE_RESTORE(&cfb_state, pGC, devPriv);
+#endif
+}
+
+void
+CreatorUnnaturalStippleFSStub(DrawablePtr pDrawable, GCPtr pGC,
+ int nInit, DDXPointPtr pptInit,
+ int *pwidthInit, int fSorted)
+{
+ WindowPtr pWin = (WindowPtr) pDrawable;
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pDrawable->pScreen);
+ ffb_fbcPtr ffb = pFfb->regs;
+#ifdef USE_SFB_TRICKS
+ struct cfb_gcstate cfb_state;
+ cfbPrivGCPtr devPriv = cfbGetGCPrivate(pGC);
+#endif
+
+ FFBLOG(("STUB(%s:%d)\n", __FILE__, __LINE__));
+#ifndef USE_SFB_TRICKS
+ FFB_ATTR_SFB_VAR_WIN(pFfb, 0xffffffff, GXcopy, pWin);
+ FFBWait(pFfb, ffb);
+ if (pGC->depth == 8)
+ cfbUnnaturalStippleFS(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted);
+ else
+ cfb32UnnaturalStippleFS(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted);
+#else
+ CFB_STATE_SAVE(&cfb_state, pGC, devPriv);
+ FFB_ATTR_SFB_VAR_WIN(pFfb, cfb_state.pmask, cfb_state.alu, pWin);
+ FFBWait(pFfb, ffb);
+ CFB_STATE_SET_SFB(pGC, devPriv);
+ if (pGC->depth == 8)
+ cfbUnnaturalStippleFS(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted);
+ else
+ cfb32UnnaturalStippleFS(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted);
+ CFB_STATE_RESTORE(&cfb_state, pGC, devPriv);
+#endif
+}
+
+void
+Creator8OpaqueStipple32FSStub(DrawablePtr pDrawable, GCPtr pGC,
+ int nInit, DDXPointPtr pptInit,
+ int *pwidthInit, int fSorted)
+{
+ WindowPtr pWin = (WindowPtr) pDrawable;
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pDrawable->pScreen);
+ ffb_fbcPtr ffb = pFfb->regs;
+#ifdef USE_SFB_TRICKS
+ struct cfb_gcstate cfb_state;
+ cfbPrivGCPtr devPriv = cfbGetGCPrivate(pGC);
+#endif
+
+ FFBLOG(("STUB(%s:%d)\n", __FILE__, __LINE__));
+#ifndef USE_SFB_TRICKS
+ FFB_ATTR_SFB_VAR_WIN(pFfb, 0xffffffff, GXcopy, pWin);
+ FFBWait(pFfb, ffb);
+ cfb8OpaqueStipple32FS(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted);
+#else
+ CFB_STATE_SAVE(&cfb_state, pGC, devPriv);
+ FFB_ATTR_SFB_VAR_WIN(pFfb, cfb_state.pmask, cfb_state.alu, pWin);
+ FFBWait(pFfb, ffb);
+ CFB_STATE_SET_SFB(pGC, devPriv);
+ cfb8OpaqueStipple32FS(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted);
+ CFB_STATE_RESTORE(&cfb_state, pGC, devPriv);
+#endif
+}
+
+void
+CreatorPolyFillRectStub(DrawablePtr pDrawable, GCPtr pGC,
+ int nrectFill, xRectangle *prectInit)
+{
+ WindowPtr pWin = (WindowPtr) pDrawable;
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pDrawable->pScreen);
+ ffb_fbcPtr ffb = pFfb->regs;
+#ifdef USE_SFB_TRICKS
+ struct cfb_gcstate cfb_state;
+ cfbPrivGCPtr devPriv = cfbGetGCPrivate(pGC);
+#endif
+
+ FFBLOG(("STUB(%s:%d)\n", __FILE__, __LINE__));
+#ifndef USE_SFB_TRICKS
+ FFB_ATTR_SFB_VAR_WIN(pFfb, 0xffffffff, GXcopy, pWin);
+ FFBWait(pFfb, ffb);
+ if (pGC->depth == 8)
+ cfbPolyFillRect(pDrawable, pGC, nrectFill, prectInit);
+ else
+ cfb32PolyFillRect(pDrawable, pGC, nrectFill, prectInit);
+#else
+ CFB_STATE_SAVE(&cfb_state, pGC, devPriv);
+ FFB_ATTR_SFB_VAR_WIN(pFfb, cfb_state.pmask, cfb_state.alu, pWin);
+ FFBWait(pFfb, ffb);
+ CFB_STATE_SET_SFB(pGC, devPriv);
+ if (pGC->depth == 8)
+ cfbPolyFillRect(pDrawable, pGC, nrectFill, prectInit);
+ else
+ cfb32PolyFillRect(pDrawable, pGC, nrectFill, prectInit);
+ CFB_STATE_RESTORE(&cfb_state, pGC, devPriv);
+#endif
+}
diff --git a/src/ffb_wid.c b/src/ffb_wid.c
new file mode 100644
index 0000000..f84c0bc
--- /dev/null
+++ b/src/ffb_wid.c
@@ -0,0 +1,464 @@
+/*
+ * Acceleration for the Creator and Creator3D framebuffer - WID pool management.
+ *
+ * Copyright (C) 2000 David S. Miller (davem@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_wid.c,v 1.3 2000/12/01 00:24:34 dawes Exp $ */
+
+#include "ffb.h"
+
+static void
+determine_numwids(FFBPtr pFfb)
+{
+ ffb_dac_info_t *p = &pFfb->dac_info;
+
+ if (p->flags & FFB_DAC_PAC1)
+ p->wid_table.num_wids = 32;
+ else
+ p->wid_table.num_wids = 64;
+}
+
+static void
+make_wlut_regval(ffb_dac_info_t *p, ffb_wid_info_t *wid)
+{
+ wid->wlut_regval = 0;
+
+ if (p->flags & FFB_DAC_PAC1) {
+ unsigned int color_model_bits;
+
+ /* Pacifica1 format */
+ if (wid->buffer != 0)
+ wid->wlut_regval |= FFBDAC_PAC1_WLUT_DB;
+
+ if (wid->depth == 8) {
+ if (wid->greyscale) {
+ if (wid->linear)
+ color_model_bits = FFBDAC_PAC1_WLUT_C_8LG;
+ else
+ color_model_bits = FFBDAC_PAC1_WLUT_C_8NG;
+ } else {
+ color_model_bits = FFBDAC_PAC1_WLUT_C_8P;
+ }
+ } else {
+ if (wid->direct) {
+ color_model_bits = FFBDAC_PAC1_WLUT_C_24D;
+ } else {
+ if (wid->linear)
+ color_model_bits = FFBDAC_PAC1_WLUT_C_24LT;
+ else
+ color_model_bits = FFBDAC_PAC1_WLUT_C_24NT;
+ }
+ }
+
+ wid->wlut_regval |= color_model_bits;
+
+ switch (wid->channel) {
+ default:
+ case 0:
+ wid->wlut_regval |= FFBDAC_PAC1_WLUT_P_XO;
+ break;
+ case 1:
+ wid->wlut_regval |= FFBDAC_PAC1_WLUT_P_R;
+ break;
+ case 2:
+ wid->wlut_regval |= FFBDAC_PAC1_WLUT_P_G;
+ break;
+ case 3:
+ wid->wlut_regval |= FFBDAC_PAC1_WLUT_P_B;
+ break;
+ };
+ } else {
+ /* Pacifica2 format */
+ if (wid->buffer != 0)
+ wid->wlut_regval |= FFBDAC_PAC2_WLUT_DB;
+
+ if (wid->depth == 24)
+ wid->wlut_regval |= FFBDAC_PAC2_WLUT_DEPTH;
+
+ switch (wid->channel) {
+ default:
+ case 0:
+ wid->wlut_regval |= FFBDAC_PAC2_WLUT_P_XO;
+ break;
+ case 1:
+ wid->wlut_regval |= FFBDAC_PAC2_WLUT_P_R;
+ break;
+ case 2:
+ wid->wlut_regval |= FFBDAC_PAC2_WLUT_P_G;
+ break;
+ case 3:
+ wid->wlut_regval |= FFBDAC_PAC2_WLUT_P_B;
+ break;
+ };
+
+ if ((wid->depth == 8 && wid->greyscale == 0) ||
+ (wid->depth == 24 && wid->direct != 0))
+ wid->wlut_regval |= FFBDAC_PAC2_WLUT_LKUP;
+
+ if (wid->palette != -1)
+ wid->wlut_regval |=
+ ((wid->palette << 4) & FFBDAC_PAC2_WLUT_PTBL);
+ }
+}
+
+static void
+init_wid_table(FFBPtr pFfb)
+{
+ ffb_dac_info_t *p = &pFfb->dac_info;
+ ffb_wid_pool_t *table = &p->wid_table;
+ int i;
+
+ for (i = 0; i < table->num_wids; i++) {
+ table->wid_pool[i].InUse = FALSE;
+ table->wid_pool[i].buffer = 0;
+ table->wid_pool[i].depth = 24;
+ table->wid_pool[i].greyscale = 0;
+ table->wid_pool[i].linear = 0;
+ table->wid_pool[i].direct = 0;
+ table->wid_pool[i].channel = 0;
+ table->wid_pool[i].palette = -1;
+ make_wlut_regval(p, &table->wid_pool[i]);
+ }
+
+ table->wid_pool[table->num_wids - 1].InUse = TRUE;
+ table->wid_pool[table->num_wids - 1].canshare = FALSE;
+}
+
+static void
+init_hw_wids(FFBPtr pFfb)
+{
+ ffb_dac_info_t *p = &pFfb->dac_info;
+ ffb_dacPtr dac = pFfb->dac;
+ ffb_wid_pool_t *table = &p->wid_table;
+ int i;
+
+ if (p->flags & FFB_DAC_PAC1)
+ dac->cfg = FFBDAC_PAC1_APWLUT_BASE;
+ else
+ dac->cfg = FFBDAC_PAC2_APWLUT_BASE;
+ for (i = 0; i < table->num_wids; i++)
+ dac->cfgdata = table->wid_pool[i].wlut_regval;
+
+ if (p->flags & FFB_DAC_PAC1)
+ dac->cfg = FFBDAC_PAC1_SPWLUT_BASE;
+ else
+ dac->cfg = FFBDAC_PAC2_SPWLUT_BASE;
+ for (i = 0; i < table->num_wids; i++)
+ dac->cfgdata = table->wid_pool[i].wlut_regval;
+}
+
+static void
+init_hw_widmode(FFBPtr pFfb)
+{
+ ffb_dacPtr dac = pFfb->dac;
+ ffb_dac_info_t *p = &pFfb->dac_info;
+ unsigned int uctrl;
+
+ /* For now we use the Combined WID mode until I figure
+ * out exactly how Seperate4 and Seperate8 work. We
+ * also disable overlays for the time being.
+ */
+ p->wid_table.wid_shift = 0;
+
+ dac->cfg = FFBDAC_CFG_UCTRL;
+ uctrl = dac->cfgdata;
+ uctrl &= ~FFBDAC_UCTRL_WMODE;
+ uctrl |= FFBDAC_UCTRL_WM_COMB;
+ uctrl &= ~FFBDAC_UCTRL_OVENAB;
+ dac->cfg = FFBDAC_CFG_UCTRL;
+ dac->cfgdata = uctrl;
+}
+
+void
+FFBWidPoolInit(FFBPtr pFfb)
+{
+ determine_numwids(pFfb);
+ init_wid_table(pFfb);
+ init_hw_wids(pFfb);
+ init_hw_widmode(pFfb);
+}
+
+static void
+update_wids(FFBPtr pFfb, int index)
+{
+ ffb_dac_info_t *p = &pFfb->dac_info;
+ ffb_dacPtr dac = pFfb->dac;
+ unsigned int base;
+ int limit;
+
+ if (pFfb->vtSema)
+ return;
+
+ if (p->flags & FFB_DAC_PAC1)
+ base = FFBDAC_PAC1_SPWLUT(index);
+ else
+ base = FFBDAC_PAC2_SPWLUT(index);
+ DACCFG_WRITE(dac, base, p->wid_table.wid_pool[index].wlut_regval);
+
+ /* Schedule the window transfer. */
+ DACCFG_WRITE(dac, FFBDAC_CFG_WTCTRL,
+ (FFBDAC_CFG_WTCTRL_TCMD | FFBDAC_CFG_WTCTRL_TE));
+
+ limit = 1000000;
+ while (limit--) {
+ unsigned int wtctrl = DACCFG_READ(dac, FFBDAC_CFG_WTCTRL);
+
+ if ((wtctrl & FFBDAC_CFG_WTCTRL_DS) == 0)
+ break;
+ }
+}
+
+unsigned int
+FFBWidAlloc(FFBPtr pFfb, int visclass, int cmap, Bool canshare)
+{
+ ffb_dac_info_t *p = &pFfb->dac_info;
+ ffb_wid_pool_t *table = &p->wid_table;
+ int i, depth, direct, static_greyscale, palette, channel;
+
+ direct = 0;
+ static_greyscale = 0;
+ switch (visclass) {
+ case StaticGray:
+ static_greyscale = 1;
+ /* Fallthrough... */
+ case StaticColor:
+ case GrayScale:
+ case PseudoColor:
+ depth = 8;
+ channel = 1;
+ break;
+
+ case DirectColor:
+ direct = 1;
+ /* Fallthrough... */
+ case TrueColor:
+ depth = 24;
+ channel = 0;
+ break;
+
+ default:
+ return (unsigned int) -1;
+ };
+
+ palette = -1;
+ if (p->flags & FFB_DAC_PAC1) {
+ if (visclass == PseudoColor ||
+ visclass == GrayScale ||
+ visclass == DirectColor)
+ palette = 0;
+ } else {
+ if (visclass == PseudoColor)
+ palette = 0;
+ if (visclass == GrayScale)
+ palette = 1;
+ if (visclass == DirectColor)
+ palette = 2;
+ }
+
+ if (canshare) {
+ for (i = 0; i < table->num_wids; i++) {
+ if (table->wid_pool[i].InUse == TRUE &&
+ table->wid_pool[i].canshare == TRUE &&
+ table->wid_pool[i].palette == palette &&
+ table->wid_pool[i].direct == direct &&
+ table->wid_pool[i].greyscale == static_greyscale &&
+ table->wid_pool[i].channel == channel &&
+ table->wid_pool[i].depth == depth) {
+ table->wid_pool[i].refcount++;
+ return i << table->wid_shift;
+ }
+ }
+ }
+
+ for (i = 0; i < table->num_wids; i++) {
+ if (table->wid_pool[i].InUse == FALSE)
+ break;
+ }
+
+ if (i != table->num_wids) {
+ table->wid_pool[i].InUse = TRUE;
+ table->wid_pool[i].buffer = 0;
+ table->wid_pool[i].depth = depth;
+ table->wid_pool[i].palette = palette;
+ table->wid_pool[i].direct = direct;
+ table->wid_pool[i].greyscale = static_greyscale;
+ if (depth == 8)
+ table->wid_pool[i].channel = 1;
+ else
+ table->wid_pool[i].channel = 0;
+ table->wid_pool[i].refcount = 1;
+ table->wid_pool[i].canshare = canshare;
+ make_wlut_regval(p, &table->wid_pool[i]);
+ update_wids(pFfb, i);
+ return i << table->wid_shift;
+ }
+
+ return (unsigned int) -1;
+}
+
+void
+FFBWidFree(FFBPtr pFfb, unsigned int wid)
+{
+ ffb_dac_info_t *p = &pFfb->dac_info;
+ ffb_wid_pool_t *table = &p->wid_table;
+ int index = wid >> table->wid_shift;
+
+ if (index < 0 || index >= table->num_wids) {
+ return;
+ }
+
+ if (--table->wid_pool[index].refcount == 0) {
+ table->wid_pool[index].InUse = FALSE;
+ }
+}
+
+/* Double Buffering support. */
+
+unsigned int
+FFBWidUnshare(FFBPtr pFfb, unsigned int wid)
+{
+ ffb_dac_info_t *p = &pFfb->dac_info;
+ ffb_wid_pool_t *table = &p->wid_table;
+ int index = wid >> table->wid_shift;
+ int i;
+
+ if (index < 0 || index >= table->num_wids) {
+ return (unsigned int) -1;
+ }
+
+ for (i = 0; i < table->num_wids; i++) {
+ if (table->wid_pool[i].InUse == FALSE)
+ break;
+ }
+
+ if (i == table->num_wids) {
+ return (unsigned int) -1;
+ }
+
+ table->wid_pool[i].InUse = TRUE;
+ table->wid_pool[i].buffer = 0;
+ table->wid_pool[i].depth = table->wid_pool[index].depth;
+ table->wid_pool[i].palette = table->wid_pool[index].palette;
+ table->wid_pool[i].direct = table->wid_pool[index].direct;
+ table->wid_pool[i].greyscale = table->wid_pool[index].greyscale;
+ table->wid_pool[i].channel = table->wid_pool[index].channel;
+ table->wid_pool[i].refcount = 1;
+ table->wid_pool[i].canshare = FALSE;
+ make_wlut_regval(p, &table->wid_pool[i]);
+ update_wids(pFfb, i);
+
+ /* Now free the original WID. */
+ if (--table->wid_pool[index].refcount == 0) {
+ table->wid_pool[index].InUse = FALSE;
+ }
+
+ return i << table->wid_shift;
+}
+
+unsigned int
+FFBWidReshare(FFBPtr pFfb, unsigned int wid)
+{
+ ffb_dac_info_t *p = &pFfb->dac_info;
+ ffb_wid_pool_t *table = &p->wid_table;
+ int index = wid >> table->wid_shift;
+ int i;
+
+ if (index < 0 || index >= table->num_wids) {
+ return wid;
+ }
+
+ for (i = 0; i < table->num_wids; i++) {
+ if (table->wid_pool[i].InUse == TRUE &&
+ table->wid_pool[i].canshare == TRUE &&
+ table->wid_pool[i].depth == table->wid_pool[index].depth &&
+ table->wid_pool[i].palette == table->wid_pool[index].palette &&
+ table->wid_pool[i].direct == table->wid_pool[index].direct &&
+ table->wid_pool[i].greyscale == table->wid_pool[index].greyscale &&
+ table->wid_pool[i].channel == table->wid_pool[index].channel)
+ break;
+ }
+
+ if (i == table->num_wids) {
+ /* OK, very simple, just make the old one shared. */
+ table->wid_pool[index].canshare = TRUE;
+ table->wid_pool[index].buffer = 0;
+ make_wlut_regval(p, &table->wid_pool[index]);
+ update_wids(pFfb, index);
+ return wid;
+ }
+
+ /* Ok, free the original WID. */
+ if (--table->wid_pool[index].refcount == 0) {
+ table->wid_pool[index].InUse = FALSE;
+ }
+
+ /* And grab a reference to the new one. */
+ table->wid_pool[i].refcount++;
+
+ /* And return the shared one. */
+ return i << table->wid_shift;
+}
+
+void
+FFBWidChangeBuffer(FFBPtr pFfb, unsigned int wid, int visible)
+{
+ ffb_dac_info_t *p = &pFfb->dac_info;
+ ffb_wid_pool_t *table = &p->wid_table;
+ int index = wid >> table->wid_shift;
+ int buffer;
+
+ if (index < 0 || index >= table->num_wids)
+ return;
+
+ buffer = (table->wid_pool[index].buffer ^= 1);
+ if (visible) {
+ unsigned int bit;
+
+ if (p->flags & FFB_DAC_PAC1)
+ bit = FFBDAC_PAC1_WLUT_DB;
+ else
+ bit = FFBDAC_PAC2_WLUT_DB;
+
+ if (buffer)
+ table->wid_pool[index].wlut_regval |= bit;
+ else
+ table->wid_pool[index].wlut_regval &= ~bit;
+
+ update_wids(pFfb, index);
+ }
+}
+
+/* Used by DRI part of driver. */
+Bool
+FFBWidIsShared(FFBPtr pFfb, unsigned int wid)
+{
+ ffb_dac_info_t *p = &pFfb->dac_info;
+ ffb_wid_pool_t *table = &p->wid_table;
+ int index = wid >> table->wid_shift;
+
+ if (index < 0 || index >= table->num_wids)
+ return TRUE;
+
+ if (table->wid_pool[index].canshare == TRUE)
+ return TRUE;
+
+ return FALSE;
+}
diff --git a/src/ffb_wline.c b/src/ffb_wline.c
new file mode 100644
index 0000000..feb8034
--- /dev/null
+++ b/src/ffb_wline.c
@@ -0,0 +1,896 @@
+/*
+ * Acceleration for the Creator and Creator3D framebuffer - Wide line rops.
+ *
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * JAKUB JELINEK OR DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_wline.c,v 1.3 2001/03/03 22:41:34 tsi Exp $ */
+
+#define PSZ 32
+
+#include "ffb.h"
+#include "ffb_regs.h"
+#include "ffb_rcache.h"
+#include "ffb_fifo.h"
+
+#include "pixmapstr.h"
+#include "scrnintstr.h"
+
+#include "cfb.h"
+
+#include "miwideline.h"
+
+#error If we start using this again, need to fixup FFB_WRITE_ATTRIBUTES for wids -DaveM
+
+/* Wheee, wide lines... */
+extern int miPolyBuildEdge();
+
+static int LeftClip, RightClip, TopClip, BottomClip;
+
+#define Y_IN_BOX(y) (((y) >= TopClip) && ((y) <= BottomClip))
+#define CLIPSTEPEDGE(edgey,edge,edgeleft) \
+if (ybase == edgey) { \
+ if (edgeleft) { \
+ if (edge->x > xcl) \
+ xcl = edge->x; \
+ } else { \
+ if (edge->x < xcr) \
+ xcr = edge->x; \
+ } \
+ edgey++; \
+ edge->x += edge->stepx; \
+ edge->e += edge->dx; \
+ if (edge->e > 0) { \
+ edge->x += edge->signdx; \
+ edge->e -= edge->dy; \
+ } \
+}
+
+#define CreatorPointHelper(pFfb, x, y) \
+do { \
+ ffb_fbcPtr ffb = (pFfb)->regs; \
+ FFB_WRITE_DRAWOP((pFfb), ffb, FFB_DRAWOP_DOT); \
+ FFBFifo(pFfb, 2); \
+ FFB_WRITE64(&ffb->bh, (y), (x)); \
+} while (0)
+
+static void CreatorFillRectHelper(FFBPtr pFfb,
+ int x, int y, int dx, int dy)
+{
+ ffb_fbcPtr ffb = pFfb->regs;
+ int x2 = x + dx - 1;
+ int y2 = y + dy - 1;
+
+ if(x < LeftClip)
+ x = LeftClip;
+ if(x2 > RightClip)
+ x2 = RightClip;
+ if(y < TopClip)
+ y = TopClip;
+ if(y2 > BottomClip)
+ y2 = BottomClip;
+
+ dx = x2 - x + 1;
+ dy = y2 - y + 1;
+
+ if((dx > 0) && (dy > 0)) {
+ FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_RECTANGLE);
+ FFBFifo(pFfb, 4);
+ FFB_WRITE64(&ffb->by, y, x);
+ FFB_WRITE64_2(&ffb->bh, dy, dx);
+ }
+}
+
+/* The span helper does not check for y being clipped, caller beware */
+static void CreatorSpanHelper(FFBPtr pFfb,
+ int x1, int y, int width)
+{
+ ffb_fbcPtr ffb = pFfb->regs;
+ int x2 = x1 + width - 1;
+
+ if(x1 < LeftClip)
+ x1 = LeftClip;
+ if(x2 > RightClip)
+ x2 = RightClip;
+ width = x2 - x1 + 1;
+
+ if(width > 0) {
+ FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_RECTANGLE);
+ FFBFifo(pFfb, 4);
+ FFB_WRITE64(&ffb->by, y, x1);
+ FFB_WRITE64_2(&ffb->bh, 1, width);
+ }
+}
+
+#define FixError(x, dx, dy, e, sign, step, h) { \
+ e += (h) * dx; \
+ x += (h) * step; \
+ if(e > 0) { \
+ x += e * sign/dy; \
+ e %= dy; \
+ if(e) { \
+ x += sign; \
+ e -= dy; \
+ } \
+ } \
+}
+
+static void
+CreatorFillPolyHelper (DrawablePtr pDrawable, GCPtr pGC,
+ int y, int overall_height,
+ PolyEdgePtr left, PolyEdgePtr right,
+ int left_count, int right_count)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN(pDrawable->pScreen);
+ int left_x, left_e, left_stepx, left_signdx, left_dy, left_dx;
+ int right_x, right_e, right_stepx, right_signdx, right_dy, right_dx, height;
+ int left_height = 0;
+ int right_height = 0;
+ int xorg = 0;
+
+ if (pGC->miTranslate) {
+ y += pDrawable->y;
+ xorg = pDrawable->x;
+ }
+
+ while ((left_count || left_height) && (right_count || right_height)) {
+ if (!left_height && left_count) {
+ left_height = left->height;
+ left_x = left->x + xorg;
+ left_stepx = left->stepx;
+ left_signdx = left->signdx;
+ left_e = left->e;
+ left_dy = left->dy;
+ left_dx = left->dx;
+ left_count--;
+ left++;
+ }
+ if (!right_height && right_count) {
+ right_height = right->height;
+ right_x = right->x + xorg + 1;
+ right_stepx = right->stepx;
+ right_signdx = right->signdx;
+ right_e = right->e;
+ right_dy = right->dy;
+ right_dx = right->dx;
+ right_count--;
+ right++;
+ }
+
+ height = (left_height > right_height) ? right_height : left_height;
+
+ left_height -= height;
+ right_height -= height;
+ while (height--) {
+ if((right_x > left_x) && Y_IN_BOX(y))
+ CreatorSpanHelper(pFfb, left_x, y, right_x - left_x);
+
+ y++;
+
+ left_x += left_stepx;
+ left_e += left_dx;
+ if (left_e > 0) {
+ left_x += left_signdx;
+ left_e -= left_dy;
+ }
+ right_x += right_stepx;
+ right_e += right_dx;
+ if (right_e > 0) {
+ right_x += right_signdx;
+ right_e -= right_dy;
+ }
+ }
+ }
+}
+
+static void
+CreatorWideSegment (DrawablePtr pDrawable, GCPtr pGC,
+ int x1, int y1, int x2, int y2,
+ Bool projectLeft, Bool projectRight,
+ LineFacePtr leftFace, LineFacePtr rightFace)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN(pDrawable->pScreen);
+ double l, L, r, xa, ya, projectXoff, projectYoff, k, maxy;
+ int x, y, dx, dy, finaly, lefty, righty, topy, bottomy, signdx;
+ PolyEdgePtr left, right, top, bottom;
+ PolyEdgeRec lefts[2], rights[2];
+ LineFacePtr tface;
+ int lw = pGC->lineWidth;
+
+ /* draw top-to-bottom always */
+ if (y2 < y1 || y2 == y1 && x2 < x1) {
+ x = x1;
+ x1 = x2;
+ x2 = x;
+
+ y = y1;
+ y1 = y2;
+ y2 = y;
+
+ x = projectLeft;
+ projectLeft = projectRight;
+ projectRight = x;
+
+ tface = leftFace;
+ leftFace = rightFace;
+ rightFace = tface;
+ }
+
+ dy = y2 - y1;
+ signdx = 1;
+ dx = x2 - x1;
+ if (dx < 0)
+ signdx = -1;
+
+ leftFace->x = x1;
+ leftFace->y = y1;
+ leftFace->dx = dx;
+ leftFace->dy = dy;
+
+ rightFace->x = x2;
+ rightFace->y = y2;
+ rightFace->dx = -dx;
+ rightFace->dy = -dy;
+
+ if (!dy) {
+ rightFace->xa = 0;
+ rightFace->ya = (double) lw / 2.0;
+ rightFace->k = -(double) (lw * dx) / 2.0;
+ leftFace->xa = 0;
+ leftFace->ya = -rightFace->ya;
+ leftFace->k = rightFace->k;
+ x = x1;
+ if (projectLeft)
+ x -= (lw >> 1);
+ y = y1 - (lw >> 1);
+ dx = x2 - x;
+ if (projectRight)
+ dx += (lw + 1 >> 1);
+ dy = lw;
+ if(pGC->miTranslate) {
+ x += pDrawable->x;
+ y += pDrawable->y;
+ }
+ CreatorFillRectHelper(pFfb, x, y, dx, dy);
+ } else if (!dx) {
+ leftFace->xa = (double) lw / 2.0;
+ leftFace->ya = 0;
+ leftFace->k = (double) (lw * dy) / 2.0;
+ rightFace->xa = -leftFace->xa;
+ rightFace->ya = 0;
+ rightFace->k = leftFace->k;
+ y = y1;
+ if (projectLeft)
+ y -= lw >> 1;
+ x = x1 - (lw >> 1);
+ dy = y2 - y;
+ if (projectRight)
+ dy += (lw + 1 >> 1);
+ dx = lw;
+ if(pGC->miTranslate) {
+ x += pDrawable->x;
+ y += pDrawable->y;
+ }
+ CreatorFillRectHelper(pFfb, x, y, dx, dy);
+ } else {
+ l = ((double) lw) / 2.0;
+ L = sqrt((double)(dx*dx + dy*dy));
+
+ if (dx < 0) {
+ right = &rights[1];
+ left = &lefts[0];
+ top = &rights[0];
+ bottom = &lefts[1];
+ } else {
+ right = &rights[0];
+ left = &lefts[1];
+ top = &lefts[0];
+ bottom = &rights[1];
+ }
+ r = l / L;
+
+ /* coord of upper bound at integral y */
+ ya = -r * dx;
+ xa = r * dy;
+
+ if (projectLeft | projectRight) {
+ projectXoff = -ya;
+ projectYoff = xa;
+ }
+
+ /* xa * dy - ya * dx */
+ k = l * L;
+
+ leftFace->xa = xa;
+ leftFace->ya = ya;
+ leftFace->k = k;
+ rightFace->xa = -xa;
+ rightFace->ya = -ya;
+ rightFace->k = k;
+
+ if (projectLeft)
+ righty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff,
+ k, dx, dy, x1, y1, 0, right);
+ else
+ righty = miPolyBuildEdge (xa, ya,
+ k, dx, dy, x1, y1, 0, right);
+
+ /* coord of lower bound at integral y */
+ ya = -ya;
+ xa = -xa;
+
+ /* xa * dy - ya * dx */
+ k = - k;
+
+ if (projectLeft)
+ lefty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff,
+ k, dx, dy, x1, y1, 1, left);
+ else
+ lefty = miPolyBuildEdge (xa, ya,
+ k, dx, dy, x1, y1, 1, left);
+
+ /* coord of top face at integral y */
+ if (signdx > 0) {
+ ya = -ya;
+ xa = -xa;
+ }
+
+ if (projectLeft) {
+ double xap = xa - projectXoff;
+ double yap = ya - projectYoff;
+ topy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy,
+ -dy, dx, x1, y1, dx > 0, top);
+ }
+ else
+ topy = miPolyBuildEdge(xa, ya, 0.0,
+ -dy, dx, x1, y1, dx > 0, top);
+
+ /* coord of bottom face at integral y */
+ if (projectRight) {
+ double xap = xa + projectXoff;
+ double yap = ya + projectYoff;
+ bottomy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy,
+ -dy, dx, x2, y2, dx < 0, bottom);
+ maxy = -ya + projectYoff;
+ } else {
+ bottomy = miPolyBuildEdge (xa, ya, 0.0,
+ -dy, dx, x2, y2, dx < 0, bottom);
+ maxy = -ya;
+ }
+
+ finaly = ICEIL (maxy) + y2;
+
+ if (dx < 0) {
+ left->height = bottomy - lefty;
+ right->height = finaly - righty;
+ top->height = righty - topy;
+ } else {
+ right->height = bottomy - righty;
+ left->height = finaly - lefty;
+ top->height = lefty - topy;
+ }
+ bottom->height = finaly - bottomy;
+ CreatorFillPolyHelper (pDrawable, pGC, topy,
+ bottom->height + bottomy - topy, lefts, rights, 2, 2);
+ }
+}
+
+static void
+CreatorLineArcI (DrawablePtr pDraw, GCPtr pGC, int xorg, int yorg)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN(pDraw->pScreen);
+ int x, y, e, ex, slw;
+
+ if (pGC->miTranslate) {
+ xorg += pDraw->x;
+ yorg += pDraw->y;
+ }
+
+ slw = pGC->lineWidth;
+ if (slw == 1) {
+ CreatorPointHelper(pFfb, xorg, yorg);
+ return;
+ }
+
+ y = (slw >> 1) + 1;
+ if (slw & 1)
+ e = - ((y << 2) + 3);
+ else
+ e = - (y << 3);
+ ex = -4;
+ x = 0;
+ while (y) {
+ e += (y << 3) - 4;
+ while (e >= 0) {
+ x++;
+ e += (ex = -((x << 3) + 4));
+ }
+ y--;
+ slw = (x << 1) + 1;
+ if ((e == ex) && (slw > 1))
+ slw--;
+
+ if(Y_IN_BOX(yorg - y))
+ CreatorSpanHelper(pFfb, xorg - x, yorg - y, slw);
+
+ if ((y != 0) && ((slw > 1) || (e != ex)) && Y_IN_BOX(yorg + y))
+ CreatorSpanHelper(pFfb, xorg - x, yorg + y, slw);
+ }
+}
+
+static void
+CreatorLineArcD (DrawablePtr pDraw, GCPtr pGC,
+ double xorg, double yorg,
+ PolyEdgePtr edge1, int edgey1, Bool edgeleft1,
+ PolyEdgePtr edge2, int edgey2, Bool edgeleft2)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN(pDraw->pScreen);
+ double radius, x0, y0, el, er, yk, xlk, xrk, k;
+ int xbase, ybase, y, boty, xl, xr, xcl, xcr, ymin, ymax, ymin1, ymin2;
+ Bool edge1IsMin, edge2IsMin;
+
+ xbase = floor(xorg);
+ x0 = xorg - xbase;
+ ybase = ICEIL (yorg);
+ y0 = yorg - ybase;
+ if (pGC->miTranslate) {
+ xbase += pDraw->x;
+ ybase += pDraw->y;
+ edge1->x += pDraw->x;
+ edge2->x += pDraw->x;
+ edgey1 += pDraw->y;
+ edgey2 += pDraw->y;
+ }
+
+ xlk = x0 + x0 + 1.0;
+ xrk = x0 + x0 - 1.0;
+ yk = y0 + y0 - 1.0;
+ radius = ((double)pGC->lineWidth) / 2.0;
+ y = floor(radius - y0 + 1.0);
+ ybase -= y;
+ ymin = ybase;
+ ymax = 65536;
+ edge1IsMin = FALSE;
+ ymin1 = edgey1;
+ if (edge1->dy >= 0) {
+ if (!edge1->dy) {
+ if (edgeleft1)
+ edge1IsMin = TRUE;
+ else
+ ymax = edgey1;
+ edgey1 = 65536;
+ } else if ((edge1->signdx < 0) == edgeleft1)
+ edge1IsMin = TRUE;
+ }
+ edge2IsMin = FALSE;
+ ymin2 = edgey2;
+ if (edge2->dy >= 0) {
+ if (!edge2->dy) {
+ if (edgeleft2)
+ edge2IsMin = TRUE;
+ else
+ ymax = edgey2;
+ edgey2 = 65536;
+ } else if ((edge2->signdx < 0) == edgeleft2)
+ edge2IsMin = TRUE;
+ }
+ if (edge1IsMin) {
+ ymin = ymin1;
+ if (edge2IsMin && (ymin1 > ymin2))
+ ymin = ymin2;
+ } else if (edge2IsMin)
+ ymin = ymin2;
+ el = radius * radius - ((y + y0) * (y + y0)) - (x0 * x0);
+ er = el + xrk;
+ xl = 1;
+ xr = 0;
+ if (x0 < 0.5) {
+ xl = 0;
+ el -= xlk;
+ }
+ boty = (y0 < -0.5) ? 1 : 0;
+ if (ybase + y - boty > ymax)
+ boty = ymax - ybase - y;
+ while (y > boty) {
+ k = (y << 1) + yk;
+ er += k;
+ while (er > 0.0) {
+ xr++;
+ er += xrk - (xr << 1);
+ }
+ el += k;
+ while (el >= 0.0) {
+ xl--;
+ el += (xl << 1) - xlk;
+ }
+ y--;
+ ybase++;
+ if (ybase < ymin)
+ continue;
+ xcl = xl + xbase;
+ xcr = xr + xbase;
+ CLIPSTEPEDGE(edgey1, edge1, edgeleft1);
+ CLIPSTEPEDGE(edgey2, edge2, edgeleft2);
+ if((xcr >= xcl) && Y_IN_BOX(ybase))
+ CreatorSpanHelper(pFfb, xcl, ybase, xcr - xcl + 1);
+ }
+ er = xrk - (xr << 1) - er;
+ el = (xl << 1) - xlk - el;
+ boty = floor(-y0 - radius + 1.0);
+ if (ybase + y - boty > ymax)
+ boty = ymax - ybase - y;
+ while (y > boty) {
+ k = (y << 1) + yk;
+ er -= k;
+ while ((er >= 0.0) && (xr >= 0)) {
+ xr--;
+ er += xrk - (xr << 1);
+ }
+ el -= k;
+ while ((el > 0.0) && (xl <= 0)) {
+ xl++;
+ el += (xl << 1) - xlk;
+ }
+ y--;
+ ybase++;
+ if (ybase < ymin)
+ continue;
+ xcl = xl + xbase;
+ xcr = xr + xbase;
+ CLIPSTEPEDGE(edgey1, edge1, edgeleft1);
+ CLIPSTEPEDGE(edgey2, edge2, edgeleft2);
+ if((xcr >= xcl) && Y_IN_BOX(ybase))
+ CreatorSpanHelper(pFfb, xcl, ybase, xcr - xcl + 1);
+ }
+}
+
+
+static void
+CreatorLineArc (DrawablePtr pDraw, GCPtr pGC,
+ LineFacePtr leftFace, LineFacePtr rightFace,
+ double xorg, double yorg,
+ Bool isInt)
+{
+ int xorgi, yorgi, edgey1, edgey2;
+ PolyEdgeRec edge1, edge2;
+ Bool edgeleft1, edgeleft2;
+
+ if (isInt) {
+ xorgi = leftFace ? leftFace->x : rightFace->x;
+ yorgi = leftFace ? leftFace->y : rightFace->y;
+ }
+ edgey1 = 65536;
+ edgey2 = 65536;
+ edge1.x = 0; /* not used, keep memory checkers happy */
+ edge1.dy = -1;
+ edge2.x = 0; /* not used, keep memory checkers happy */
+ edge2.dy = -1;
+ edgeleft1 = FALSE;
+ edgeleft2 = FALSE;
+
+ if ((pGC->lineWidth > 2) &&
+ (pGC->capStyle == CapRound && pGC->joinStyle != JoinRound ||
+ pGC->joinStyle == JoinRound && pGC->capStyle == CapButt)) {
+ if (isInt) {
+ xorg = (double) xorgi;
+ yorg = (double) yorgi;
+ }
+
+ if (leftFace && rightFace) {
+ miRoundJoinClip (leftFace, rightFace, &edge1, &edge2,
+ &edgey1, &edgey2, &edgeleft1, &edgeleft2);
+ } else if (leftFace) {
+ edgey1 = miRoundCapClip (leftFace, isInt, &edge1, &edgeleft1);
+ } else if (rightFace) {
+ edgey2 = miRoundCapClip (rightFace, isInt, &edge2, &edgeleft2);
+ }
+
+ isInt = FALSE;
+ }
+
+ if (isInt)
+ CreatorLineArcI(pDraw, pGC, xorgi, yorgi);
+ else
+ CreatorLineArcD(pDraw, pGC, xorg, yorg,
+ &edge1, edgey1, edgeleft1,
+ &edge2, edgey2, edgeleft2);
+}
+
+static void
+CreatorLineJoin (DrawablePtr pDrawable, GCPtr pGC, LineFacePtr pLeft, LineFacePtr pRight)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN(pDrawable->pScreen);
+ double mx, my, denom;
+ PolyVertexRec vertices[4];
+ PolySlopeRec slopes[4];
+ PolyEdgeRec left[4], right[4];
+ int edgecount, nleft, nright, y, height, swapslopes;
+ int joinStyle = pGC->joinStyle;
+ int lw = pGC->lineWidth;
+
+ if (lw == 1) {
+ /* Lines going in the same direction have no join */
+ if ((pLeft->dx >= 0) == (pRight->dx <= 0))
+ return;
+ if (joinStyle != JoinRound) {
+ denom = - pLeft->dx * (double)pRight->dy + pRight->dx *
+ (double)pLeft->dy;
+ if (denom == 0.0)
+ return; /* no join to draw */
+ }
+ if (joinStyle != JoinMiter) {
+ if(pGC->miTranslate)
+ CreatorPointHelper(pFfb,
+ pLeft->x + pDrawable->x,
+ pLeft->y + pDrawable->y);
+ else
+ CreatorPointHelper(pFfb, pLeft->x, pLeft->y);
+ return;
+ }
+ } else {
+ if (joinStyle == JoinRound) {
+ CreatorLineArc(pDrawable, pGC, pLeft, pRight,
+ (double)0.0, (double)0.0, TRUE);
+ return;
+ }
+ denom = - pLeft->dx * (double)pRight->dy + pRight->dx *
+ (double)pLeft->dy;
+ if (denom == 0.0)
+ return; /* no join to draw */
+ }
+
+ swapslopes = 0;
+ if (denom > 0) {
+ pLeft->xa = -pLeft->xa;
+ pLeft->ya = -pLeft->ya;
+ pLeft->dx = -pLeft->dx;
+ pLeft->dy = -pLeft->dy;
+ } else {
+ swapslopes = 1;
+ pRight->xa = -pRight->xa;
+ pRight->ya = -pRight->ya;
+ pRight->dx = -pRight->dx;
+ pRight->dy = -pRight->dy;
+ }
+
+ vertices[0].x = pRight->xa;
+ vertices[0].y = pRight->ya;
+ slopes[0].dx = -pRight->dy;
+ slopes[0].dy = pRight->dx;
+ slopes[0].k = 0;
+
+ vertices[1].x = 0;
+ vertices[1].y = 0;
+ slopes[1].dx = pLeft->dy;
+ slopes[1].dy = -pLeft->dx;
+ slopes[1].k = 0;
+
+ vertices[2].x = pLeft->xa;
+ vertices[2].y = pLeft->ya;
+
+ if (joinStyle == JoinMiter) {
+ my = (pLeft->dy * (pRight->xa * pRight->dy - pRight->ya * pRight->dx) -
+ pRight->dy * (pLeft->xa * pLeft->dy - pLeft->ya * pLeft->dx ))/
+ denom;
+ if (pLeft->dy != 0)
+ mx = pLeft->xa + (my - pLeft->ya) *
+ (double) pLeft->dx / (double) pLeft->dy;
+ else
+ mx = pRight->xa + (my - pRight->ya) *
+ (double) pRight->dx / (double) pRight->dy;
+
+ /* check miter limit */
+ if ((mx * mx + my * my) * 4 > SQSECANT * lw * lw)
+ joinStyle = JoinBevel;
+ }
+
+ if (joinStyle == JoinMiter) {
+ slopes[2].dx = pLeft->dx;
+ slopes[2].dy = pLeft->dy;
+ slopes[2].k = pLeft->k;
+ if (swapslopes) {
+ slopes[2].dx = -slopes[2].dx;
+ slopes[2].dy = -slopes[2].dy;
+ slopes[2].k = -slopes[2].k;
+ }
+ vertices[3].x = mx;
+ vertices[3].y = my;
+ slopes[3].dx = pRight->dx;
+ slopes[3].dy = pRight->dy;
+ slopes[3].k = pRight->k;
+ if (swapslopes) {
+ slopes[3].dx = -slopes[3].dx;
+ slopes[3].dy = -slopes[3].dy;
+ slopes[3].k = -slopes[3].k;
+ }
+ edgecount = 4;
+ } else {
+ double scale, dx, dy, adx, ady;
+
+ adx = dx = pRight->xa - pLeft->xa;
+ ady = dy = pRight->ya - pLeft->ya;
+ if (adx < 0)
+ adx = -adx;
+ if (ady < 0)
+ ady = -ady;
+ scale = ady;
+ if (adx > ady)
+ scale = adx;
+ slopes[2].dx = (dx * 65536) / scale;
+ slopes[2].dy = (dy * 65536) / scale;
+ slopes[2].k = ((pLeft->xa + pRight->xa) * slopes[2].dy -
+ (pLeft->ya + pRight->ya) * slopes[2].dx) / 2.0;
+ edgecount = 3;
+ }
+
+ y = miPolyBuildPoly (vertices, slopes, edgecount, pLeft->x, pLeft->y,
+ left, right, &nleft, &nright, &height);
+ CreatorFillPolyHelper(pDrawable, pGC, y, height, left, right, nleft, nright);
+}
+
+void
+CreatorWideLineSolid (DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, DDXPointPtr pPts)
+{
+ int x1, y1, x2, y2, first = TRUE;
+ Bool projectLeft, projectRight, somethingDrawn = FALSE, selfJoin = FALSE;
+ LineFaceRec leftFace, rightFace, prevRightFace, firstFace;
+ cfbPrivGCPtr devPriv = cfbGetGCPrivate(pGC);
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN(pDrawable->pScreen);
+ ffb_fbcPtr ffb = pFfb->regs;
+ RegionPtr clip;
+ int numRects;
+ unsigned int ppc;
+ BoxPtr pbox;
+
+ clip = ((cfbPrivGC *)(pGC->devPrivates[cfbGCPrivateIndex].ptr))->pCompositeClip;
+ numRects = REGION_NUM_RECTS(clip);
+ if (!numRects)
+ return;
+ if (!(ppc = FFBSetClip(pFfb, ffb, clip, numRects))) {
+ miWideLine(pDrawable, pGC, mode, npt, pPts);
+ return;
+ }
+
+ LeftClip = 2048; TopClip = 2048;
+ RightClip = 0; BottomClip = 0;
+ for (pbox = REGION_RECTS(clip); numRects; numRects--, pbox++) {
+ if (pbox->x1 < LeftClip) LeftClip = pbox->x1;
+ if (pbox->x2 > RightClip) RightClip = pbox->x2 - 1;
+ if (pbox->y1 < TopClip) TopClip = pbox->y1;
+ if (pbox->y2 > BottomClip) BottomClip = pbox->y2 - 1;
+ }
+
+ FFB_WRITE_ATTRIBUTES(pFfb,
+ ppc|FFB_PPC_APE_DISABLE|FFB_PPC_TBE_OPAQUE|
+ FFB_PPC_XS_CONST|FFB_PPC_YS_CONST|FFB_PPC_ZS_CONST|FFB_PPC_CS_CONST,
+ FFB_PPC_VCE_MASK|FFB_PPC_ACE_MASK|FFB_PPC_APE_MASK|FFB_PPC_TBE_MASK|
+ FFB_PPC_XS_MASK|FFB_PPC_YS_MASK|FFB_PPC_ZS_MASK|FFB_PPC_CS_MASK,
+ pGC->planemask,
+ FFB_ROP_EDIT_BIT|pGC->alu,
+ -1, pGC->fgPixel,
+ FFB_FBC_DEFAULT);
+
+ x2 = pPts->x;
+ y2 = pPts->y;
+ if (npt > 1) {
+ if (mode == CoordModePrevious) {
+ int nptTmp;
+ register DDXPointPtr pPtsTmp;
+
+ x1 = x2;
+ y1 = y2;
+ nptTmp = npt;
+ pPtsTmp = pPts + 1;
+ while (--nptTmp) {
+ x1 += pPtsTmp->x;
+ y1 += pPtsTmp->y;
+ ++pPtsTmp;
+ }
+ if ((x2 == x1) && (y2 == y1))
+ selfJoin = TRUE;
+ } else if ((x2 == pPts[npt-1].x) && (y2 == pPts[npt-1].y))
+ selfJoin = TRUE;
+ }
+
+ projectLeft = ((pGC->capStyle == CapProjecting) && !selfJoin);
+ projectRight = FALSE;
+
+ while (--npt) {
+ x1 = x2;
+ y1 = y2;
+ ++pPts;
+ x2 = pPts->x;
+ y2 = pPts->y;
+ if (mode == CoordModePrevious) {
+ x2 += x1;
+ y2 += y1;
+ }
+ if ((x1 != x2) || (y1 != y2)) {
+ somethingDrawn = TRUE;
+ if ((npt == 1) && (pGC->capStyle == CapProjecting) && !selfJoin)
+ projectRight = TRUE;
+ CreatorWideSegment(pDrawable, pGC, x1, y1, x2, y2,
+ projectLeft, projectRight, &leftFace, &rightFace);
+ if (first) {
+ if (selfJoin)
+ firstFace = leftFace;
+ else if (pGC->capStyle == CapRound) {
+ if (pGC->lineWidth == 1) {
+ if(pGC->miTranslate)
+ CreatorPointHelper(pFfb,
+ x1 + pDrawable->x,
+ y1 + pDrawable->y);
+ else
+ CreatorPointHelper(pFfb, x1, y1);
+ } else
+ CreatorLineArc(pDrawable, pGC,
+ &leftFace, (LineFacePtr) NULL,
+ (double)0.0, (double)0.0,
+ TRUE);
+ }
+ } else
+ CreatorLineJoin (pDrawable, pGC, &leftFace, &prevRightFace);
+
+ prevRightFace = rightFace;
+ first = FALSE;
+ projectLeft = FALSE;
+ }
+ if (npt == 1 && somethingDrawn) {
+ if (selfJoin)
+ CreatorLineJoin (pDrawable, pGC, &firstFace, &rightFace);
+ else if (pGC->capStyle == CapRound) {
+ if (pGC->lineWidth == 1) {
+ if(pGC->miTranslate)
+ CreatorPointHelper(pFfb,
+ x2 + pDrawable->x,
+ y2 + pDrawable->y);
+ else
+ CreatorPointHelper(pFfb, x2, y2);
+ } else
+ CreatorLineArc (pDrawable, pGC,
+ (LineFacePtr) NULL, &rightFace,
+ (double)0.0, (double)0.0,
+ TRUE);
+ }
+ }
+ }
+
+ /* handle crock where all points are coincedent */
+ if (!somethingDrawn) {
+ projectLeft = (pGC->capStyle == CapProjecting);
+ CreatorWideSegment (pDrawable, pGC,
+ x2, y2, x2, y2, projectLeft, projectLeft,
+ &leftFace, &rightFace);
+ if (pGC->capStyle == CapRound) {
+ CreatorLineArc (pDrawable, pGC,
+ &leftFace, (LineFacePtr) NULL,
+ (double)0.0, (double)0.0,
+ TRUE);
+ rightFace.dx = -1; /* sleezy hack to make it work */
+ CreatorLineArc (pDrawable, pGC,
+ (LineFacePtr) NULL, &rightFace,
+ (double)0.0, (double)0.0,
+ TRUE);
+ }
+ }
+ pFfb->rp_active = 1;
+}
diff --git a/src/ffb_zeroarc.c b/src/ffb_zeroarc.c
new file mode 100644
index 0000000..86b5876
--- /dev/null
+++ b/src/ffb_zeroarc.c
@@ -0,0 +1,536 @@
+/*
+ * Acceleration for the Creator and Creator3D framebuffer - Zero arc
+ * rops.
+ *
+ * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com)
+ *
+ * Derived from mi/mizerarc.c, see there for authors.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * JAKUB JELINEK OR DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_zeroarc.c,v 1.2 2000/05/23 04:47:45 dawes Exp $ */
+
+#include "ffb.h"
+#include "ffb_regs.h"
+#include "ffb_rcache.h"
+#include "ffb_fifo.h"
+#include "ffb_stip.h"
+
+#include "pixmapstr.h"
+#include "scrnintstr.h"
+
+#define PSZ 8
+#include "cfb.h"
+#undef PSZ
+#include "cfb32.h"
+
+#include "mi.h"
+#include "mizerarc.h"
+
+#define FULLCIRCLE (360 * 64)
+#define OCTANT (45 * 64)
+#define QUADRANT (90 * 64)
+#define HALFCIRCLE (180 * 64)
+#define QUADRANT3 (270 * 64)
+
+typedef struct {
+ int skipStart;
+ int haveStart;
+ DDXPointRec startPt;
+ int haveLast;
+ int skipLast;
+ DDXPointRec endPt;
+ int dashIndex;
+ int dashOffset;
+ int dashIndexInit;
+ int dashOffsetInit;
+} DashInfo;
+
+#define Pixelate(xval,yval,ext) \
+if (((xval)+xoff) >= (ext)->x1 && \
+ ((xval)+xoff) < (ext)->x2 && \
+ ((yval)+yoff) >= (ext)->y1 && \
+ ((yval)+yoff) < (ext)->y2) { \
+ FFBFifo(pFfb, 2); \
+ FFB_WRITE64(&ffb->bh, ((yval)+yoff), ((xval)+xoff)); \
+}
+
+#define Pixelate1(xval,yval,ext) \
+if (((xval)+xoff) >= (ext)->x1 && \
+ ((xval)+xoff) < (ext)->x2 && \
+ ((yval)+yoff) >= (ext)->y1 && \
+ ((yval)+yoff) < (ext)->y2) { \
+ FFBFifo(pFfb, 2); \
+ FFB_WRITE64(&ffb->bh, ((yval)+yoff), ((xval)+xoff)); \
+}
+
+#define DoPix(idx,xval,yval,ext) if (mask & (1 << idx)) Pixelate(xval, yval,ext);
+
+static void
+CreatorZeroArcPts(xArc *arc, DrawablePtr pDrawable, GCPtr pGC, BoxPtr pextent)
+{
+ miZeroArcRec info;
+ register int x, y, a, b, d, mask;
+ register int k1, k3, dx, dy;
+ int xoff, yoff;
+ Bool do360;
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN(pDrawable->pScreen);
+ ffb_fbcPtr ffb = pFfb->regs;
+
+ xoff = 0;
+ yoff = 0;
+ if (pGC->miTranslate) {
+ xoff = pDrawable->x;
+ yoff = pDrawable->y;
+ }
+ do360 = miZeroArcSetup(arc, &info, TRUE);
+ MIARCSETUP();
+ mask = info.initialMask;
+ if (!(arc->width & 1)) {
+ DoPix(1, info.xorgo, info.yorg, pextent);
+ DoPix(3, info.xorgo, info.yorgo, pextent);
+ }
+ if (!info.end.x || !info.end.y) {
+ mask = info.end.mask;
+ info.end = info.altend;
+ }
+ if (do360 && (arc->width == arc->height) && !(arc->width & 1)) {
+ int yorgh = info.yorg + info.h;
+ int xorghp = info.xorg + info.h;
+ int xorghn = info.xorg - info.h;
+ int lastx = 0, lasty = 0;
+
+ while (1) {
+ if (a < 0)
+ break;
+ Pixelate1(info.xorg + x, info.yorg + y, pextent);
+ Pixelate1(info.xorg - x, info.yorg + y, pextent);
+ Pixelate1(info.xorg - x, info.yorgo - y, pextent);
+ Pixelate1(info.xorg + x, info.yorgo - y, pextent);
+ Pixelate1(xorghp - y, yorgh - x, pextent);
+ Pixelate1(xorghn + y, yorgh - x, pextent);
+ Pixelate1(xorghn + y, yorgh + x, pextent);
+ lastx = xorghp - y; lasty = yorgh + x;
+ Pixelate1(xorghp - y, yorgh + x, pextent);
+ MIARCCIRCLESTEP(;);
+ }
+ if (x <= 0 || lastx != info.xorg + x || lasty != info.yorg + y) {
+ Pixelate1(info.xorg + x, info.yorg + y, pextent);
+ Pixelate1(info.xorg - x, info.yorg + y, pextent);
+ Pixelate1(info.xorg - x, info.yorgo - y, pextent);
+ Pixelate1(info.xorg + x, info.yorgo - y, pextent);
+ }
+ x = info.w;
+ y = info.h;
+ } else if (do360) {
+ while (y < info.h || x < info.w) {
+ MIARCOCTANTSHIFT(;);
+ Pixelate1(info.xorg + x, info.yorg + y, pextent);
+ Pixelate1(info.xorgo - x, info.yorg + y, pextent);
+ Pixelate1(info.xorgo - x, info.yorgo - y, pextent);
+ Pixelate1(info.xorg + x, info.yorgo - y, pextent);
+ MIARCSTEP(;,;);
+ }
+ } else {
+ while (y < info.h || x < info.w) {
+ MIARCOCTANTSHIFT(;);
+ if ((x == info.start.x) || (y == info.start.y)) {
+ mask = info.start.mask;
+ info.start = info.altstart;
+ }
+ DoPix(0, info.xorg + x, info.yorg + y, pextent);
+ DoPix(1, info.xorgo - x, info.yorg + y, pextent);
+ DoPix(2, info.xorgo - x, info.yorgo - y, pextent);
+ DoPix(3, info.xorg + x, info.yorgo - y, pextent);
+ if (x == info.end.x || y == info.end.y) {
+ mask = info.end.mask;
+ info.end = info.altend;
+ }
+ MIARCSTEP(;,;);
+ }
+ }
+ if (x == info.start.x || y == info.start.y)
+ mask = info.start.mask;
+ DoPix(0, info.xorg + x, info.yorg + y, pextent);
+ DoPix(2, info.xorgo - x, info.yorgo - y, pextent);
+ if (arc->height & 1) {
+ DoPix(1, info.xorgo - x, info.yorg + y, pextent);
+ DoPix(3, info.xorg + x, info.yorgo - y, pextent);
+ }
+}
+
+#undef DoPix
+#define DoPix(idx,xval,yval) \
+ if (mask & (1 << idx)) \
+ { \
+ arcPts[idx]->x = xval; \
+ arcPts[idx]->y = yval; \
+ arcPts[idx]++; \
+ }
+
+static void
+CreatorZeroArcDashPts(GCPtr pGC, xArc *arc, DashInfo *dinfo, DDXPointPtr points,
+ int maxPts, DDXPointPtr *evenPts, DDXPointPtr *oddPts)
+{
+ miZeroArcRec info;
+ register int x, y, a, b, d, mask;
+ register int k1, k3, dx, dy;
+ int dashRemaining;
+ DDXPointPtr arcPts[4];
+ DDXPointPtr startPts[5], endPts[5];
+ int deltas[5];
+ DDXPointPtr startPt, pt, lastPt, pts;
+ int i, j, delta, ptsdelta, seg, startseg;
+
+ for (i = 0; i < 4; i++)
+ arcPts[i] = points + (i * maxPts);
+ miZeroArcSetup(arc, &info, FALSE);
+ MIARCSETUP();
+ mask = info.initialMask;
+ startseg = info.startAngle / QUADRANT;
+ startPt = arcPts[startseg];
+ if (!(arc->width & 1)) {
+ DoPix(1, info.xorgo, info.yorg);
+ DoPix(3, info.xorgo, info.yorgo);
+ }
+ if (!info.end.x || !info.end.y) {
+ mask = info.end.mask;
+ info.end = info.altend;
+ }
+ while (y < info.h || x < info.w) {
+ MIARCOCTANTSHIFT(;);
+ if ((x == info.firstx) || (y == info.firsty))
+ startPt = arcPts[startseg];
+ if ((x == info.start.x) || (y == info.start.y)) {
+ mask = info.start.mask;
+ info.start = info.altstart;
+ }
+ DoPix(0, info.xorg + x, info.yorg + y);
+ DoPix(1, info.xorgo - x, info.yorg + y);
+ DoPix(2, info.xorgo - x, info.yorgo - y);
+ DoPix(3, info.xorg + x, info.yorgo - y);
+ if (x == info.end.x || y == info.end.y) {
+ mask = info.end.mask;
+ info.end = info.altend;
+ }
+ MIARCSTEP(;,;);
+ }
+ if (x == info.firstx || y == info.firsty)
+ startPt = arcPts[startseg];
+ if (x == info.start.x || y == info.start.y)
+ mask = info.start.mask;
+ DoPix(0, info.xorg + x, info.yorg + y);
+ DoPix(2, info.xorgo - x, info.yorgo - y);
+ if (arc->height & 1) {
+ DoPix(1, info.xorgo - x, info.yorg + y);
+ DoPix(3, info.xorg + x, info.yorgo - y);
+ }
+ for (i = 0; i < 4; i++) {
+ seg = (startseg + i) & 3;
+ pt = points + (seg * maxPts);
+ if (seg & 1) {
+ startPts[i] = pt;
+ endPts[i] = arcPts[seg];
+ deltas[i] = 1;
+ } else {
+ startPts[i] = arcPts[seg] - 1;
+ endPts[i] = pt - 1;
+ deltas[i] = -1;
+ }
+ }
+ startPts[4] = startPts[0];
+ endPts[4] = startPt;
+ startPts[0] = startPt;
+ if (startseg & 1) {
+ if (startPts[4] != endPts[4])
+ endPts[4]--;
+ deltas[4] = 1;
+ } else {
+ if (startPts[0] > startPts[4])
+ startPts[0]--;
+ if (startPts[4] < endPts[4])
+ endPts[4]--;
+ deltas[4] = -1;
+ }
+ if (arc->angle2 < 0) {
+ DDXPointPtr tmps, tmpe;
+ int tmpd;
+
+ tmpd = deltas[0];
+ tmps = startPts[0] - tmpd;
+ tmpe = endPts[0] - tmpd;
+ startPts[0] = endPts[4] - deltas[4];
+ endPts[0] = startPts[4] - deltas[4];
+ deltas[0] = -deltas[4];
+ startPts[4] = tmpe;
+ endPts[4] = tmps;
+ deltas[4] = -tmpd;
+ tmpd = deltas[1];
+ tmps = startPts[1] - tmpd;
+ tmpe = endPts[1] - tmpd;
+ startPts[1] = endPts[3] - deltas[3];
+ endPts[1] = startPts[3] - deltas[3];
+ deltas[1] = -deltas[3];
+ startPts[3] = tmpe;
+ endPts[3] = tmps;
+ deltas[3] = -tmpd;
+ tmps = startPts[2] - deltas[2];
+ startPts[2] = endPts[2] - deltas[2];
+ endPts[2] = tmps;
+ deltas[2] = -deltas[2];
+ }
+ for (i = 0; i < 5 && startPts[i] == endPts[i]; i++);
+ if (i == 5)
+ return;
+ pt = startPts[i];
+ for (j = 4; startPts[j] == endPts[j]; j--);
+ lastPt = endPts[j] - deltas[j];
+ if (dinfo->haveLast &&
+ (pt->x == dinfo->endPt.x) && (pt->y == dinfo->endPt.y)) {
+ startPts[i] += deltas[i];
+ } else {
+ dinfo->dashIndex = dinfo->dashIndexInit;
+ dinfo->dashOffset = dinfo->dashOffsetInit;
+ }
+ if (!dinfo->skipStart && (info.startAngle != info.endAngle)) {
+ dinfo->startPt = *pt;
+ dinfo->haveStart = TRUE;
+ } else if (!dinfo->skipLast && dinfo->haveStart &&
+ (lastPt->x == dinfo->startPt.x) &&
+ (lastPt->y == dinfo->startPt.y) &&
+ (lastPt != startPts[i]))
+ endPts[j] = lastPt;
+ if (info.startAngle != info.endAngle) {
+ dinfo->haveLast = TRUE;
+ dinfo->endPt = *lastPt;
+ }
+ dashRemaining = pGC->dash[dinfo->dashIndex] - dinfo->dashOffset;
+ for (i = 0; i < 5; i++) {
+ pt = startPts[i];
+ lastPt = endPts[i];
+ delta = deltas[i];
+ while (pt != lastPt) {
+ if (dinfo->dashIndex & 1) {
+ pts = *oddPts;
+ ptsdelta = -1;
+ } else {
+ pts = *evenPts;
+ ptsdelta = 1;
+ }
+ while ((pt != lastPt) && --dashRemaining >= 0) {
+ *pts = *pt;
+ pts += ptsdelta;
+ pt += delta;
+ }
+ if (dinfo->dashIndex & 1)
+ *oddPts = pts;
+ else
+ *evenPts = pts;
+ if (dashRemaining <= 0) {
+ if (++(dinfo->dashIndex) == pGC->numInDashList)
+ dinfo->dashIndex = 0;
+ dashRemaining = pGC->dash[dinfo->dashIndex];
+ }
+ }
+ }
+ dinfo->dashOffset = pGC->dash[dinfo->dashIndex] - dashRemaining;
+}
+
+void
+CreatorZeroPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc *parcs)
+{
+ WindowPtr pWin = (WindowPtr) pDrawable;
+ int maxPts = 0;
+ register int n;
+ register xArc *arc;
+ register int i;
+ register int j, k;
+ DDXPointPtr points = NULL, pts, oddPts;
+ int numPts = 0;
+ DashInfo dinfo;
+ FFBPtr pFfb;
+ ffb_fbcPtr ffb;
+ RegionPtr clip;
+ int numRects, ppc;
+ BoxPtr pbox;
+ CreatorPrivGCPtr gcPriv;
+ register int off = 0, c1, c2;
+ register char *addrp = NULL;
+ register int *ppt, pt, pix;
+
+ gcPriv = CreatorGetGCPrivate (pGC);
+ pFfb = GET_FFB_FROM_SCREEN(pDrawable->pScreen);
+ ffb = pFfb->regs;
+ clip = cfbGetCompositeClip(pGC);
+ numRects = REGION_NUM_RECTS(clip);
+ if (!numRects)
+ return;
+ if (pGC->lineStyle == LineSolid && numRects != 1) {
+ miZeroPolyArc(pDrawable, pGC, narcs, parcs);
+ return;
+ }
+ FFBLOG(("CreatorZeroPolyArc: ALU(%x) PMSK(%08x) narcs(%d)\n",
+ pGC->alu, pGC->planemask, narcs));
+ if (pGC->lineStyle == LineSolid)
+ for (arc = parcs, i = narcs, j = 0; --i >= 0; arc++) {
+ if (!miCanZeroArc(arc))
+ miPolyArc(pDrawable, pGC, 1, arc);
+ else
+ j++;
+ }
+ else
+ for (arc = parcs, i = narcs, j = 0; --i >= 0; arc++) {
+ if (!miCanZeroArc(arc))
+ miPolyArc(pDrawable, pGC, 1, arc);
+ else {
+ j++;
+ if (arc->width > arc->height)
+ n = arc->width + (arc->height >> 1);
+ else
+ n = arc->height + (arc->width >> 1);
+ if (n > maxPts)
+ maxPts = n;
+ }
+ }
+ if (!j)
+ return;
+
+ if (pGC->lineStyle != LineSolid) {
+ numPts = maxPts << 2;
+ points = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * (numPts + (maxPts << 1)));
+ if (!points) return;
+ dinfo.haveStart = FALSE;
+ dinfo.skipStart = FALSE;
+ dinfo.haveLast = FALSE;
+ dinfo.dashIndexInit = 0;
+ dinfo.dashOffsetInit = 0;
+ miStepDash((int)pGC->dashOffset, &dinfo.dashIndexInit,
+ (unsigned char *) pGC->dash, (int)pGC->numInDashList,
+ &dinfo.dashOffsetInit);
+ off = *(int *)&pDrawable->x;
+ off -= (off & 0x8000) << 1;
+ if (pGC->depth == 8) {
+ addrp = (char *)pFfb->sfb8r +
+ (pDrawable->y << 11) + (pDrawable->x << 0);
+ } else {
+ addrp = (char *)pFfb->sfb32 +
+ (pDrawable->y << 13) + (pDrawable->x << 2);
+ }
+ ppc = FFB_PPC_CS_VAR;
+ } else
+ ppc = FFB_PPC_CS_CONST;
+
+ if(gcPriv->stipple == NULL) {
+ FFB_ATTR_GC(pFfb, pGC, pWin,
+ ppc | FFB_PPC_APE_DISABLE,
+ FFB_DRAWOP_DOT);
+ } else {
+ unsigned int fbc;
+
+ FFBSetStipple(pFfb, ffb, gcPriv->stipple,
+ ppc, FFB_PPC_CS_MASK);
+ FFB_WRITE_PMASK(pFfb, ffb, pGC->planemask);
+ FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_DOT);
+ fbc = FFB_FBC_WIN(pWin);
+ fbc = (fbc & ~FFB_FBC_XE_MASK) | FFB_FBC_XE_OFF;
+ FFB_WRITE_FBC(pFfb, ffb, fbc);
+ }
+ if((ppc & FFB_PPC_CS_MASK) == FFB_PPC_CS_VAR)
+ FFBWait(pFfb, ffb);
+
+ for (arc = parcs, i = narcs; --i >= 0; arc++) {
+ if (miCanZeroArc(arc)) {
+ if (pGC->lineStyle == LineSolid)
+ CreatorZeroArcPts(arc, pDrawable, pGC, REGION_RECTS(clip));
+ else {
+ pts = points;
+ oddPts = &points[(numPts >> 1) - 1];
+ dinfo.skipLast = i;
+ CreatorZeroArcDashPts(pGC, arc, &dinfo,
+ oddPts + 1, maxPts, &pts, &oddPts);
+ dinfo.skipStart = TRUE;
+ n = pts - points;
+ pbox = REGION_RECTS(clip);
+ j = numRects;
+ pix = pGC->fgPixel;
+ if (pGC->depth == 8) {
+ while (j--) {
+ c1 = *(int *)&pbox->x1 - off;
+ c2 = *(int *)&pbox->x2 - off - 0x00010001;
+ for (ppt = (int *)points, k = n; --k >= 0; ) {
+ pt = *ppt++;
+ if (!(((pt - c1) | (c2 - pt)) & 0x80008000))
+ *(unsigned char *)(addrp + ((pt << 11) & 0x3ff800) + ((pt >> 16) & 0x07ff)) = pix;
+ }
+ pbox++;
+ }
+ } else {
+ while (j--) {
+ c1 = *(int *)&pbox->x1 - off;
+ c2 = *(int *)&pbox->x2 - off - 0x00010001;
+ for (ppt = (int *)points, k = n; --k >= 0; ) {
+ pt = *ppt++;
+ if (!(((pt - c1) | (c2 - pt)) & 0x80008000))
+ *(unsigned int *)(addrp + ((pt << 13) & 0xffe000) + ((pt >> 14) & 0x1ffc)) = pix;
+ }
+ pbox++;
+ }
+ }
+ if (pGC->lineStyle != LineDoubleDash)
+ continue;
+ if ((pGC->fillStyle == FillSolid) || (pGC->fillStyle == FillStippled))
+ pix = pGC->bgPixel;
+ pts = &points[numPts >> 1];
+ oddPts++;
+ n = pts - oddPts;
+ pbox = REGION_RECTS(clip);
+ j = numRects;
+ if (pGC->depth == 8) {
+ while (j--) {
+ c1 = *(int *)&pbox->x1 - off;
+ c2 = *(int *)&pbox->x2 - off - 0x00010001;
+ for (ppt = (int *)oddPts, k = n; --k >= 0; ) {
+ pt = *ppt++;
+ if (!(((pt - c1) | (c2 - pt)) & 0x80008000))
+ *(unsigned char *)(addrp + ((pt << 11) & 0x3ff800) + ((pt >> 16) & 0x07ff)) = pix;
+ }
+ pbox++;
+ }
+ } else {
+ while (j--) {
+ c1 = *(int *)&pbox->x1 - off;
+ c2 = *(int *)&pbox->x2 - off - 0x00010001;
+ for (ppt = (int *)oddPts, k = n; --k >= 0; ) {
+ pt = *ppt++;
+ if (!(((pt - c1) | (c2 - pt)) & 0x80008000))
+ *(unsigned int *)(addrp + ((pt << 13) & 0xffe000) + ((pt >> 14) & 0x1ffc)) = pix;
+ }
+ pbox++;
+ }
+ }
+ }
+ }
+ }
+ if (pGC->lineStyle != LineSolid) {
+ DEALLOCATE_LOCAL(points);
+ } else {
+ pFfb->rp_active = 1;
+ FFBSync(pFfb, ffb);
+ }
+}