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