diff options
author | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 16:48:55 +0000 |
---|---|---|
committer | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 16:48:55 +0000 |
commit | 68c56916d79bf06e26e01c3e84206edc928d9b51 (patch) | |
tree | d39c13092dc680721e163e448a57df847a6fad62 |
Initial revision
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); + } +} |