i740_accel.c revision 301ea0f4
1
2/**************************************************************************
3
4Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
5All Rights Reserved.
6
7Permission is hereby granted, free of charge, to any person obtaining a
8copy of this software and associated documentation files (the
9"Software"), to deal in the Software without restriction, including
10without limitation the rights to use, copy, modify, merge, publish,
11distribute, sub license, and/or sell copies of the Software, and to
12permit persons to whom the Software is furnished to do so, subject to
13the following conditions:
14
15The above copyright notice and this permission notice (including the
16next paragraph) shall be included in all copies or substantial portions
17of the Software.
18
19THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
23ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
27**************************************************************************/
28/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i740/i740_accel.c,v 1.6 2002/01/25 21:56:02 tsi Exp $ */
29
30/*
31 * Authors:
32 *   Daryll Strauss <daryll@precisioninsight.com>
33 *
34 */
35
36#ifdef HAVE_CONFIG_H
37#include "config.h"
38#endif
39
40#include "xf86.h"
41#include "xf86_OSproc.h"
42
43#include "compiler.h"
44
45#include "xf86Pci.h"
46#include "xf86PciInfo.h"
47
48#include "xaa.h"
49#include "vgaHW.h"
50
51#include "xf86xv.h"
52#include "i740.h"
53
54static unsigned int i740Rop[16] = {
55    0x00, /* GXclear      */
56    0x88, /* GXand        */
57    0x44, /* GXandReverse */
58    0xCC, /* GXcopy       */
59    0x22, /* GXandInvert  */
60    0xAA, /* GXnoop       */
61    0x66, /* GXxor        */
62    0xEE, /* GXor         */
63    0x11, /* GXnor        */
64    0x99, /* GXequiv      */
65    0x55, /* GXinvert     */
66    0xDD, /* GXorReverse  */
67    0x33, /* GXcopyInvert */
68    0xBB, /* GXorInverted */
69    0x77, /* GXnand       */
70    0xFF  /* GXset        */
71};
72
73static unsigned int i740PatternRop[16] = {
74    0x00, /* GXclear      */
75    0xA0, /* GXand        */
76    0x50, /* GXandReverse */
77    0xF0, /* GXcopy       */
78    0x0A, /* GXandInvert  */
79    0xAA, /* GXnoop       */
80    0x5A, /* GXxor        */
81    0xFA, /* GXor         */
82    0x05, /* GXnor        */
83    0xA5, /* GXequiv      */
84    0x55, /* GXinvert     */
85    0xF5, /* GXorReverse  */
86    0x0F, /* GXcopyInvert */
87    0xAF, /* GXorInverted */
88    0x5F, /* GXnand       */
89    0xFF  /* GXset        */
90};
91
92static void I740SyncPIO(ScrnInfoPtr pScrn);
93static void I740SyncMMIO(ScrnInfoPtr pScrn);
94static void I740SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop,
95				      unsigned int planemask);
96static void I740SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y,
97					int w, int h);
98static void I740SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir,
99					   int ydir, int rop,
100					   unsigned int planemask,
101					   int transparency_color);
102static void I740SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1,
103					     int x2, int y2, int w, int h);
104static void I740SetupForMono8x8PatternFill(ScrnInfoPtr pScrn,
105					   int pattx, int patty,
106					   int fg, int bg, int rop,
107					   unsigned int planemask);
108static void I740SubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn,
109						  int pattx, int patty,
110						  int x, int y, int w, int h);
111#if 0
112static void I740SetupForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
113						   int bg, int fg, int rop,
114						   unsigned int planemask);
115static void I740SubsequentCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
116						     int x, int y, int w, int h,
117						     int skipleft);
118#endif
119/*
120 * The following function sets up the supported acceleration. Call it
121 * from the FbInit() function in the SVGA driver, or before ScreenInit
122 * in a monolithic server.
123 */
124Bool
125I740AccelInit(ScreenPtr pScreen) {
126  XAAInfoRecPtr infoPtr;
127  ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
128  I740Ptr pI740 = I740PTR(pScrn);
129
130  pI740->AccelInfoRec = infoPtr = XAACreateInfoRec();
131  if (!infoPtr) return FALSE;
132
133  if (pScrn->bitsPerPixel == 32) {
134    infoPtr->Flags = 0; /* Disables all acceleration */
135    return TRUE;;
136  }
137
138  infoPtr->Flags = PIXMAP_CACHE | OFFSCREEN_PIXMAPS | LINEAR_FRAMEBUFFER;
139
140  /* Sync */
141  if (pI740->usePIO)
142    infoPtr->Sync = I740SyncPIO;
143  else
144    infoPtr->Sync = I740SyncMMIO;
145
146  infoPtr->CachePixelGranularity=8/pI740->cpp;
147
148  /* Solid filled rectangles */
149  infoPtr->SolidFillFlags = NO_PLANEMASK;
150  infoPtr->SetupForSolidFill = I740SetupForSolidFill;
151  infoPtr->SubsequentSolidFillRect = I740SubsequentSolidFillRect;
152
153  /* Screen to screen copy */
154  infoPtr->ScreenToScreenCopyFlags = (NO_PLANEMASK | NO_TRANSPARENCY);
155  infoPtr->SetupForScreenToScreenCopy = I740SetupForScreenToScreenCopy;
156  infoPtr->SubsequentScreenToScreenCopy = I740SubsequentScreenToScreenCopy;
157
158  /* 8x8 pattern fills */
159  infoPtr->SetupForMono8x8PatternFill = I740SetupForMono8x8PatternFill;
160  infoPtr->SubsequentMono8x8PatternFillRect = I740SubsequentMono8x8PatternFillRect;
161  infoPtr->Mono8x8PatternFillFlags = NO_PLANEMASK | HARDWARE_PATTERN_SCREEN_ORIGIN |
162    BIT_ORDER_IN_BYTE_MSBFIRST;
163
164  /* CPU to screen color expansion */
165  /* Currently XAA is limited to only DWORD padding.  The 3.3 driver
166   * uses NO_PAD scanlines b/c of problems with using the chip in
167   * DWORD mode. Once other padding modes are available in XAA this
168   * Code can be turned back on.
169   */
170#if 0
171#ifndef ALLOW_PCI_COLOR_EXP
172  if (pI740->Chipset != PCI_CHIP_I740_PCI) {
173#endif
174    /*
175     * Currently, we are not properly able to read the bitblt engine
176     * busy bit on the PCI i740 card.  When we are able to do so, we
177     * can re-enable color expansion.
178     */
179    infoPtr->CPUToScreenColorExpandFillFlags =
180       					  NO_PLANEMASK |
181#ifdef USE_DWORD_COLOR_EXP
182					  SCANLINE_PAD_DWORD |
183#endif
184					  CPU_TRANSFER_PAD_QWORD |
185					  SYNC_AFTER_COLOR_EXPAND |
186					  BIT_ORDER_IN_BYTE_MSBFIRST;
187    infoPtr->ColorExpandBase = (unsigned char *)(pI740->MMIOBase + BLTDATA);
188    infoPtr->ColorExpandRange = 0x10000;
189    infoPtr->SetupForCPUToScreenColorExpandFill = I740SetupForCPUToScreenColorExpandFill;
190    infoPtr->SubsequentCPUToScreenColorExpandFill = I740SubsequentCPUToScreenColorExpandFill;
191#ifndef ALLOW_PCI_COLOR_EXP
192    }
193#endif
194#endif
195  return XAAInit(pScreen, infoPtr);
196}
197
198static void
199I740SyncPIO(ScrnInfoPtr pScrn) {
200  WAIT_ENGINE_IDLE_PIO();
201}
202
203static void
204I740SyncMMIO(ScrnInfoPtr pScrn) {
205  I740Ptr pI740;
206
207  pI740 = I740PTR(pScrn);
208  WAIT_ENGINE_IDLE_MMIO();
209}
210
211static void
212I740SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop,
213		      unsigned int planemask) {
214  I740Ptr pI740;
215
216  pI740 = I740PTR(pScrn);
217
218  pI740->bltcmd.BR00 = ((pScrn->displayWidth * pI740->cpp) << 16) |
219    (pScrn->displayWidth * pI740->cpp);
220  pI740->bltcmd.BR01 = color;
221  pI740->bltcmd.BR04 = SOLID_PAT_SELECT | PAT_IS_MONO | i740PatternRop[rop];
222}
223
224static void
225I740SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h) {
226  I740Ptr pI740;
227
228  pI740 = I740PTR(pScrn);
229  WAIT_LP_FIFO(12);
230  OUTREG(LP_FIFO, 0x6000000A);
231  OUTREG(LP_FIFO, pI740->bltcmd.BR00);
232  OUTREG(LP_FIFO, pI740->bltcmd.BR01);
233  OUTREG(LP_FIFO, 0x00000000);
234  OUTREG(LP_FIFO, 0x00000000);
235  OUTREG(LP_FIFO, pI740->bltcmd.BR04);
236  OUTREG(LP_FIFO, 0x00000000);
237  OUTREG(LP_FIFO, 0x00000000);
238  OUTREG(LP_FIFO, (y * pScrn->displayWidth + x) * pI740->cpp);
239  OUTREG(LP_FIFO, 0x00000000);
240  OUTREG(LP_FIFO, 0x00000000);
241  OUTREG(LP_FIFO, (h << 16) | (w * pI740->cpp));
242}
243
244static void
245I740SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, int rop,
246			       unsigned int planemask, int transparency_color)
247{
248  I740Ptr pI740;
249
250  pI740 = I740PTR(pScrn);
251  pI740->bltcmd.BR00 = (((pScrn->displayWidth * pI740->cpp) << 16) |
252			(pScrn->displayWidth * pI740->cpp));
253
254  pI740->bltcmd.BR04 = SRC_IS_IN_COLOR | SRC_USE_SRC_ADDR | i740Rop[rop];
255  if (xdir == -1)
256    pI740->bltcmd.BR04 |= BLT_RIGHT_TO_LEFT;
257  else
258    pI740->bltcmd.BR04 |= BLT_LEFT_TO_RIGHT;
259
260  if (ydir == -1)
261    pI740->bltcmd.BR04 |= BLT_BOT_TO_TOP;
262  else
263    pI740->bltcmd.BR04 |= BLT_TOP_TO_BOT;
264
265    pI740->bltcmd.BR01 = 0x00000000;
266
267}
268
269static void
270I740SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1,
271				 int x2, int y2, int w, int h) {
272  I740Ptr pI740;
273
274  pI740 = I740PTR(pScrn);
275  if (pI740->bltcmd.BR04 & BLT_BOT_TO_TOP) {
276    pI740->bltcmd.BR06 = (y1 + h - 1) *
277      pScrn->displayWidth * pI740->cpp;
278    pI740->bltcmd.BR07 = (y2 + h - 1) *
279      pScrn->displayWidth * pI740->cpp;
280    } else {
281      pI740->bltcmd.BR06 = y1 * pScrn->displayWidth * pI740->cpp;
282      pI740->bltcmd.BR07 = y2 * pScrn->displayWidth * pI740->cpp;
283    }
284
285  if (pI740->bltcmd.BR04 & BLT_RIGHT_TO_LEFT) {
286    pI740->bltcmd.BR06 += (x1 + w - 1) * pI740->cpp + pI740->cpp - 1;
287    pI740->bltcmd.BR07 += (x2 + w - 1) * pI740->cpp + pI740->cpp - 1;
288  } else {
289    pI740->bltcmd.BR06 += x1 * pI740->cpp;
290    pI740->bltcmd.BR07 += x2 * pI740->cpp;
291  }
292
293  WAIT_LP_FIFO(12);
294  OUTREG(LP_FIFO, 0x6000000A);
295  OUTREG(LP_FIFO, pI740->bltcmd.BR00);
296  OUTREG(LP_FIFO, pI740->bltcmd.BR01);
297  OUTREG(LP_FIFO, 0x00000000);
298  OUTREG(LP_FIFO, 0x00000000);
299  OUTREG(LP_FIFO, pI740->bltcmd.BR04);
300  OUTREG(LP_FIFO, 0x00000000);
301  OUTREG(LP_FIFO, pI740->bltcmd.BR06);
302  OUTREG(LP_FIFO, pI740->bltcmd.BR07);
303  OUTREG(LP_FIFO, 0x00000000);
304  OUTREG(LP_FIFO, 0x00000000);
305  OUTREG(LP_FIFO, (h << 16) | (w * pI740->cpp));
306}
307
308static void
309I740SetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int pattx, int patty,
310				int fg, int bg, int rop,
311				unsigned int planemask) {
312  I740Ptr pI740;
313
314  pI740 = I740PTR(pScrn);
315  pI740->bltcmd.BR00 = ((pScrn->displayWidth * pI740->cpp) << 16) |
316			(pScrn->displayWidth * pI740->cpp);
317
318  pI740->bltcmd.BR01 = bg;
319  pI740->bltcmd.BR02 = fg;
320
321  pI740->bltcmd.BR04 = PAT_IS_MONO | i740PatternRop[rop];
322  if (bg == -1) pI740->bltcmd.BR04 |= MONO_PAT_TRANSP;
323
324  pI740->bltcmd.BR05 = (pattx + patty * pScrn->displayWidth) * pI740->cpp;
325}
326
327static void
328I740SubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, int pattx, int patty,
329				     int x, int y, int w, int h) {
330  I740Ptr pI740;
331
332  pI740 = I740PTR(pScrn);
333  WAIT_LP_FIFO(12);
334  OUTREG(LP_FIFO, 0x6000000A);
335  OUTREG(LP_FIFO, pI740->bltcmd.BR00);
336  OUTREG(LP_FIFO, pI740->bltcmd.BR01);
337  OUTREG(LP_FIFO, pI740->bltcmd.BR02);
338  OUTREG(LP_FIFO, 0x00000000);
339  OUTREG(LP_FIFO, pI740->bltcmd.BR04 | ((y<<20) & PAT_VERT_ALIGN));
340  OUTREG(LP_FIFO, pI740->bltcmd.BR05);
341  OUTREG(LP_FIFO, 0x00000000);
342  OUTREG(LP_FIFO, (y * pScrn->displayWidth + x) * pI740->cpp);
343  OUTREG(LP_FIFO, 0x00000000);
344  OUTREG(LP_FIFO, 0x00000000);
345  OUTREG(LP_FIFO, (h << 16) | (w * pI740->cpp));
346}
347#if 0
348static void
349I740SetupForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, int bg, int fg,
350				       int rop, unsigned int planemask) {
351  I740Ptr pI740;
352
353  pI740 = I740PTR(pScrn);
354  pI740->bltcmd.BR00 = (pScrn->displayWidth * pI740->cpp) << 16;
355  pI740->bltcmd.BR01 = bg;
356  pI740->bltcmd.BR02 = fg;
357#ifdef USE_DWORD_COLOR_EXP
358  pI740->bltcmd.BR03 = MONO_DWORD_ALIGN | MONO_USE_COLEXP;
359#else
360  pI740->bltcmd.BR03 = MONO_BIT_ALIGN | MONO_USE_COLEXP;
361#endif
362  pI740->bltcmd.BR04 = SRC_IS_MONO | SRC_USE_BLTDATA | i740Rop[rop];
363  if (bg == -1) pI740->bltcmd.BR04 |= MONO_SRC_TRANSP;
364}
365
366static void
367I740SubsequentCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, int x, int y,
368				     int w, int h, int skipleft) {
369  I740Ptr pI740;
370
371  pI740 = I740PTR(pScrn);
372  pI740->AccelInfoRec->Sync(pScrn);
373  OUTREG(LP_FIFO, 0x6000000A);
374  OUTREG(LP_FIFO, pI740->bltcmd.BR00);
375  OUTREG(LP_FIFO, pI740->bltcmd.BR01);
376  OUTREG(LP_FIFO, pI740->bltcmd.BR02);
377  OUTREG(LP_FIFO, pI740->bltcmd.BR03 | (skipleft & MONO_SRC_LEFT_CLIP));
378  OUTREG(LP_FIFO, pI740->bltcmd.BR04);
379  OUTREG(LP_FIFO, 0x00000000);
380  OUTREG(LP_FIFO, 0x00000000);
381  OUTREG(LP_FIFO, (y * pScrn->displayWidth + x) * pI740->cpp);
382  OUTREG(LP_FIFO, 0x00000000);
383  OUTREG(LP_FIFO, 0x00000000);
384#ifdef USE_DWORD_COLOR_EXP
385  /*
386   * This extra wait is necessary to keep the bitblt engine from
387   * locking up, but I am not sure why it is needed.  If we take it
388   * out, "x11perf -copyplane10" will lock the bitblt engine.  When
389   * the bitblt engine is locked, it is waiting for mono data to be
390   * written to the BLTDATA region, which seems to imply that some of
391   * the data that was written was lost.  This might be fixed by
392   * BLT_SKEW changes.  Update: The engine still locks up with this
393   * extra wait.  More investigation (and time) is needed.
394   */
395  WAIT_BLT_IDLE();
396#endif
397  OUTREG(LP_FIFO, (h << 16) | (w * pI740->cpp));
398}
399#endif
400