summaryrefslogtreecommitdiff
path: root/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_accel.c
diff options
context:
space:
mode:
Diffstat (limited to 'xc/programs/Xserver/hw/xfree86/drivers/i810/i810_accel.c')
-rw-r--r--xc/programs/Xserver/hw/xfree86/drivers/i810/i810_accel.c95
1 files changed, 56 insertions, 39 deletions
diff --git a/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_accel.c b/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_accel.c
index 1b41e8f14..17c24b375 100644
--- a/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_accel.c
+++ b/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_accel.c
@@ -25,7 +25,7 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
-/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i810_accel.c,v 1.14 2002/10/08 20:15:46 dawes Exp $ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i810_accel.c,v 1.17 2002/11/25 14:04:59 eich Exp $ */
/*
* Reformatted with GNU indent (2.2.8), using the following options:
@@ -42,7 +42,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
/*
* Authors:
- * Keith Whitwell <keithw@precisioninsight.com>
+ * Keith Whitwell <keith@tungstengraphics.com>
*
*/
@@ -50,7 +50,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "xf86.h"
#include "i810.h"
-#include "i810_reg.h"
static unsigned int i810Rop[16] = {
0x00, /* GXclear */
@@ -390,42 +389,60 @@ void
I810SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1,
int x2, int y2, int w, int h)
{
- I810Ptr pI810 = I810PTR(pScrn);
- int src, dst;
-
- if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
- ErrorF("I810SubsequentScreenToScreenCopy %d,%d - %d,%d %dx%d\n",
- x1, y1, x2, y2, w, h);
-
- if (pI810->BR[13] & BR13_PITCH_SIGN_BIT) {
- src = (y1 + h - 1) * pScrn->displayWidth * pI810->cpp;
- dst = (y2 + h - 1) * pScrn->displayWidth * pI810->cpp;
- } else {
- src = y1 * pScrn->displayWidth * pI810->cpp;
- dst = y2 * pScrn->displayWidth * pI810->cpp;
- }
-
- if (pI810->BR[13] & BR13_RIGHT_TO_LEFT) {
- src += (x1 + w - 1) * pI810->cpp + pI810->cpp - 1;
- dst += (x2 + w - 1) * pI810->cpp + pI810->cpp - 1;
- } else {
- src += x1 * pI810->cpp;
- dst += x2 * pI810->cpp;
- }
-
- /* SRC_COPY_BLT, p169 */
- {
- BEGIN_LP_RING(6);
- OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4);
- OUT_RING(pI810->BR[13]);
-
- OUT_RING((h << 16) | (w * pI810->cpp));
- OUT_RING(pI810->bufferOffset + dst);
-
- OUT_RING(pI810->BR[13] & 0xFFFF);
- OUT_RING(pI810->bufferOffset + src);
- ADVANCE_LP_RING();
- }
+ I810Ptr pI810 = I810PTR(pScrn);
+ int src, dst;
+ int w_back = w;
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF( "I810SubsequentScreenToScreenCopy %d,%d - %d,%d %dx%d\n",
+ x1,y1,x2,y2,w,h);
+ /*
+ * This works around a bug in the i810 drawing engine.
+ * This was developed empirically so it may not catch all
+ * cases.
+ */
+ if ( !(pI810->BR[13] & BR13_RIGHT_TO_LEFT) && (y2 - y1) < 3
+ && (y2 - y1) >= 0 && (x2 - x1) <= (w + 4) && (w > 4))
+ w = 4;
+ do {
+
+ if (pI810->BR[13] & BR13_PITCH_SIGN_BIT) {
+ src = (y1 + h - 1) * pScrn->displayWidth * pI810->cpp;
+ dst = (y2 + h - 1) * pScrn->displayWidth * pI810->cpp;
+ } else {
+ src = y1 * pScrn->displayWidth * pI810->cpp;
+ dst = y2 * pScrn->displayWidth * pI810->cpp;
+ }
+
+ if (pI810->BR[13] & BR13_RIGHT_TO_LEFT) {
+ src += (x1 + w - 1) * pI810->cpp + pI810->cpp - 1;
+ dst += (x2 + w - 1) * pI810->cpp + pI810->cpp - 1;
+ } else {
+ src += x1 * pI810->cpp;
+ dst += x2 * pI810->cpp;
+ }
+
+
+ /* SRC_COPY_BLT, p169 */
+ {
+ BEGIN_LP_RING(6);
+ OUT_RING( BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4 );
+ OUT_RING( pI810->BR[13]);
+
+ OUT_RING( (h << 16) | (w * pI810->cpp));
+ OUT_RING( pI810->bufferOffset + dst);
+
+ OUT_RING( pI810->BR[13] & 0xFFFF);
+ OUT_RING( pI810->bufferOffset + src);
+ ADVANCE_LP_RING();
+ }
+ w_back -= w;
+ if (w_back <= 0)
+ break;
+ x2 += w;
+ x1 += w;
+ w = w_back;
+ } while (1);
}
static void