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