i128exa.c revision 50806d53
150806d53Smrg/* 250806d53Smrg * Copyright 1997-2000 by Robin Cutshaw <robin@XFree86.Org> 350806d53Smrg * Copyright 2005 Adam Jackson <ajax@nwnk.net> 450806d53Smrg * 550806d53Smrg * Permission to use, copy, modify, distribute, and sell this software and its 650806d53Smrg * documentation for any purpose is hereby granted without fee, provided that 750806d53Smrg * the above copyright notice appear in all copies and that both that 850806d53Smrg * copyright notice and this permission notice appear in supporting 950806d53Smrg * documentation, and that the names of the authors not be used in 1050806d53Smrg * advertising or publicity pertaining to distribution of the software without 1150806d53Smrg * specific, written prior permission. The authors make no representations 1250806d53Smrg * about the suitability of this software for any purpose. It is provided 1350806d53Smrg * "as is" without express or implied warranty. 1450806d53Smrg * 1550806d53Smrg * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 1650806d53Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 1750806d53Smrg * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 1850806d53Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 1950806d53Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 2050806d53Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 2150806d53Smrg * PERFORMANCE OF THIS SOFTWARE. 2250806d53Smrg */ 2350806d53Smrg 2450806d53Smrg/* Solid and Copy support derived from the i128 XAA code */ 2550806d53Smrg 2650806d53Smrg#ifdef HAVE_CONFIG_H 2750806d53Smrg#include "config.h" 2850806d53Smrg#endif 2950806d53Smrg 3050806d53Smrg#include "exa.h" 3150806d53Smrg#include "miline.h" 3250806d53Smrg#include "servermd.h" 3350806d53Smrg#include "picture.h" 3450806d53Smrg 3550806d53Smrg#include "xf86.h" 3650806d53Smrg#include "xf86_OSproc.h" 3750806d53Smrg#include "xf86_ansic.h" 3850806d53Smrg#include "xf86Pci.h" 3950806d53Smrg#include "xf86PciInfo.h" 4050806d53Smrg 4150806d53Smrg#include "i128.h" 4250806d53Smrg#include "i128reg.h" 4350806d53Smrg 4450806d53Smrg#define PI128_FROM_PIXMAP(x) \ 4550806d53Smrg I128Ptr pI128 = I128PTR(xf86Screens[x->drawable.pScreen->myNum]) 4650806d53Smrg#define PI128_FROM_SCREEN(x) \ 4750806d53Smrg I128Ptr pI128 = I128PTR(xf86Screens[x->myNum]) 4850806d53Smrg#define PI128_FROM_PICTURE(x) \ 4950806d53Smrg I128Ptr pI128 = I128PTR(xf86Screens[x->pDrawable->pScreen->myNum]) 5050806d53Smrg 5150806d53Smrg/* we might be able to do something smarter than this */ 5250806d53Smrg#define ENG_PIPELINE_READY() \ 5350806d53Smrg while (pI128->mem.rbase_a[BUSY] & BUSY_BUSY) 5450806d53Smrg#define ENG_DONE() \ 5550806d53Smrg while (pI128->mem.rbase_a[FLOW] & (FLOW_DEB | FLOW_MCB | FLOW_PRV)) 5650806d53Smrg 5750806d53Smrg#if 1 5850806d53Smrg#define I128_EXA_DEBUG(x) 5950806d53Smrg#else 6050806d53Smrg#define I128_EXA_DEBUG(x) ErrorF x 6150806d53Smrg#endif 6250806d53Smrg 6350806d53Smrg/* technically we should set the caches to bogus things during init... */ 6450806d53Smrg#define CACHE_DEBUG 0 6550806d53Smrg 6650806d53Smrg#define CACHED_UPDATE(val, reg) \ 6750806d53Smrg do if (pI128->val != val) { \ 6850806d53Smrg if (CACHE_DEBUG) I128_EXA_DEBUG(("Updated cache for " #reg "\n")); \ 6950806d53Smrg pI128->mem.rbase_a[reg] = pI128->val = val; \ 7050806d53Smrg } while (0) 7150806d53Smrg 7250806d53Smrgstatic void 7350806d53Smrgi128SetBufCtrl(I128Ptr pI128, int dest_bpp) 7450806d53Smrg{ 7550806d53Smrg unsigned int buf_ctrl; 7650806d53Smrg 7750806d53Smrg switch (dest_bpp) { 7850806d53Smrg case 8: buf_ctrl = BC_PSIZ_8B; break; 7950806d53Smrg case 16: buf_ctrl = BC_PSIZ_16B; break; 8050806d53Smrg case 24: 8150806d53Smrg case 32: buf_ctrl = BC_PSIZ_32B; break; 8250806d53Smrg default: buf_ctrl = 0; break; /* error */ 8350806d53Smrg } 8450806d53Smrg if (pI128->Chipset == PCI_CHIP_I128_T2R) { 8550806d53Smrg if (pI128->MemoryType == I128_MEMORY_SGRAM) 8650806d53Smrg buf_ctrl |= BC_MDM_PLN; 8750806d53Smrg else 8850806d53Smrg buf_ctrl |= BC_BLK_ENA; 8950806d53Smrg } 9050806d53Smrg 9150806d53Smrg CACHED_UPDATE(buf_ctrl, BUF_CTRL); 9250806d53Smrg} 9350806d53Smrg 9450806d53Smrgstatic const CARD32 i128alu[16] = 9550806d53Smrg{ 9650806d53Smrg CR_CLEAR << 8, 9750806d53Smrg CR_AND << 8, 9850806d53Smrg CR_AND_REV << 8, 9950806d53Smrg CR_COPY << 8, 10050806d53Smrg CR_AND_INV << 8, 10150806d53Smrg CR_NOOP << 8, 10250806d53Smrg CR_XOR << 8, 10350806d53Smrg CR_OR << 8, 10450806d53Smrg CR_NOR << 8, 10550806d53Smrg CR_EQUIV << 8, 10650806d53Smrg CR_INVERT << 8, 10750806d53Smrg CR_OR_REV << 8, 10850806d53Smrg CR_COPY_INV << 8, 10950806d53Smrg CR_OR_INV << 8, 11050806d53Smrg CR_NAND << 8, 11150806d53Smrg CR_SET << 8 11250806d53Smrg}; 11350806d53Smrg 11450806d53Smrg/* 8bpp 16bpp 32bpp unused */ 11550806d53Smrgstatic const int min_size[] = { 0x62, 0x32, 0x1A, 0x00 }; 11650806d53Smrgstatic const int max_size[] = { 0x80, 0x40, 0x20, 0x00 }; 11750806d53Smrgstatic const int split_size[] = { 0x20, 0x10, 0x08, 0x00 }; 11850806d53Smrg 11950806d53Smrg/* 12050806d53Smrg * this is the workhorse for our solid and copy routines. this works because 12150806d53Smrg * when CS_SOLID is set, the color comes from the FORE register regardless of 12250806d53Smrg * the source pixmap coords. 12350806d53Smrg */ 12450806d53Smrg 12550806d53Smrgstatic void 12650806d53Smrgi128ExaBlit(PixmapPtr dst, int x1, int y1, int x2, int y2, int w, int h) 12750806d53Smrg{ 12850806d53Smrg int wh; 12950806d53Smrg PI128_FROM_PIXMAP(dst); 13050806d53Smrg 13150806d53Smrg I128_EXA_DEBUG(("Blit: %d %d %d %d %d %d\n", x1, y1, x2, y2, w, h)); 13250806d53Smrg ENG_PIPELINE_READY(); 13350806d53Smrg 13450806d53Smrg /* 13550806d53Smrg * this deserves explanation. XY3_DIR == 0 means left to right, top to 13650806d53Smrg * bottom. setting bit zero (DIR_LR_BT) switches to bottom to top, and 13750806d53Smrg * setting bit one (DIR_RL_TB) switches to right to left. XXX rewrite me. 13850806d53Smrg */ 13950806d53Smrg if (pI128->blitdir & DIR_RL_TB) { /* right-to-left */ 14050806d53Smrg x1 += w; x1--; 14150806d53Smrg x2 += w; x2--; 14250806d53Smrg } 14350806d53Smrg if (pI128->blitdir & DIR_LR_BT) { /* bottom-to-top */ 14450806d53Smrg y1 += h; y1--; 14550806d53Smrg y2 += h; y2--; 14650806d53Smrg } 14750806d53Smrg 14850806d53Smrg if (pI128->Chipset == PCI_CHIP_I128) { 14950806d53Smrg int bppi; 15050806d53Smrg 15150806d53Smrg /* The I128-1 has a nasty bitblit bug 15250806d53Smrg * that occurs when dest is exactly 8 pages wide 15350806d53Smrg */ 15450806d53Smrg 15550806d53Smrg bppi = (pI128->mem.rbase_a[BUF_CTRL] & BC_PSIZ_MSK) >> 24; 15650806d53Smrg 15750806d53Smrg if ((w >= min_size[bppi]) && (w <= max_size[bppi])) { 15850806d53Smrg bppi = split_size[bppi]; 15950806d53Smrg#if 1 16050806d53Smrg /* split method */ 16150806d53Smrg 16250806d53Smrg wh = (bppi << 16) | h; 16350806d53Smrg CACHED_UPDATE(wh, XY2_WH); 16450806d53Smrg pI128->mem.rbase_a[XY0_SRC] = (x1 << 16) | y1; MB; 16550806d53Smrg pI128->mem.rbase_a[XY1_DST] = (x2 << 16) | y2; MB; 16650806d53Smrg 16750806d53Smrg ENG_PIPELINE_READY(); 16850806d53Smrg 16950806d53Smrg w -= bppi; 17050806d53Smrg 17150806d53Smrg if (pI128->blitdir & DIR_RL_TB) { 17250806d53Smrg /* right to left blit */ 17350806d53Smrg x1 -= bppi; 17450806d53Smrg x2 -= bppi; 17550806d53Smrg } else { 17650806d53Smrg /* left to right blit */ 17750806d53Smrg x1 += bppi; 17850806d53Smrg x2 += bppi; 17950806d53Smrg } 18050806d53Smrg#else 18150806d53Smrg /* clip method */ 18250806d53Smrg pI128->mem.rbase_a[CLPTL] = (x2 << 16) | y2; 18350806d53Smrg pI128->mem.rbase_a[CLPBR] = ((x2 + w) << 16) | (y2 + h); 18450806d53Smrg w += bppi; 18550806d53Smrg#endif 18650806d53Smrg } 18750806d53Smrg } 18850806d53Smrg 18950806d53Smrg /* this is overkill, but you can never have too much overkill */ 19050806d53Smrg wh = (w << 16) | h; 19150806d53Smrg CACHED_UPDATE(wh, XY2_WH); 19250806d53Smrg 19350806d53Smrg pI128->mem.rbase_a[XY0_SRC] = (x1 << 16) | y1; MB; 19450806d53Smrg pI128->mem.rbase_a[XY1_DST] = (x2 << 16) | y2; MB; 19550806d53Smrg} 19650806d53Smrg 19750806d53Smrgstatic void 19850806d53Smrgi128WaitMarker(ScreenPtr pScreen, int Marker) 19950806d53Smrg{ 20050806d53Smrg PI128_FROM_SCREEN(pScreen); 20150806d53Smrg ENG_DONE(); 20250806d53Smrg} 20350806d53Smrg 20450806d53Smrgstatic void 20550806d53Smrgi128SetPlanemask(I128Ptr pI128, Pixel p) 20650806d53Smrg{ 20750806d53Smrg Pixel planemask; 20850806d53Smrg I128_EXA_DEBUG(("SetPlanemask: %d\n", (int)p)); 20950806d53Smrg if (p == -1) 21050806d53Smrg planemask = -1; 21150806d53Smrg else switch (pI128->bitsPerPixel) { 21250806d53Smrg case 8: 21350806d53Smrg planemask = p * 0x01010101; break; 21450806d53Smrg case 16: 21550806d53Smrg planemask = p * 0x00010001; break; 21650806d53Smrg default: 21750806d53Smrg planemask = p; break; 21850806d53Smrg } 21950806d53Smrg 22050806d53Smrg CACHED_UPDATE(planemask, MASK); 22150806d53Smrg} 22250806d53Smrg 22350806d53Smrg/* this should be superfluous... */ 22450806d53Smrgstatic void 22550806d53Smrgi128SetClip(I128Ptr pI128) 22650806d53Smrg{ 22750806d53Smrg#if 0 22850806d53Smrg pI128->clptl = pI128->mem.rbase_a[CLPTL] = 0x00000000; 22950806d53Smrg pI128->clpbr = pI128->mem.rbase_a[CLPBR] = (4095 << 16) | 2047; 23050806d53Smrg#endif 23150806d53Smrg} 23250806d53Smrg 23350806d53Smrgstatic void 23450806d53Smrgi128SetBlitDirection(I128Ptr pI128, int dx, int dy) 23550806d53Smrg{ 23650806d53Smrg int blitdir; 23750806d53Smrg 23850806d53Smrg I128_EXA_DEBUG(("SetBlitDirection: %d %d\n", dx, dy)); 23950806d53Smrg 24050806d53Smrg if (dx < 0) { 24150806d53Smrg if (dy < 0) blitdir = DIR_RL_BT; 24250806d53Smrg else blitdir = DIR_RL_TB; 24350806d53Smrg } else { 24450806d53Smrg if (dy < 0) blitdir = DIR_LR_BT; 24550806d53Smrg else blitdir = DIR_LR_TB; 24650806d53Smrg } 24750806d53Smrg 24850806d53Smrg CACHED_UPDATE(blitdir, XY3_DIR); 24950806d53Smrg} 25050806d53Smrg 25150806d53Smrgstatic void 25250806d53Smrgi128SetRop(I128Ptr pI128, int alu, int solid) 25350806d53Smrg{ 25450806d53Smrg int cmd; 25550806d53Smrg 25650806d53Smrg I128_EXA_DEBUG(("SetRop: %d %d\n", alu, solid)); 25750806d53Smrg 25850806d53Smrg cmd = i128alu[alu] | CO_BITBLT | (solid ? (CS_SOLID << 16) : 0); 25950806d53Smrg 26050806d53Smrg CACHED_UPDATE(cmd, CMD); 26150806d53Smrg} 26250806d53Smrg 26350806d53Smrgstatic void 26450806d53Smrgi128SetSourcePixmap(I128Ptr pI128, PixmapPtr src) 26550806d53Smrg{ 26650806d53Smrg unsigned int sorg = exaGetPixmapOffset(src); 26750806d53Smrg unsigned int sptch = exaGetPixmapPitch(src); 26850806d53Smrg 26950806d53Smrg I128_EXA_DEBUG(("SetSourcePixmap: %x, %d\n", sorg, sptch)); 27050806d53Smrg 27150806d53Smrg CACHED_UPDATE(sorg, DE_SORG); 27250806d53Smrg CACHED_UPDATE(sptch, DE_SPTCH); 27350806d53Smrg} 27450806d53Smrg 27550806d53Smrgstatic void 27650806d53Smrgi128SetDestPixmap(I128Ptr pI128, PixmapPtr dst) 27750806d53Smrg{ 27850806d53Smrg unsigned int dorg = exaGetPixmapOffset(dst); 27950806d53Smrg unsigned int dptch = exaGetPixmapPitch(dst); 28050806d53Smrg 28150806d53Smrg I128_EXA_DEBUG(("SetDestPixmap: %x, %d\n", dorg, dptch)); 28250806d53Smrg 28350806d53Smrg CACHED_UPDATE(dorg, DE_DORG); 28450806d53Smrg CACHED_UPDATE(dptch, DE_DPTCH); 28550806d53Smrg} 28650806d53Smrg 28750806d53Smrgstatic void 28850806d53Smrgi128SetTexture(I128Ptr pI128, PixmapPtr tex) 28950806d53Smrg{ 29050806d53Smrg unsigned int torg = exaGetPixmapOffset(tex); 29150806d53Smrg unsigned int tptch = exaGetPixmapPitch(tex); 29250806d53Smrg 29350806d53Smrg I128_EXA_DEBUG(("SetTexture: %x, %d\n", torg, tptch)); 29450806d53Smrg 29550806d53Smrg CACHED_UPDATE(torg, LOD0_ORG); 29650806d53Smrg CACHED_UPDATE(tptch, DE_TPTCH); 29750806d53Smrg} 29850806d53Smrg 29950806d53Smrgstatic const int func_tab[13][2] = { 30050806d53Smrg /* source function, destination function */ 30150806d53Smrg { ABLEND_SRC_ZERO, ABLEND_DST_ZERO }, /* clear */ 30250806d53Smrg { ABLEND_SRC_ONE, ABLEND_DST_ZERO }, /* src */ 30350806d53Smrg { ABLEND_SRC_ZERO, ABLEND_DST_ONE }, /* dst */ 30450806d53Smrg { ABLEND_SRC_ONE, ABLEND_DST_OMSRC_ALPHA }, /* over */ 30550806d53Smrg { ABLEND_SRC_OMDST_ALPHA, ABLEND_DST_ONE }, /* overreverse */ 30650806d53Smrg { ABLEND_SRC_DST_ALPHA, ABLEND_DST_ZERO }, /* in */ 30750806d53Smrg { ABLEND_SRC_ZERO, ABLEND_DST_SRC_ALPHA }, /* inreverse */ 30850806d53Smrg { ABLEND_SRC_OMDST_ALPHA, ABLEND_DST_ZERO }, /* out */ 30950806d53Smrg { ABLEND_SRC_ZERO, ABLEND_DST_OMSRC_ALPHA }, /* outreverse */ 31050806d53Smrg { ABLEND_SRC_DST_ALPHA, ABLEND_DST_OMSRC_ALPHA }, /* atop */ 31150806d53Smrg { ABLEND_SRC_OMDST_ALPHA, ABLEND_DST_SRC_ALPHA }, /* atopreverse */ 31250806d53Smrg { ABLEND_SRC_OMDST_ALPHA, ABLEND_DST_OMSRC_ALPHA }, /* xor */ 31350806d53Smrg { ABLEND_SRC_ONE, ABLEND_DST_ONE } /* add */ 31450806d53Smrg}; 31550806d53Smrg 31650806d53Smrgstatic void 31750806d53Smrgi128SetAlphaForOp(I128Ptr pI128, int op, int enable) 31850806d53Smrg{ 31950806d53Smrg int acntrl = 0; 32050806d53Smrg 32150806d53Smrg if (enable) { 32250806d53Smrg acntrl |= ACTL_BE; /* blend enable */ 32350806d53Smrg acntrl |= func_tab[op][0]; /* source factor */ 32450806d53Smrg acntrl |= func_tab[op][1]; /* dest_factor */ 32550806d53Smrg acntrl |= 0; /* ACTL_AMD; / * modulate alpha */ 32650806d53Smrg } else { 32750806d53Smrg acntrl = 0; 32850806d53Smrg } 32950806d53Smrg 33050806d53Smrg I128_EXA_DEBUG(("SetAlphaForOp: %d, %d\n", op, enable)); 33150806d53Smrg 33250806d53Smrg CACHED_UPDATE(acntrl, ACNTRL); 33350806d53Smrg} 33450806d53Smrg 33550806d53Smrg/* we don't need a finalizer, yet */ 33650806d53Smrgstatic void 33750806d53Smrgi128Done(PixmapPtr p) { 33850806d53Smrg I128_EXA_DEBUG(("Done\n\n")); 33950806d53Smrg return; 34050806d53Smrg} 34150806d53Smrg 34250806d53Smrg/* Solid */ 34350806d53Smrg 34450806d53Smrgstatic Bool 34550806d53Smrgi128PrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg) 34650806d53Smrg{ 34750806d53Smrg PI128_FROM_PIXMAP(pPixmap); 34850806d53Smrg 34950806d53Smrg ENG_PIPELINE_READY(); 35050806d53Smrg 35150806d53Smrg i128SetPlanemask(pI128, planemask); 35250806d53Smrg 35350806d53Smrg if (alu != GXclear && alu != GXset) 35450806d53Smrg pI128->mem.rbase_a[FORE] = fg; 35550806d53Smrg 35650806d53Smrg i128SetClip(pI128); 35750806d53Smrg i128SetBlitDirection(pI128, 1, 1); /* probably unnecessary/ignored */ 35850806d53Smrg 35950806d53Smrg i128SetAlphaForOp(pI128, 0, 0); 36050806d53Smrg i128SetRop(pI128, alu, 1); 36150806d53Smrg 36250806d53Smrg /* no need to set the source, the chip ignores it */ 36350806d53Smrg i128SetDestPixmap(pI128, pPixmap); 36450806d53Smrg 36550806d53Smrg return TRUE; 36650806d53Smrg} 36750806d53Smrg 36850806d53Smrgstatic void 36950806d53Smrgi128Solid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2) 37050806d53Smrg{ 37150806d53Smrg i128ExaBlit(pPixmap, 0, 0, x1, y1, x2 - x1, y2 - y1); 37250806d53Smrg} 37350806d53Smrg 37450806d53Smrg/* Copy */ 37550806d53Smrg 37650806d53Smrgstatic Bool 37750806d53Smrgi128PrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int dx, int dy, 37850806d53Smrg int alu, Pixel planemask) 37950806d53Smrg{ 38050806d53Smrg PI128_FROM_PIXMAP(pSrcPixmap); 38150806d53Smrg 38250806d53Smrg ENG_PIPELINE_READY(); 38350806d53Smrg 38450806d53Smrg i128SetPlanemask(pI128, planemask); 38550806d53Smrg i128SetClip(pI128); 38650806d53Smrg i128SetBlitDirection(pI128, dx, dy); 38750806d53Smrg 38850806d53Smrg i128SetAlphaForOp(pI128, 0, 0); 38950806d53Smrg i128SetRop(pI128, alu, 0); 39050806d53Smrg 39150806d53Smrg i128SetSourcePixmap(pI128, pSrcPixmap); 39250806d53Smrg i128SetDestPixmap(pI128, pDstPixmap); 39350806d53Smrg 39450806d53Smrg return TRUE; 39550806d53Smrg} 39650806d53Smrg 39750806d53Smrgstatic void 39850806d53Smrgi128Copy(PixmapPtr pDstPixmap, int x1, int y1, int x2, int y2, int w, int h) 39950806d53Smrg{ 40050806d53Smrg i128ExaBlit(pDstPixmap, x1, y1, x2, y2, w, h); 40150806d53Smrg} 40250806d53Smrg 40350806d53Smrg/* Composite */ 40450806d53Smrg 40550806d53Smrgstatic const struct source_format source_formats[] = { 40650806d53Smrg /* 32bpp */ 40750806d53Smrg { PICT_a8r8g8b8, 0x14, 0, 0 }, 40850806d53Smrg { PICT_x8r8g8b8, 0x14, 0, 1 }, 40950806d53Smrg#if 0 41050806d53Smrg { PICT_a8b8g8r8, 0x14, 0, 0 }, 41150806d53Smrg { PICT_x8b8g8r8, 0x14, 0, 1 }, 41250806d53Smrg /* no direct 24bpp formats */ 41350806d53Smrg /* 16bpp */ 41450806d53Smrg { PICT_r5g6b5, 0x12, 0, 0 }, 41550806d53Smrg { PICT_b5g6r5, 0x12, 0, 0 }, 41650806d53Smrg { PICT_a1r5g5b5, 0x11, 0, 0 }, 41750806d53Smrg { PICT_x1r5g5b5, 0x11, 0, 1 }, 41850806d53Smrg { PICT_a1b5g5r5, 0x11, 0, 0 }, 41950806d53Smrg { PICT_x1b5g5r5, 0x11, 0, 1 }, 42050806d53Smrg { PICT_a4r4g4b4, 0x10, 0, 0 }, 42150806d53Smrg { PICT_x4r4g4b4, 0x10, 0, 1 }, 42250806d53Smrg { PICT_a4b4g4r4, 0x10, 0, 0 }, 42350806d53Smrg { PICT_x4b4g4r4, 0x10, 0, 1 }, 42450806d53Smrg /* 8bpp */ 42550806d53Smrg { PICT_a8, 0x21, 0, 0 }, 42650806d53Smrg { PICT_r3g3b2, 0x0D, 0, 0 }, 42750806d53Smrg { PICT_b2g3r3, 0x0D, 0, 0 }, 42850806d53Smrg { PICT_a2r2g2b2, 0x30, 0, 0 }, 42950806d53Smrg { PICT_a2b2g2r2, 0x30, 0, 0 }, 43050806d53Smrg /* 4bpp */ 43150806d53Smrg { PICT_a4, 0x20, 0, 0 }, 43250806d53Smrg#endif 43350806d53Smrg /* terminator */ 43450806d53Smrg { 0, 0, 0, 0 } 43550806d53Smrg}; 43650806d53Smrg 43750806d53Smrgstatic struct source_format * 43850806d53Smrgi128MapSourceFormat(int fmt) 43950806d53Smrg{ 44050806d53Smrg struct source_format *f; 44150806d53Smrg for (f = (struct source_format *)source_formats; f->render_format; f++) 44250806d53Smrg if (f->render_format == fmt) 44350806d53Smrg return f; 44450806d53Smrg return NULL; 44550806d53Smrg} 44650806d53Smrg 44750806d53Smrgstruct dest_format { 44850806d53Smrg int render_format; 44950806d53Smrg int i128_format; 45050806d53Smrg}; 45150806d53Smrg 45250806d53Smrgstatic const struct dest_format dest_formats[] = { 45350806d53Smrg { 0, 0 } 45450806d53Smrg}; 45550806d53Smrg 45650806d53Smrgstatic struct dest_format * 45750806d53Smrgi128MapDestFormat(int fmt) 45850806d53Smrg{ 45950806d53Smrg return NULL; 46050806d53Smrg} 46150806d53Smrg 46250806d53Smrg/* Composite is probably t2r and t2r4 only */ 46350806d53Smrgstatic Bool 46450806d53Smrgi128CheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, 46550806d53Smrg PicturePtr pDstPicture) 46650806d53Smrg{ 46750806d53Smrg PI128_FROM_PICTURE(pDstPicture); 46850806d53Smrg 46950806d53Smrg if (op >= PictOpSaturate) return FALSE; 47050806d53Smrg 47150806d53Smrg /* 47250806d53Smrg * no direct alpha mask support. we only have one TMU, so while we 47350806d53Smrg * can emulate it, we should emulate it in the generic EXA layer. 47450806d53Smrg */ 47550806d53Smrg if (pMaskPicture) return FALSE; 47650806d53Smrg 47750806d53Smrg /* when transforms added, be sure to check for linear/nearest */ 47850806d53Smrg /* if (pSrcPicture->transform) return FALSE; */ 47950806d53Smrg 48050806d53Smrg /* no support for external alpha */ 48150806d53Smrg if (pSrcPicture->alphaMap || pDstPicture->alphaMap) return FALSE; 48250806d53Smrg 48350806d53Smrg pI128->source = i128MapSourceFormat(pSrcPicture->format); 48450806d53Smrg if (!pI128->source) 48550806d53Smrg return FALSE; 48650806d53Smrg#if 0 48750806d53Smrg if (!i128MapDestFormat(pDstPicture->format)) return FALSE; 48850806d53Smrg#endif 48950806d53Smrg 49050806d53Smrg return TRUE; 49150806d53Smrg} 49250806d53Smrg 49350806d53Smrgstatic Bool 49450806d53Smrgi128PrepareComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, 49550806d53Smrg PicturePtr pDstPicture, PixmapPtr pSrc, PixmapPtr pMask, 49650806d53Smrg PixmapPtr pDst) 49750806d53Smrg{ 49850806d53Smrg unsigned int cmd; 49950806d53Smrg unsigned int tex_ctl = 0; 50050806d53Smrg unsigned int threedctl = 0; 50150806d53Smrg PI128_FROM_PIXMAP(pDst); 50250806d53Smrg 50350806d53Smrg /* 2D setup */ 50450806d53Smrg i128SetBufCtrl(pI128, pDst->drawable.bitsPerPixel); 50550806d53Smrg i128SetPlanemask(pI128, -1); 50650806d53Smrg i128SetSourcePixmap(pI128, pSrc); 50750806d53Smrg i128SetDestPixmap(pI128, pDst); 50850806d53Smrg 50950806d53Smrg /* TEX_INV command here? */ 51050806d53Smrg 51150806d53Smrg cmd = CO_TRIAN3D; 51250806d53Smrg CACHED_UPDATE(cmd, CMD); 51350806d53Smrg 51450806d53Smrg /* 3D setup */ 51550806d53Smrg i128SetTexture(pI128, pSrc); 51650806d53Smrg 51750806d53Smrg i128SetAlphaForOp(pI128, op, 1); 51850806d53Smrg 51950806d53Smrg /* it looks pointless to cache these, but we'll need it for DRI */ 52050806d53Smrg 52150806d53Smrg tex_ctl |= TEX_TM; /* enable texture mapping */ 52250806d53Smrg tex_ctl |= TEX_NMG | TEX_NMN; /* nearest interpolation */ 52350806d53Smrg tex_ctl |= 0; /* TEX_RM; / * modulate RGB */ 52450806d53Smrg CACHED_UPDATE(tex_ctl, TEX_CTL); 52550806d53Smrg 52650806d53Smrg threedctl |= 0; /* COMP_TRUE << TCTL_ZOP_SHIFT; / * always pass Z check */ 52750806d53Smrg threedctl |= TCTL_ABS; /* enable alpha blend */ 52850806d53Smrg threedctl |= TCTL_TBS; /* enable texture blend */ 52950806d53Smrg threedctl |= TCTL_RT; /* draw textured rectangle */ 53050806d53Smrg CACHED_UPDATE(threedctl, THREEDCTL); 53150806d53Smrg 53250806d53Smrg return TRUE; 53350806d53Smrg} 53450806d53Smrg 53550806d53Smrgstatic void 53650806d53Smrgi128Composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY, 53750806d53Smrg int dstX, int dstY, int width, int height) 53850806d53Smrg{ 53950806d53Smrg PI128_FROM_PIXMAP(pDst); 54050806d53Smrg 54150806d53Smrg /* 54250806d53Smrg * vertex setup. vertex layout must be: 54350806d53Smrg * V0 V1 54450806d53Smrg * V2 (V3 is implicit) 54550806d53Smrg */ 54650806d53Smrg 54750806d53Smrg pI128->mem.rbase_af[V0_X] = 0.0; 54850806d53Smrg pI128->mem.rbase_af[V0_Y] = 0.0; 54950806d53Smrg pI128->mem.rbase_af[V0_W] = 1.0; 55050806d53Smrg pI128->mem.rbase_af[V0_U] = 0.0; 55150806d53Smrg pI128->mem.rbase_af[V0_V] = 0.0; 55250806d53Smrg pI128->mem.rbase_af[V1_X] = 300.0; 55350806d53Smrg pI128->mem.rbase_af[V1_Y] = 0.0; 55450806d53Smrg pI128->mem.rbase_af[V1_W] = 1.0; 55550806d53Smrg pI128->mem.rbase_af[V1_U] = 1.0; 55650806d53Smrg pI128->mem.rbase_af[V1_V] = 0.0; 55750806d53Smrg pI128->mem.rbase_af[V2_X] = 0.0; 55850806d53Smrg pI128->mem.rbase_af[V2_Y] = 300.0; 55950806d53Smrg pI128->mem.rbase_af[V2_W] = 1.0; 56050806d53Smrg pI128->mem.rbase_af[V2_U] = 0.0; 56150806d53Smrg pI128->mem.rbase_af[V2_V] = 1.0; 56250806d53Smrg 56350806d53Smrg /* and fire */ 56450806d53Smrg pI128->mem.rbase_a[TRIGGER3D] = 1; MB; 56550806d53Smrg 56650806d53Smrg#if 0 56750806d53Smrg static int i = 0; 56850806d53Smrg /* test for raster */ 56950806d53Smrg if (!(i = (i + 1) % 32)) { 57050806d53Smrg ErrorF("Composite test: %d %d %d %d %d %d\n", srcX, srcY, dstX, dstY, 57150806d53Smrg width, height); 57250806d53Smrg } 57350806d53Smrg i128SetRop(pI128, GXxor, 0); 57450806d53Smrg i128ExaBlit(pDst, srcX, srcY, dstX, dstY, width, height); 57550806d53Smrg#endif 57650806d53Smrg} 57750806d53Smrg 57850806d53Smrg#if 0 57950806d53Smrg/* 58050806d53Smrg * upload and download will require a DRM. AGP DMA only works on T2R4, and 58150806d53Smrg * then only for upload. we could probably use memory windows on other chips, 58250806d53Smrg * but those have goofy alignment restrictions and need to be disabled when 58350806d53Smrg * not in use. 58450806d53Smrg */ 58550806d53Smrgstatic Bool 58650806d53Smrgi128DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, char *dst, 58750806d53Smrg int dst_pitch) 58850806d53Smrg{ 58950806d53Smrg} 59050806d53Smrg 59150806d53Smrgstatic Bool 59250806d53Smrgi128UploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, char *src, 59350806d53Smrg int src_pitch) 59450806d53Smrg{ 59550806d53Smrg} 59650806d53Smrg#endif 59750806d53Smrg 59850806d53SmrgBool 59950806d53SmrgI128ExaInit(ScreenPtr pScreen) 60050806d53Smrg{ 60150806d53Smrg ExaDriverPtr pExa; 60250806d53Smrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 60350806d53Smrg I128Ptr pI128 = I128PTR(pScrn); 60450806d53Smrg 60550806d53Smrg if (!(pExa = exaDriverAlloc())) { 60650806d53Smrg pI128->NoAccel = TRUE; 60750806d53Smrg return FALSE; 60850806d53Smrg } 60950806d53Smrg pI128->ExaDriver = pExa; 61050806d53Smrg 61150806d53Smrg pExa->flags = EXA_OFFSCREEN_PIXMAPS | EXA_OFFSCREEN_ALIGN_POT; 61250806d53Smrg pExa->memoryBase = pI128->MemoryPtr; 61350806d53Smrg pExa->memorySize = pI128->MemorySize * 1024; 61450806d53Smrg pExa->offScreenBase = (pScrn->virtualX * pScrn->virtualY) * 61550806d53Smrg (pScrn->bitsPerPixel / 8) + 4096; 61650806d53Smrg /* these two are probably right */ 61750806d53Smrg pExa->pixmapOffsetAlign = 16; 61850806d53Smrg pExa->pixmapPitchAlign = 16; 61950806d53Smrg /* these two are guesses */ 62050806d53Smrg pExa->maxX = 2048; 62150806d53Smrg pExa->maxY = 2048; 62250806d53Smrg 62350806d53Smrg pExa->WaitMarker = i128WaitMarker; 62450806d53Smrg 62550806d53Smrg pExa->PrepareSolid = i128PrepareSolid; 62650806d53Smrg pExa->Solid = i128Solid; 62750806d53Smrg pExa->DoneSolid = i128Done; 62850806d53Smrg 62950806d53Smrg pExa->PrepareCopy = i128PrepareCopy; 63050806d53Smrg pExa->Copy = i128Copy; 63150806d53Smrg pExa->DoneCopy = i128Done; 63250806d53Smrg 63350806d53Smrg if (0 && (pI128->Chipset == PCI_CHIP_I128_T2R || 63450806d53Smrg pI128->Chipset == PCI_CHIP_I128_T2R4)) 63550806d53Smrg { 63650806d53Smrg#if 0 63750806d53Smrg pExa->DownloadFromScreen = i128DownloadFromScreen; 63850806d53Smrg pExa->UploadToScreen = i128UploadToScreen; 63950806d53Smrg#endif 64050806d53Smrg pExa->CheckComposite = i128CheckComposite; 64150806d53Smrg pExa->PrepareComposite = i128PrepareComposite; 64250806d53Smrg pExa->Composite = i128Composite; 64350806d53Smrg pExa->DoneComposite = i128Done; 64450806d53Smrg } 64550806d53Smrg 64650806d53Smrg /* 64750806d53Smrg * XXX much of this is duplicated from the XAA code, but I expect the XAA 64850806d53Smrg * support to disappear eventually. 64950806d53Smrg */ 65050806d53Smrg pI128->buf_ctrl = 0; /* force write */ 65150806d53Smrg i128SetBufCtrl(pI128, pI128->bitsPerPixel); 65250806d53Smrg 65350806d53Smrg /* all of this needs to be properly documented */ 65450806d53Smrg { 65550806d53Smrg pI128->mem.rbase_a[DE_PGE] = 0x00; 65650806d53Smrg pI128->mem.rbase_a[DE_SORG] = pI128->displayOffset; 65750806d53Smrg pI128->mem.rbase_a[DE_DORG] = pI128->displayOffset; 65850806d53Smrg pI128->mem.rbase_a[DE_MSRC] = 0x00; 65950806d53Smrg pI128->mem.rbase_a[DE_WKEY] = 0x00; 66050806d53Smrg pI128->mem.rbase_a[DE_SPTCH] = pI128->mem.rbase_g[DB_PTCH]; 66150806d53Smrg pI128->mem.rbase_a[DE_DPTCH] = pI128->mem.rbase_g[DB_PTCH]; 66250806d53Smrg if (pI128->Chipset == PCI_CHIP_I128_T2R4) 66350806d53Smrg pI128->mem.rbase_a[DE_ZPTCH] = pI128->mem.rbase_g[DB_PTCH]; 66450806d53Smrg pI128->mem.rbase_a[RMSK] = 0x00000000; 66550806d53Smrg pI128->mem.rbase_a[XY4_ZM] = ZOOM_NONE; 66650806d53Smrg pI128->mem.rbase_a[LPAT] = 0xffffffff; /* for lines */ 66750806d53Smrg pI128->mem.rbase_a[PCTRL] = 0x00000000; /* for lines */ 66850806d53Smrg pI128->mem.rbase_a[CLPTL] = 0x00000000; 66950806d53Smrg pI128->mem.rbase_a[CLPBR] = (4095 << 16) | 2047 ; 67050806d53Smrg pI128->mem.rbase_a[ACNTRL] = 0x00000000; 67150806d53Smrg pI128->mem.rbase_a[INTM] = 0x03; 67250806d53Smrg } 67350806d53Smrg 67450806d53Smrg /* need this as a float * for vertex setup */ 67550806d53Smrg pI128->mem.rbase_af = (float *)pI128->mem.rbase_a; 67650806d53Smrg 67750806d53Smrg if (pI128->Debug) { 67850806d53Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "I128ExaInit done\n"); 67950806d53Smrg I128DumpActiveRegisters(pScrn); 68050806d53Smrg } 68150806d53Smrg 68250806d53Smrg return(exaDriverInit(pScreen, pExa)); 68350806d53Smrg} 684