1 /*
2  * Copyright 1997-2003 by Alan Hourihane, North Wales, UK.
3  * Copyright (c) 2006, Jesse Barnes <jbarnes@virtuousgeek.org>
4  *
5  * Permission to use, copy, modify, distribute, and sell this software and its
6  * documentation for any purpose is hereby granted without fee, provided that
7  * the above copyright notice appear in all copies and that both that
8  * copyright notice and this permission notice appear in supporting
9  * documentation, and that the name of the authors not be used in
10  * advertising or publicity pertaining to distribution of the software without
11  * specific, written prior permission.  The authors make no representations
12  * about the suitability of this software for any purpose.  It is provided
13  * "as is" without express or implied warranty.
14  *
15  * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17  * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21  * PERFORMANCE OF THIS SOFTWARE.
22  *
23  * Authors:  Alan Hourihane, <alanh@fairlite.demon.co.uk>
24  *           Jesse Barnes <jbarnes@virtuousgeek.org>
25  *
26  * Trident Blade3D EXA support.
27  * TODO:
28  *   Composite hooks (some ops/arg. combos may not be supported)
29  *   Upload/Download from screen (is this even possible with this chip?)
30  *   Fast mixed directoion Blts
31  */
32 
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
36 
37 #include "xf86.h"
38 #include "xf86_OSproc.h"
39 
40 #include "xf86Pci.h"
41 
42 #include "exa.h"
43 
44 #include "trident.h"
45 #include "trident_regs.h"
46 
47 #include "xaarop.h"
48 
49 #undef REPLICATE
50 #define REPLICATE(r, bpp)					\
51 {								\
52 	if (bpp == 16) {					\
53 		r = ((r & 0xFFFF) << 16) | (r & 0xFFFF);	\
54 	} else							\
55 	if (bpp == 8) { 					\
56 		r &= 0xFF;					\
57 		r |= (r<<8);					\
58 		r |= (r<<16);					\
59 	}							\
60 }
61 
62 static int rop_table[16] =
63 {
64    ROP_0,               /* GXclear */
65    ROP_DSa,             /* GXand */
66    ROP_SDna,            /* GXandReverse */
67    ROP_S,               /* GXcopy */
68    ROP_DSna,            /* GXandInverted */
69    ROP_D,               /* GXnoop */
70    ROP_DSx,             /* GXxor */
71    ROP_DSo,             /* GXor */
72    ROP_DSon,            /* GXnor */
73    ROP_DSxn,            /* GXequiv */
74    ROP_Dn,              /* GXinvert*/
75    ROP_SDno,            /* GXorReverse */
76    ROP_Sn,              /* GXcopyInverted */
77    ROP_DSno,            /* GXorInverted */
78    ROP_DSan,            /* GXnand */
79    ROP_1                /* GXset */
80 };
81 
GetCopyROP(int rop)82 static int GetCopyROP(int rop)
83 {
84     return rop_table[rop];
85 }
86 
GetDepth(int depth)87 static unsigned long GetDepth(int depth)
88 {
89     unsigned long ret;
90 
91     switch (depth) {
92     case 8:
93 	ret = 0;
94 	break;
95     case 15:
96 	ret = 5UL << 29; /* 555 */
97     case 16:
98 	ret = 1UL << 29; /* 565 */
99 	break;
100     case 32:
101 	ret = 2UL << 29;
102 	break;
103     default:
104 	ret = 0;
105 	break;
106     }
107     return ret;
108 }
109 
PrepareSolid(PixmapPtr pPixmap,int rop,Pixel planemask,Pixel color)110 static Bool PrepareSolid(PixmapPtr pPixmap, int rop, Pixel planemask,
111 			 Pixel color)
112 {
113     TRIDENTPtr pTrident =
114 	TRIDENTPTR(xf86ScreenToScrn(pPixmap->drawable.pScreen));
115 
116     REPLICATE(color, pPixmap->drawable.bitsPerPixel);
117     BLADE_OUT(GER_FGCOLOR, color);
118     BLADE_OUT(GER_ROP, GetCopyROP(rop));
119     pTrident->BltScanDirection = 0;
120 
121     return TRUE;
122 }
123 
Solid(PixmapPtr pPixmap,int x,int y,int x2,int y2)124 static void Solid(PixmapPtr pPixmap, int x, int y, int x2, int y2)
125 {
126     TRIDENTPtr pTrident =
127 	TRIDENTPTR(xf86ScreenToScrn(pPixmap->drawable.pScreen));
128     int dst_stride = (pPixmap->drawable.width + 7) / 8;
129     int dst_off = exaGetPixmapOffset(pPixmap) / 8;
130 
131     BLADE_OUT(GER_DSTBASE0, GetDepth(pPixmap->drawable.bitsPerPixel) |
132 	      dst_stride << 20 | dst_off);
133 
134     BLADE_OUT(GER_DRAW_CMD, GER_OP_LINE | pTrident->BltScanDirection |
135 	      GER_DRAW_SRC_COLOR | GER_ROP_ENABLE | GER_SRC_CONST);
136 
137     BLADE_OUT(GER_DST1, y << 16 | x);
138     BLADE_OUT(GER_DST2, ((y2 - 1) & 0xfff) << 16 | ((x2 - 1) & 0xfff));
139 }
140 
DoneSolid(PixmapPtr pPixmap)141 static void DoneSolid(PixmapPtr pPixmap)
142 {
143 }
144 
PrepareCopy(PixmapPtr pSrcPixmap,PixmapPtr pDstPixmap,int xdir,int ydir,int alu,Pixel planemask)145 static Bool PrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap,
146 			int xdir, int ydir, int alu, Pixel planemask)
147 {
148     TRIDENTPtr pTrident =
149 	TRIDENTPTR(xf86ScreenToScrn(pSrcPixmap->drawable.pScreen));
150     int src_stride = (pSrcPixmap->drawable.width + 7) / 8;
151     int src_off = exaGetPixmapOffset(pSrcPixmap) / 8;
152     int dst_stride = (pDstPixmap->drawable.width + 7) / 8;
153     int dst_off = exaGetPixmapOffset(pDstPixmap) / 8;
154 
155     pTrident->BltScanDirection = 0;
156 
157     REPLICATE(planemask, pSrcPixmap->drawable.bitsPerPixel);
158     if (planemask != (unsigned int)-1) {
159 	BLADE_OUT(GER_BITMASK, ~planemask);
160 	pTrident->BltScanDirection |= 1 << 5;
161     }
162 
163     BLADE_OUT(GER_SRCBASE0, GetDepth(pSrcPixmap->drawable.bitsPerPixel) |
164 	      src_stride << 20 | src_off);
165 
166     BLADE_OUT(GER_DSTBASE0, GetDepth(pDstPixmap->drawable.bitsPerPixel) |
167 	      dst_stride << 20 | dst_off);
168 
169     if ((xdir < 0) || (ydir < 0))
170 	pTrident->BltScanDirection |= 1 << 1;
171 
172     BLADE_OUT(GER_ROP, GetCopyROP(alu));
173 
174     return TRUE;
175 }
176 
Copy(PixmapPtr pDstPixmap,int x1,int y1,int x2,int y2,int w,int h)177 static void Copy(PixmapPtr pDstPixmap, int x1, int y1, int x2,
178 		 int y2, int w, int h)
179 {
180     TRIDENTPtr pTrident =
181 	TRIDENTPTR(xf86ScreenToScrn(pDstPixmap->drawable.pScreen));
182 
183     BLADE_OUT(GER_DRAW_CMD, GER_OP_BLT_HOST | GER_DRAW_SRC_COLOR |
184 	      GER_ROP_ENABLE | GER_BLT_SRC_FB | pTrident->BltScanDirection);
185 
186     if (pTrident->BltScanDirection) {
187 	BLADE_OUT(GER_SRC1, (y1 + h - 1) << 16 | (x1 + w - 1));
188 	BLADE_OUT(GER_SRC2, y1 << 16 | x1);
189 	BLADE_OUT(GER_DST1, (y2 + h - 1) << 16 | (x2 + w - 1));
190 	BLADE_OUT(GER_DST2, (y2 & 0xfff) << 16 | (x2 & 0xfff));
191     } else {
192 	BLADE_OUT(GER_SRC1, y1 << 16 | x1);
193 	BLADE_OUT(GER_SRC2, (y1 + h - 1) << 16 | (x1 + w - 1));
194 	BLADE_OUT(GER_DST1, y2 << 16 | x2);
195 	BLADE_OUT(GER_DST2, (((y2 + h - 1) & 0xfff) << 16 |
196 			     ((x2 +w - 1) & 0xfff)));
197     }
198 }
199 
DoneCopy(PixmapPtr pDstPixmap)200 static void DoneCopy(PixmapPtr pDstPixmap)
201 {
202 }
203 
204 /* Composite comes later (if at all) */
CheckComposite(int op,PicturePtr pSrcPicture,PicturePtr pMaskPicture,PicturePtr pDstPicture)205 static Bool CheckComposite(int op, PicturePtr pSrcPicture,
206 			   PicturePtr pMaskPicture, PicturePtr pDstPicture)
207 {
208     return 0;
209 }
210 
PrepareComposite(int op,PicturePtr pSrcPicture,PicturePtr pMaskPicture,PicturePtr pDstPicture,PixmapPtr pSrc,PixmapPtr pMask,PixmapPtr pDst)211 static Bool PrepareComposite(int op, PicturePtr pSrcPicture,
212 			     PicturePtr pMaskPicture, PicturePtr pDstPicture,
213 			     PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
214 {
215     return 0;
216 }
217 
Composite(PixmapPtr pDst,int srcX,int srcY,int maskX,int maskY,int dstX,int dstY,int width,int height)218 static void Composite(PixmapPtr pDst, int srcX, int srcY, int maskX,
219 		      int maskY, int dstX, int dstY, int width,
220 		      int height)
221 {
222 }
223 
DoneComposite(PixmapPtr pDst)224 static void DoneComposite(PixmapPtr pDst)
225 {
226 }
227 
MarkSync(ScreenPtr pScreen)228 static int MarkSync(ScreenPtr pScreen)
229 {
230     return 0;
231 }
232 
WaitMarker(ScreenPtr pScreen,int marker)233 static void WaitMarker(ScreenPtr pScreen, int marker)
234 {
235     TRIDENTPtr pTrident = TRIDENTPTR(xf86ScreenToScrn(pScreen));
236     int busy;
237     int cnt = 10000000;
238 
239     BLADE_OUT(GER_PATSTYLE, 0); /* Clear pattern & style first? */
240 
241     BLADEBUSY(busy);
242     while (busy != 0) {
243 	if (--cnt < 0) {
244 	    ErrorF("GE timeout\n");
245 	    BLADE_OUT(GER_CONTROL, GER_CTL_RESET);
246 	    BLADE_OUT(GER_CONTROL, GER_CTL_RESUME);
247 	    break;
248 	}
249     	BLADEBUSY(busy);
250     }
251 }
252 
BladeInitializeAccelerator(ScrnInfoPtr pScrn)253 static void BladeInitializeAccelerator(ScrnInfoPtr pScrn)
254 {
255     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
256 
257     BLADE_OUT(GER_DSTBASE0, 0);
258     BLADE_OUT(GER_DSTBASE1, 0);
259     BLADE_OUT(GER_DSTBASE2, 0);
260     BLADE_OUT(GER_DSTBASE3, 0);
261     BLADE_OUT(GER_SRCBASE0, 0);
262     BLADE_OUT(GER_SRCBASE1, 0);
263     BLADE_OUT(GER_SRCBASE2, 0);
264     BLADE_OUT(GER_SRCBASE3, 0);
265     BLADE_OUT(GER_PATSTYLE, 0);
266 }
267 
BladeExaInit(ScreenPtr pScreen)268 Bool BladeExaInit(ScreenPtr pScreen)
269 {
270     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
271     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
272     ExaDriverPtr ExaDriver;
273 
274     if (pTrident->NoAccel)
275 	return FALSE;
276 
277     if (!(ExaDriver = exaDriverAlloc())) {
278         pTrident->NoAccel = TRUE;
279         return FALSE;
280     }
281 
282     ExaDriver->exa_major = 2;
283     ExaDriver->exa_minor = 0;
284 
285     pTrident->EXADriverPtr = ExaDriver;
286 
287     pTrident->InitializeAccelerator = BladeInitializeAccelerator;
288     BladeInitializeAccelerator(pScrn);
289 
290     ExaDriver->memoryBase = pTrident->FbBase;
291     ExaDriver->memorySize = pScrn->videoRam * 1024;
292 
293     ExaDriver->offScreenBase = pScrn->displayWidth * pScrn->virtualY *
294 	((pScrn->bitsPerPixel + 7) / 8);
295 
296     if(ExaDriver->memorySize > ExaDriver->offScreenBase)
297 	ExaDriver->flags |= EXA_OFFSCREEN_PIXMAPS;
298     else {
299 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Not enough video RAM for "
300 		   "offscreen memory manager. Xv disabled\n");
301 	/* disable Xv here... */
302     }
303 
304     ExaDriver->pixmapOffsetAlign = 32;
305     ExaDriver->pixmapPitchAlign = 32;
306     ExaDriver->maxX = 2047;
307     ExaDriver->maxY = 2047;
308 
309     ExaDriver->flags |= EXA_TWO_BITBLT_DIRECTIONS;
310 
311     ExaDriver->MarkSync = MarkSync;
312     ExaDriver->WaitMarker = WaitMarker;
313 
314     /* Solid fill & copy, the bare minimum */
315     ExaDriver->PrepareSolid = PrepareSolid;
316     ExaDriver->Solid = Solid;
317     ExaDriver->DoneSolid = DoneSolid;
318     ExaDriver->PrepareCopy = PrepareCopy;
319     ExaDriver->Copy = Copy;
320     ExaDriver->DoneCopy = DoneCopy;
321 
322     /* Composite not done yet */
323 
324     return exaDriverInit(pScreen, ExaDriver);
325 }
326