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