103b705cfSriastradh
203b705cfSriastradh/**************************************************************************
303b705cfSriastradh
403b705cfSriastradhCopyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
503b705cfSriastradhAll Rights Reserved.
603b705cfSriastradh
703b705cfSriastradhPermission is hereby granted, free of charge, to any person obtaining a
803b705cfSriastradhcopy of this software and associated documentation files (the
903b705cfSriastradh"Software"), to deal in the Software without restriction, including
1003b705cfSriastradhwithout limitation the rights to use, copy, modify, merge, publish,
1103b705cfSriastradhdistribute, sub license, and/or sell copies of the Software, and to
1203b705cfSriastradhpermit persons to whom the Software is furnished to do so, subject to
1303b705cfSriastradhthe following conditions:
1403b705cfSriastradh
1503b705cfSriastradhThe above copyright notice and this permission notice (including the
1603b705cfSriastradhnext paragraph) shall be included in all copies or substantial portions
1703b705cfSriastradhof the Software.
1803b705cfSriastradh
1903b705cfSriastradhTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
2003b705cfSriastradhOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2103b705cfSriastradhMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
2203b705cfSriastradhIN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
2303b705cfSriastradhANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
2403b705cfSriastradhTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
2503b705cfSriastradhSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2603b705cfSriastradh
2703b705cfSriastradh**************************************************************************/
2803b705cfSriastradh
2903b705cfSriastradh#ifdef HAVE_CONFIG_H
3003b705cfSriastradh#include "config.h"
3103b705cfSriastradh#endif
3203b705cfSriastradh
3303b705cfSriastradh/*
3403b705cfSriastradh * Authors:
3503b705cfSriastradh *   Keith Whitwell <keith@tungstengraphics.com>
3603b705cfSriastradh *
3703b705cfSriastradh */
3803b705cfSriastradh
3942542f5fSchristos#include "xorg-server.h"
4003b705cfSriastradh#include "xf86.h"
4103b705cfSriastradh#include "xaarop.h"
4203b705cfSriastradh#include "i810.h"
4303b705cfSriastradh
4403b705cfSriastradhconst int I810CopyROP[16] = {
4503b705cfSriastradh	ROP_0,			/* GXclear */
4603b705cfSriastradh	ROP_DSa,		/* GXand */
4703b705cfSriastradh	ROP_SDna,		/* GXandReverse */
4803b705cfSriastradh	ROP_S,			/* GXcopy */
4903b705cfSriastradh	ROP_DSna,		/* GXandInverted */
5003b705cfSriastradh	ROP_D,			/* GXnoop */
5103b705cfSriastradh	ROP_DSx,		/* GXxor */
5203b705cfSriastradh	ROP_DSo,		/* GXor */
5303b705cfSriastradh	ROP_DSon,		/* GXnor */
5403b705cfSriastradh	ROP_DSxn,		/* GXequiv */
5503b705cfSriastradh	ROP_Dn,			/* GXinvert */
5603b705cfSriastradh	ROP_SDno,		/* GXorReverse */
5703b705cfSriastradh	ROP_Sn,			/* GXcopyInverted */
5803b705cfSriastradh	ROP_DSno,		/* GXorInverted */
5903b705cfSriastradh	ROP_DSan,		/* GXnand */
6003b705cfSriastradh	ROP_1			/* GXset */
6103b705cfSriastradh};
6203b705cfSriastradh
6303b705cfSriastradhconst int I810PatternROP[16] = {
6403b705cfSriastradh	ROP_0,
6503b705cfSriastradh	ROP_DPa,
6603b705cfSriastradh	ROP_PDna,
6703b705cfSriastradh	ROP_P,
6803b705cfSriastradh	ROP_DPna,
6903b705cfSriastradh	ROP_D,
7003b705cfSriastradh	ROP_DPx,
7103b705cfSriastradh	ROP_DPo,
7203b705cfSriastradh	ROP_DPon,
7303b705cfSriastradh	ROP_PDxn,
7403b705cfSriastradh	ROP_Dn,
7503b705cfSriastradh	ROP_PDno,
7603b705cfSriastradh	ROP_Pn,
7703b705cfSriastradh	ROP_DPno,
7803b705cfSriastradh	ROP_DPan,
7903b705cfSriastradh	ROP_1
8003b705cfSriastradh};
8103b705cfSriastradh
8203b705cfSriastradhint
8303b705cfSriastradhI810WaitLpRing(ScrnInfoPtr pScrn, int n, int timeout_millis)
8403b705cfSriastradh{
8503b705cfSriastradh   I810Ptr pI810 = I810PTR(pScrn);
8603b705cfSriastradh   I810RingBuffer *ring = pI810->LpRing;
8703b705cfSriastradh   int iters = 0;
8803b705cfSriastradh   int start = 0;
8903b705cfSriastradh   int now = 0;
9003b705cfSriastradh   int last_head = 0;
9103b705cfSriastradh   int first = 0;
9203b705cfSriastradh
9303b705cfSriastradh   /* If your system hasn't moved the head pointer in 2 seconds, I'm going to
9403b705cfSriastradh    * call it crashed.
9503b705cfSriastradh    */
9603b705cfSriastradh   if (timeout_millis == 0)
9703b705cfSriastradh      timeout_millis = 2000;
9803b705cfSriastradh
9903b705cfSriastradh   if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) {
10003b705cfSriastradh      ErrorF("I810WaitLpRing %d\n", n);
10103b705cfSriastradh      first = GetTimeInMillis();
10203b705cfSriastradh   }
10303b705cfSriastradh
10403b705cfSriastradh   while (ring->space < n) {
10503b705cfSriastradh      ring->head = INREG(LP_RING + RING_HEAD) & HEAD_ADDR;
10603b705cfSriastradh      ring->space = ring->head - (ring->tail + 8);
10703b705cfSriastradh
10803b705cfSriastradh      if (ring->space < 0)
10903b705cfSriastradh	 ring->space += ring->mem.Size;
11003b705cfSriastradh
11103b705cfSriastradh      iters++;
11203b705cfSriastradh      now = GetTimeInMillis();
11303b705cfSriastradh      if (start == 0 || now < start || ring->head != last_head) {
11403b705cfSriastradh	 if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
11503b705cfSriastradh	    if (now > start)
11603b705cfSriastradh	       ErrorF("space: %d wanted %d\n", ring->space, n);
11703b705cfSriastradh	 start = now;
11803b705cfSriastradh	 last_head = ring->head;
11903b705cfSriastradh      } else if (now - start > timeout_millis) {
12003b705cfSriastradh	 ErrorF("Error in I810WaitLpRing(), now is %d, start is %d\n", now,
12103b705cfSriastradh		start);
12203b705cfSriastradh	 I810PrintErrorState(pScrn);
12303b705cfSriastradh	 ErrorF("space: %d wanted %d\n", ring->space, n);
12403b705cfSriastradh#ifdef HAVE_DRI1
12503b705cfSriastradh	 if (pI810->directRenderingEnabled) {
12603b705cfSriastradh	    DRIUnlock(xf86ScrnToScreen(pScrn));
12703b705cfSriastradh	    DRICloseScreen(xf86ScrnToScreen(pScrn));
12803b705cfSriastradh	 }
12903b705cfSriastradh#endif
13003b705cfSriastradh#if HAVE_XAA_H
13103b705cfSriastradh	 pI810->AccelInfoRec = NULL;	/* Stops recursive behavior */
13203b705cfSriastradh#endif
13303b705cfSriastradh	 FatalError("lockup\n");
13403b705cfSriastradh      }
13503b705cfSriastradh
13603b705cfSriastradh      DELAY(10000);
13703b705cfSriastradh   }
13803b705cfSriastradh
13903b705cfSriastradh   if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) {
14003b705cfSriastradh      now = GetTimeInMillis();
14103b705cfSriastradh      if (now - first) {
14203b705cfSriastradh	 ErrorF("Elapsed %d ms\n", now - first);
14303b705cfSriastradh	 ErrorF("space: %d wanted %d\n", ring->space, n);
14403b705cfSriastradh      }
14503b705cfSriastradh   }
14603b705cfSriastradh
14703b705cfSriastradh   return iters;
14803b705cfSriastradh}
14903b705cfSriastradh
15003b705cfSriastradhvoid
15103b705cfSriastradhI810Sync(ScrnInfoPtr pScrn)
15203b705cfSriastradh{
15303b705cfSriastradh   I810Ptr pI810 = I810PTR(pScrn);
15403b705cfSriastradh
15503b705cfSriastradh   if (I810_DEBUG & (DEBUG_VERBOSE_ACCEL | DEBUG_VERBOSE_SYNC))
15603b705cfSriastradh      ErrorF("I810Sync\n");
15703b705cfSriastradh
15803b705cfSriastradh#ifdef HAVE_DRI1
15903b705cfSriastradh   /* VT switching tries to do this.
16003b705cfSriastradh    */
16103b705cfSriastradh   if (!pI810->LockHeld && pI810->directRenderingEnabled) {
16203b705cfSriastradh      return;
16303b705cfSriastradh   }
16403b705cfSriastradh#endif
16503b705cfSriastradh
16603b705cfSriastradh   /* Send a flush instruction and then wait till the ring is empty.
16703b705cfSriastradh    * This is stronger than waiting for the blitter to finish as it also
16803b705cfSriastradh    * flushes the internal graphics caches.
16903b705cfSriastradh    */
17003b705cfSriastradh   {
17103b705cfSriastradh      BEGIN_LP_RING(2);
17203b705cfSriastradh      OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
17303b705cfSriastradh      OUT_RING(0);			/* pad to quadword */
17403b705cfSriastradh      ADVANCE_LP_RING();
17503b705cfSriastradh   }
17603b705cfSriastradh
17703b705cfSriastradh   I810WaitLpRing(pScrn, pI810->LpRing->mem.Size - 8, 0);
17803b705cfSriastradh
17903b705cfSriastradh   pI810->LpRing->space = pI810->LpRing->mem.Size - 8;
18003b705cfSriastradh   pI810->nextColorExpandBuf = 0;
18103b705cfSriastradh}
18203b705cfSriastradh
18303b705cfSriastradhvoid
18403b705cfSriastradhI810SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop,
18503b705cfSriastradh		      unsigned int planemask)
18603b705cfSriastradh{
18703b705cfSriastradh   I810Ptr pI810 = I810PTR(pScrn);
18803b705cfSriastradh
18903b705cfSriastradh   if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
19003b705cfSriastradh      ErrorF("I810SetupForFillRectSolid color: %x rop: %x mask: %x\n",
19103b705cfSriastradh	     color, rop, planemask);
19203b705cfSriastradh
19303b705cfSriastradh   /* Color blit, p166 */
19403b705cfSriastradh   pI810->BR[13] = (BR13_SOLID_PATTERN |
19503b705cfSriastradh		    (I810PatternROP[rop] << 16) |
19603b705cfSriastradh		    (pScrn->displayWidth * pI810->cpp));
19703b705cfSriastradh   pI810->BR[16] = color;
19803b705cfSriastradh}
19903b705cfSriastradh
20003b705cfSriastradhvoid
20103b705cfSriastradhI810SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h)
20203b705cfSriastradh{
20303b705cfSriastradh   I810Ptr pI810 = I810PTR(pScrn);
20403b705cfSriastradh
20503b705cfSriastradh   if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
20603b705cfSriastradh      ErrorF("I810SubsequentFillRectSolid %d,%d %dx%d\n", x, y, w, h);
20703b705cfSriastradh
20803b705cfSriastradh   {
20903b705cfSriastradh      BEGIN_LP_RING(6);
21003b705cfSriastradh
21103b705cfSriastradh      OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3);
21203b705cfSriastradh      OUT_RING(pI810->BR[13]);
21303b705cfSriastradh      OUT_RING((h << 16) | (w * pI810->cpp));
21403b705cfSriastradh      OUT_RING(pI810->bufferOffset +
21503b705cfSriastradh	       (y * pScrn->displayWidth + x) * pI810->cpp);
21603b705cfSriastradh
21703b705cfSriastradh      OUT_RING(pI810->BR[16]);
21803b705cfSriastradh      OUT_RING(0);			/* pad to quadword */
21903b705cfSriastradh
22003b705cfSriastradh      ADVANCE_LP_RING();
22103b705cfSriastradh   }
22203b705cfSriastradh}
22303b705cfSriastradh
22403b705cfSriastradhvoid
22503b705cfSriastradhI810SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, int rop,
22603b705cfSriastradh			       unsigned int planemask, int transparency_color)
22703b705cfSriastradh{
22803b705cfSriastradh   I810Ptr pI810 = I810PTR(pScrn);
22903b705cfSriastradh
23003b705cfSriastradh   if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
23103b705cfSriastradh      ErrorF("I810SetupForScreenToScreenCopy %d %d %x %x %d\n",
23203b705cfSriastradh	     xdir, ydir, rop, planemask, transparency_color);
23303b705cfSriastradh
23403b705cfSriastradh   pI810->BR[13] = (pScrn->displayWidth * pI810->cpp);
23503b705cfSriastradh
23603b705cfSriastradh   if (ydir == -1)
23703b705cfSriastradh      pI810->BR[13] = (-pI810->BR[13]) & 0xFFFF;
23803b705cfSriastradh   if (xdir == -1)
23903b705cfSriastradh      pI810->BR[13] |= BR13_RIGHT_TO_LEFT;
24003b705cfSriastradh
24103b705cfSriastradh   pI810->BR[13] |= I810CopyROP[rop] << 16;
24203b705cfSriastradh
24303b705cfSriastradh   pI810->BR[18] = 0;
24403b705cfSriastradh}
24503b705cfSriastradh
24603b705cfSriastradhvoid
24703b705cfSriastradhI810SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1,
24803b705cfSriastradh				 int x2, int y2, int w, int h)
24903b705cfSriastradh{
25003b705cfSriastradh    I810Ptr pI810 = I810PTR(pScrn);
25103b705cfSriastradh    int src, dst;
25203b705cfSriastradh    int w_back = w;
25303b705cfSriastradh
25403b705cfSriastradh    if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
25503b705cfSriastradh	ErrorF( "I810SubsequentScreenToScreenCopy %d,%d - %d,%d %dx%d\n",
25603b705cfSriastradh		x1,y1,x2,y2,w,h);
25703b705cfSriastradh    /*
25803b705cfSriastradh     * This works around a bug in the i810 drawing engine.
25903b705cfSriastradh     * This was developed empirically so it may not catch all
26003b705cfSriastradh     * cases.
26103b705cfSriastradh     */
26203b705cfSriastradh#define I810_MWIDTH 8
26303b705cfSriastradh
26403b705cfSriastradh    if ( !(pI810->BR[13] & BR13_RIGHT_TO_LEFT) && (y2 - y1) < 3
26503b705cfSriastradh	 && (y2 - y1) >= 0 && (x2 - x1) <= (w + I810_MWIDTH)
26603b705cfSriastradh	 && (w > I810_MWIDTH))
26703b705cfSriastradh	w = I810_MWIDTH;
26803b705cfSriastradh    do {
26903b705cfSriastradh
27003b705cfSriastradh	if (pI810->BR[13] & BR13_PITCH_SIGN_BIT) {
27103b705cfSriastradh	    src = (y1 + h - 1) * pScrn->displayWidth * pI810->cpp;
27203b705cfSriastradh	    dst = (y2 + h - 1) * pScrn->displayWidth * pI810->cpp;
27303b705cfSriastradh	} else {
27403b705cfSriastradh	    src = y1 * pScrn->displayWidth * pI810->cpp;
27503b705cfSriastradh	    dst = y2 * pScrn->displayWidth * pI810->cpp;
27603b705cfSriastradh	}
27703b705cfSriastradh
27803b705cfSriastradh	if (pI810->BR[13] & BR13_RIGHT_TO_LEFT) {
27903b705cfSriastradh	    src += (x1 + w - 1) * pI810->cpp + pI810->cpp - 1;
28003b705cfSriastradh	    dst += (x2 + w - 1) * pI810->cpp + pI810->cpp - 1;
28103b705cfSriastradh	} else {
28203b705cfSriastradh	    src += x1 * pI810->cpp;
28303b705cfSriastradh	    dst += x2 * pI810->cpp;
28403b705cfSriastradh	}
28503b705cfSriastradh
28603b705cfSriastradh
28703b705cfSriastradh	/* SRC_COPY_BLT, p169 */
28803b705cfSriastradh	{
28903b705cfSriastradh	    BEGIN_LP_RING(6);
29003b705cfSriastradh	    OUT_RING( BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4 );
29103b705cfSriastradh	    OUT_RING( pI810->BR[13]);
29203b705cfSriastradh
29303b705cfSriastradh	    OUT_RING( (h << 16) | (w * pI810->cpp));
29403b705cfSriastradh	    OUT_RING( pI810->bufferOffset + dst);
29503b705cfSriastradh
29603b705cfSriastradh	    OUT_RING( pI810->BR[13] & 0xFFFF);
29703b705cfSriastradh	    OUT_RING( pI810->bufferOffset + src);
29803b705cfSriastradh	    ADVANCE_LP_RING();
29903b705cfSriastradh	}
30003b705cfSriastradh	w_back -= w;
30103b705cfSriastradh	if (w_back <= 0)
30203b705cfSriastradh	    break;
30303b705cfSriastradh	x2 += w;
30403b705cfSriastradh	x1 += w;
30503b705cfSriastradh	if (w_back > I810_MWIDTH)
30603b705cfSriastradh	    w = I810_MWIDTH;
30703b705cfSriastradh	else
30803b705cfSriastradh	    w = w_back;
30903b705cfSriastradh    }  while (1);
31003b705cfSriastradh}
31103b705cfSriastradh
31203b705cfSriastradhvoid
31303b705cfSriastradhI810EmitFlush(ScrnInfoPtr pScrn)
31403b705cfSriastradh{
31503b705cfSriastradh   I810Ptr pI810 = I810PTR(pScrn);
31603b705cfSriastradh
31703b705cfSriastradh   BEGIN_LP_RING(2);
31803b705cfSriastradh   OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
31903b705cfSriastradh   OUT_RING(0);
32003b705cfSriastradh   ADVANCE_LP_RING();
32103b705cfSriastradh}
32203b705cfSriastradh
32303b705cfSriastradhvoid
32403b705cfSriastradhI810SelectBuffer(ScrnInfoPtr pScrn, int buffer)
32503b705cfSriastradh{
32603b705cfSriastradh   I810Ptr pI810 = I810PTR(pScrn);
32703b705cfSriastradh
32803b705cfSriastradh   switch (buffer) {
32903b705cfSriastradh   case I810_SELECT_BACK:
33003b705cfSriastradh      pI810->bufferOffset = pI810->BackBuffer.Start;
33103b705cfSriastradh      break;
33203b705cfSriastradh   case I810_SELECT_DEPTH:
33303b705cfSriastradh      pI810->bufferOffset = pI810->DepthBuffer.Start;
33403b705cfSriastradh      break;
33503b705cfSriastradh   default:
33603b705cfSriastradh   case I810_SELECT_FRONT:
33703b705cfSriastradh      pI810->bufferOffset = pI810->FrontBuffer.Start;
33803b705cfSriastradh      break;
33903b705cfSriastradh   }
34003b705cfSriastradh
34103b705cfSriastradh   if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
34203b705cfSriastradh      ErrorF("I810SelectBuffer %d --> offset %x\n",
34303b705cfSriastradh	     buffer, pI810->bufferOffset);
34403b705cfSriastradh}
34503b705cfSriastradh
34603b705cfSriastradhvoid
34703b705cfSriastradhI810RefreshRing(ScrnInfoPtr pScrn)
34803b705cfSriastradh{
34903b705cfSriastradh   I810Ptr pI810 = I810PTR(pScrn);
35003b705cfSriastradh
35103b705cfSriastradh   pI810->LpRing->head = INREG(LP_RING + RING_HEAD) & HEAD_ADDR;
35203b705cfSriastradh   pI810->LpRing->tail = INREG(LP_RING + RING_TAIL);
35303b705cfSriastradh   pI810->LpRing->space = pI810->LpRing->head - (pI810->LpRing->tail + 8);
35403b705cfSriastradh   if (pI810->LpRing->space < 0)
35503b705cfSriastradh      pI810->LpRing->space += pI810->LpRing->mem.Size;
35603b705cfSriastradh
35703b705cfSriastradh#if HAVE_XAA_H
35803b705cfSriastradh   if (pI810->AccelInfoRec)
35903b705cfSriastradh      pI810->AccelInfoRec->NeedToSync = TRUE;
36003b705cfSriastradh#endif
36103b705cfSriastradh}
362