changeset 5500:6ac26131bcaf

SW pipeline: 9-Slice stretched areas were wrong (RT-33414)
author Martin Soch <Martin.Soch@oracle.com>
date Wed, 23 Oct 2013 13:29:25 +0200
parents 288eb8869c9c
children 29ce5c785087
files modules/graphics/src/main/java/com/sun/pisces/PiscesRenderer.java modules/graphics/src/main/java/com/sun/prism/sw/SWGraphics.java modules/graphics/src/main/java/com/sun/prism/sw/SWPaint.java modules/graphics/src/main/native-prism-sw/JPiscesRenderer.c modules/graphics/src/main/native-prism-sw/PiscesPaint.c modules/graphics/src/main/native-prism-sw/PiscesRenderer.h modules/graphics/src/main/native-prism-sw/PiscesRenderer.inl modules/graphics/src/main/native-prism-sw/PiscesUtil.h
diffstat 8 files changed, 147 insertions(+), 109 deletions(-) [+]
line wrap: on
line diff
--- a/modules/graphics/src/main/java/com/sun/pisces/PiscesRenderer.java	Wed Oct 23 09:51:45 2013 +0200
+++ b/modules/graphics/src/main/java/com/sun/pisces/PiscesRenderer.java	Wed Oct 23 13:29:25 2013 +0200
@@ -386,7 +386,7 @@
         Transform6 textureTransform, boolean repeat,
         int bboxX, int bboxY, int bboxW, int bboxH,
         int lEdge, int rEdge, int tEdge, int bEdge,
-        int interpolateMinX, int interpolateMinY, int interpolateMaxX, int interpolateMaxY,
+        int txMin, int tyMin, int txMax, int tyMax,
         boolean hasAlpha)
     {
         this.inputImageCheck(width, height, offset, stride, data.length);
@@ -394,7 +394,7 @@
             textureTransform, repeat,
             bboxX, bboxY, bboxW, bboxH,
             lEdge, rEdge, tEdge, bEdge,
-            interpolateMinX, interpolateMinY, interpolateMaxX, interpolateMaxY,
+            txMin, tyMin, txMax, tyMax,
             hasAlpha);
     }
 
@@ -402,7 +402,7 @@
         Transform6 textureTransform, boolean repeat,
         int bboxX, int bboxY, int bboxW, int bboxH,
         int lEdge, int rEdge, int tEdge, int bEdge,
-        int interpolateMinX, int interpolateMinY, int interpolateMaxX, int interpolateMaxY,
+        int txMin, int tyMin, int txMax, int tyMax,
         boolean hasAlpha);
 
     private void inputImageCheck(int width, int height, int offset, int stride, int data_length) {
--- a/modules/graphics/src/main/java/com/sun/prism/sw/SWGraphics.java	Wed Oct 23 09:51:45 2013 +0200
+++ b/modules/graphics/src/main/java/com/sun/prism/sw/SWGraphics.java	Wed Oct 23 13:29:25 2013 +0200
@@ -717,12 +717,11 @@
             System.out.println("dstBBox: " + dstBBox);
         }
 
-        final int interpolateMinX = Math.max(0, SWUtils.fastFloor(Math.min(sx1, sx2)));
-        final int interpolateMinY = Math.max(0, SWUtils.fastFloor(Math.min(sy1, sy2)));
-        final int interpolateMaxX = Math.min(tex.getContentWidth() - 1,
-                SWUtils.fastCeil(Math.max(sx1, sx2)) - 1);
-        final int interpolateMaxY = Math.min(tex.getContentHeight() - 1,
-                SWUtils.fastCeil(Math.max(sy1, sy2)) - 1);
+        // texture coordinates range
+        final int txMin = Math.max(0, SWUtils.fastFloor(Math.min(sx1, sx2)));
+        final int tyMin = Math.max(0, SWUtils.fastFloor(Math.min(sy1, sy2)));
+        final int txMax = Math.min(tex.getContentWidth() - 1, SWUtils.fastCeil(Math.max(sx1, sx2)) - 1);
+        final int tyMax = Math.min(tex.getContentHeight() - 1, SWUtils.fastCeil(Math.max(sy1, sy2)) - 1);
 
         this.pr.drawImage(RendererBase.TYPE_INT_ARGB_PRE, imageMode,
                 data, tex.getContentWidth(), tex.getContentHeight(),
@@ -732,7 +731,7 @@
                 (int)(SWUtils.TO_PISCES * dstBBox.getMinX()), (int)(SWUtils.TO_PISCES * dstBBox.getMinY()),
                 (int)(SWUtils.TO_PISCES * dstBBox.getWidth()), (int)(SWUtils.TO_PISCES * dstBBox.getHeight()),
                 lEdge, rEdge, tEdge, bEdge,
-                interpolateMinX, interpolateMinY, interpolateMaxX, interpolateMaxY,
+                txMin, tyMin, txMax, tyMax,
                 swTex.hasAlpha());
 
         if (PrismSettings.debug) {
--- a/modules/graphics/src/main/java/com/sun/prism/sw/SWPaint.java	Wed Oct 23 09:51:45 2013 +0200
+++ b/modules/graphics/src/main/java/com/sun/prism/sw/SWPaint.java	Wed Oct 23 13:29:25 2013 +0200
@@ -238,14 +238,8 @@
     {
         paintTx.setTransform(tx);
 
-        final float[] scale_correction = new float[2];
-        computeScaleAndPixelCorrection(scale_correction, dx1, dx2, sx1, sx2);
-        final float scaleX = scale_correction[0];
-        final float x_pixel_correction = scale_correction[1];
-
-        computeScaleAndPixelCorrection(scale_correction, dy1, dy2, sy1, sy2);
-        final float scaleY = scale_correction[0];
-        final float y_pixel_correction = scale_correction[1];
+        final float scaleX = computeScale(dx1, dx2, sx1, sx2);
+        final float scaleY = computeScale(dy1, dy2, sy1, sy2);
 
         if (scaleX == 1 && scaleY == 1) {
             paintTx.deriveWithTranslation(-Math.min(sx1, sx2) + Math.min(dx1, dx2),
@@ -255,32 +249,20 @@
             paintTx.deriveWithTranslation((scaleX >= 0) ? 0 : Math.abs(dx2 - dx1),
                     (scaleY >= 0) ? 0 : Math.abs(dy2 - dy1));
             paintTx.deriveWithConcatenation(scaleX, 0, 0, scaleY, 0, 0);
-            paintTx.deriveWithTranslation(-Math.min(sx1, sx2) + x_pixel_correction,
-                    -Math.min(sy1, sy2) + y_pixel_correction);
+            paintTx.deriveWithTranslation(-Math.min(sx1, sx2), -Math.min(sy1, sy2));
         }
 
         SWUtils.convertToPiscesTransform(paintTx, piscesTx);
         return piscesTx;
     }
 
-    private void computeScaleAndPixelCorrection(float[] target, float dv1, float dv2, float sv1, float sv2) {
+    private float computeScale(float dv1, float dv2, float sv1, float sv2) {
         final float dv_diff = dv2 - dv1;
         float scale = dv_diff / (sv2 - sv1);
-        float pixel_correction = 0;
-        if (Math.abs(scale) > 2*Math.abs(dv_diff)) {
-            // scaling "single" pixel
-            // we need to "2*" since there is half-pixel shift for
-            // the purpose of interpolation in the native
-            scale = 2 * Math.signum(scale) * Math.abs(dv_diff);
-            if ((int)sv2 != (int)sv1) {
-                // scaling parts of two neighboring pixels
-                final float sx_min = Math.min(sv1, sv2);
-                final float pixel_reminder = (float)(Math.ceil(sx_min)) - sx_min;
-                pixel_correction = pixel_reminder / (2*(sv2 - sv1));
-            }
+        if (Math.abs(scale) > (Integer.MAX_VALUE >> 16)) {
+            scale = Math.signum(scale) * (Integer.MAX_VALUE >> 16);
         }
-        target[0] = scale;
-        target[1] = pixel_correction;
+        return scale;
     }
 
     Transform6 computeSetTexturePaintTransform(Paint p, BaseTransform tx, RectBounds nodeBounds,
--- a/modules/graphics/src/main/native-prism-sw/JPiscesRenderer.c	Wed Oct 23 09:51:45 2013 +0200
+++ b/modules/graphics/src/main/native-prism-sw/JPiscesRenderer.c	Wed Oct 23 13:29:25 2013 +0200
@@ -660,7 +660,7 @@
     jintArray dataArray, jint width, jint height, jint offset, jint stride,
     jobject jTransform, jboolean repeat, jint bboxX, jint bboxY, jint bboxW, jint bboxH,
     jint lEdge, jint rEdge, jint tEdge, jint bEdge,
-    jint interpolateMinX, jint interpolateMinY, jint interpolateMaxX, jint interpolateMaxY,
+    jint txMin, jint tyMin, jint txMax, jint tyMax,
     jboolean hasAlpha)
 {
     Renderer* rdr;
@@ -674,7 +674,7 @@
         transform_get6(&textureTransform, env, jTransform);
         renderer_setTexture(rdr, imageMode, data + offset, width, height, stride,
             repeat, JNI_TRUE, &textureTransform, JNI_FALSE, hasAlpha,
-            interpolateMinX, interpolateMinY, interpolateMaxX, interpolateMaxY);
+            txMin, tyMin, txMax, tyMax);
 
         fillRect(env, this, rdr,
             bboxX, bboxY, bboxW, bboxH,
@@ -690,6 +690,7 @@
         JNI_ThrowNew(env, "java/lang/OutOfMemoryError",
                      "Allocation of internal renderer buffer failed.");
     }
+    PISCES_DEBUG_FLUSH(stdout);
 }
 
 /*
--- a/modules/graphics/src/main/native-prism-sw/PiscesPaint.c	Wed Oct 23 09:51:45 2013 +0200
+++ b/modules/graphics/src/main/native-prism-sw/PiscesPaint.c	Wed Oct 23 13:29:25 2013 +0200
@@ -364,7 +364,7 @@
 static INLINE void checkBoundsRepeat(jint *a, jlong *la, jint min, jint max) {
     jint aval = *a;
     if (aval < min || aval > max) {
-        if (max > 0) {
+        if (max >= 0) {
             *la = lmod(*la, (max+1) << 16);
             *a = (jint)(*la >> 16);
         } else {
@@ -384,28 +384,34 @@
 }
 
 static INLINE void getPointsToInterpolate(jint *pts, jint *data, jint sidx, jint stride, jint p00,
-    jint tx, jint txMin, jint txMax, jint ty, jint tyMin, jint tyMax)
-{
-    jint sidx2 = ((ty < tyMax) && (ty >= tyMin)) ? sidx + stride : sidx;
-    jboolean isXin = ((tx < txMax) && (tx >= txMin));
-    pts[0] = (isXin) ? data[sidx + 1] : p00;
-    pts[1] = data[sidx2];
-    pts[2] = (isXin) ? data[sidx2 + 1] : data[sidx2];
-}
-
-static INLINE void getPointsToInterpolateRepeat(jint *pts, jint *data, jint sidx, jint stride, jint p00,
-    jint tx, jint txMin, jint txMax, jint ty, jint tyMin, jint tyMax)
+    jint tx, jint txMax, jint ty, jint tyMax)
 {
     jint txn = tx+1;
     jint tyn = ty+1;
     if (txn > txMax) {
-        txn = txMin;
+        txn = txMax;
     }
     if (tyn > tyMax) {
-        tyn = tyMin;
+        tyn = tyMax;
     }
-    pts[0] = data[MAX(tyMin, ty) * stride + txn];
-    pts[1] = data[tyn * stride + MAX(txMin, tx)];
+    pts[0] = data[MAX(0, ty) * stride + txn];
+    pts[1] = data[tyn * stride + MAX(0, tx)];
+    pts[2] = data[tyn * stride + txn];
+}
+
+static INLINE void getPointsToInterpolateRepeat(jint *pts, jint *data, jint sidx, jint stride, jint p00,
+    jint tx, jint txMax, jint ty, jint tyMax)
+{
+    jint txn = tx+1;
+    jint tyn = ty+1;
+    if (txn > txMax) {
+        txn = 0;
+    }
+    if (tyn > tyMax) {
+        tyn = 0;
+    }
+    pts[0] = data[MAX(0, ty) * stride + txn];
+    pts[1] = data[tyn * stride + MAX(0, tx)];
     pts[2] = data[tyn * stride + txn];
 }
 
@@ -420,10 +426,11 @@
     jint* txtData = rdr->_texture_intData;
     jint txtWidth = rdr->_texture_imageWidth;
     jint txtHeight = rdr->_texture_imageHeight;
-    jint txMin = rdr->_texture_interpolateMinX;
-    jint tyMin = rdr->_texture_interpolateMinY;
-    jint txMax = rdr->_texture_interpolateMaxX;
-    jint tyMax = rdr->_texture_interpolateMaxY;
+    jint txtStride = rdr->_texture_stride;
+    jint txMin = rdr->_texture_txMin;
+    jint tyMin = rdr->_texture_tyMin;
+    jint txMax = rdr->_texture_txMax;
+    jint tyMax = rdr->_texture_tyMax;
     jint repeatInterpolateMode;
 
     if (rdr->_texture_interpolate) {
@@ -449,7 +456,7 @@
             jint txtOffsetRepeat = rdr->_currX % txtWidth;
             jint txtRowNumRepeat = rdr->_currY % txtHeight;
             for (j = 0; j < height; j++) {
-                jint *tStart = txtData + rdr->_texture_stride * txtRowNumRepeat;
+                jint *tStart = txtData + txtStride * txtRowNumRepeat;
                 jint *t = tStart + txtOffsetRepeat;
                 jint *tEnd = tStart + txtWidth;
                 jint *d = paint + paintStride * j;
@@ -468,10 +475,10 @@
         } else {
             jint minX = MAX(rdr->_rectX, rdr->_clip_bbMinX);
             jint minY = MAX(rdr->_rectY, rdr->_clip_bbMinY);
-            jint clipOffset = (minY - rdr->_rectY) * rdr->_texture_stride + minX - rdr->_rectX;
+            jint clipOffset = (minY - rdr->_rectY) * txtStride + minX - rdr->_rectX;
             for (j = 0; j < height; j++) {
                 memcpy(paint + paintStride * j,
-                     txtData + clipOffset + rdr->_texture_stride * (firstRowNum + j),
+                     txtData + clipOffset + txtStride * (firstRowNum + j),
                      sizeof(jint) * paintStride);
             }
         }
@@ -514,12 +521,15 @@
             a = paint + pidx;
             am = a + paintStride;
 
+            PISCES_DEBUG("TRANSLATE, txMin: %d, txMax: %d, tyMin: %d, tyMax: %d\n", txMin, txMax, tyMin, tyMax);
+
             switch (repeatInterpolateMode) {
             case NO_REPEAT_NO_INTERPOLATE:
                 while (a < am) {
                     tx = (jint)(ltx >> 16);
                     checkBoundsNoRepeat(&tx, &ltx, txMin-1, txMax);
-                    sidx = MAX(tyMin, ty) * rdr->_texture_stride + MAX(txMin, tx);
+                    PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac);
+                    sidx = MAX(0, ty) * txtStride + MAX(0, tx);
                     assert(pidx >= 0);
                     assert(pidx < rdr->_paint_length);
                     paint[pidx] = txtData[sidx];
@@ -532,7 +542,8 @@
                 while (a < am) {
                     tx = (jint)(ltx >> 16);
                     checkBoundsRepeat(&tx, &ltx, txMin-1, txMax);
-                    sidx = MAX(tyMin, ty) * rdr->_texture_stride + MAX(txMin, tx);
+                    PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac);
+                    sidx = MAX(0, ty) * txtStride + MAX(0, tx);
                     assert(pidx >= 0);
                     assert(pidx < rdr->_paint_length);
                     paint[pidx] = txtData[sidx];
@@ -545,10 +556,12 @@
                 while (a < am) {
                     tx = (jint)(ltx >> 16);
                     checkBoundsNoRepeat(&tx, &ltx, txMin-1, txMax);
-                    sidx = MAX(tyMin, ty) * rdr->_texture_stride + MAX(txMin, tx);
+                    PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac);
+                    sidx = MAX(0, ty) * txtStride + MAX(0, tx);
                     p00 = txtData[sidx];
-                    getPointsToInterpolate(pts, txtData, sidx, rdr->_texture_stride, p00,
-                        tx, txMin, txMax, ty, tyMin, tyMax);
+                    getPointsToInterpolate(pts, txtData, sidx, txtStride, p00,
+                        tx, txtWidth-1, ty, txtHeight-1);
+                    PISCES_DEBUG("cols[%x, %x, %x, %x] ", p00, pts[0], pts[1], pts[2]);
                     if (hfrac && vfrac) {
                         cval = interpolate4points(p00, pts[0], pts[1], pts[2], hfrac, vfrac);
                     } else if (hfrac) {
@@ -570,10 +583,12 @@
                 while (a < am) {
                     tx = (jint)(ltx >> 16);
                     checkBoundsRepeat(&tx, &ltx, txMin-1, txMax);
-                    sidx = MAX(tyMin, ty) * rdr->_texture_stride + MAX(txMin, tx);
+                    PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac);
+                    sidx = MAX(0, ty) * txtStride + MAX(0, tx);
                     p00 = txtData[sidx];
-                    getPointsToInterpolateRepeat(pts, txtData, sidx, rdr->_texture_stride, p00,
-                        tx, txMin, txMax, ty, tyMin, tyMax);
+                    getPointsToInterpolateRepeat(pts, txtData, sidx, txtStride, p00,
+                        tx, txtWidth-1, ty, txtHeight-1);
+                    PISCES_DEBUG("cols[%x, %x, %x, %x] ", p00, pts[0], pts[1], pts[2]);
                     if (hfrac && vfrac) {
                         cval = interpolate4points(p00, pts[0], pts[1], pts[2], hfrac, vfrac);
                     } else if (hfrac) {
@@ -595,10 +610,12 @@
                 while (a < am) {
                     tx = (jint)(ltx >> 16);
                     checkBoundsNoRepeat(&tx, &ltx, txMin-1, txMax);
-                    sidx = MAX(tyMin, ty) * rdr->_texture_stride + MAX(txMin, tx);
+                    PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac);
+                    sidx = MAX(0, ty) * txtStride + MAX(0, tx);
                     p00 = txtData[sidx];
-                    getPointsToInterpolate(pts, txtData, sidx, rdr->_texture_stride, p00,
-                        tx, txMin, txMax, ty, tyMin, tyMax);
+                    getPointsToInterpolate(pts, txtData, sidx, txtStride, p00,
+                        tx, txtWidth-1, ty, txtHeight-1);
+                    PISCES_DEBUG("cols[%x, %x, %x, %x] ", p00, pts[0], pts[1], pts[2]);
                     if (hfrac && vfrac) {
                         cval = interpolate4pointsNoAlpha(p00, pts[0], pts[1], pts[2], hfrac, vfrac);
                     } else if (hfrac) {
@@ -620,10 +637,12 @@
                 while (a < am) {
                     tx = (jint)(ltx >> 16);
                     checkBoundsRepeat(&tx, &ltx, txMin-1, txMax);
-                    sidx = MAX(tyMin, ty) * rdr->_texture_stride + MAX(txMin, tx);
+                    PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac);
+                    sidx = MAX(0, ty) * txtStride + MAX(0, tx);
                     p00 = txtData[sidx];
-                    getPointsToInterpolateRepeat(pts, txtData, sidx, rdr->_texture_stride, p00,
-                        tx, txMin, txMax, ty, tyMin, tyMax);
+                    getPointsToInterpolateRepeat(pts, txtData, sidx, txtStride, p00,
+                        tx, txtWidth-1, ty, txtHeight-1);
+                    PISCES_DEBUG("cols[%x, %x, %x, %x] ", p00, pts[0], pts[1], pts[2]);
                     if (hfrac && vfrac) {
                         cval = interpolate4pointsNoAlpha(p00, pts[0], pts[1], pts[2], hfrac, vfrac);
                     } else if (hfrac) {
@@ -642,6 +661,7 @@
                 } // while (a < am)
                 break;
             }
+            PISCES_DEBUG("\n");
             paintOffset += paintStride;
         } // for
         }
@@ -670,6 +690,9 @@
 
             a = paint + pidx;
             am = a + paintStride;
+
+            PISCES_DEBUG("SCALE, txMin: %d, txMax: %d, tyMin: %d, tyMax: %d\n", txMin, txMax, tyMin, tyMax);
+
             switch (repeatInterpolateMode) {
             case NO_REPEAT_NO_INTERPOLATE:
                 while (a < am) {
@@ -679,7 +702,8 @@
                     vfrac = (jint)(lty & 0xffff);
                     checkBoundsNoRepeat(&tx, &ltx, txMin-1, txMax);
                     checkBoundsNoRepeat(&ty, &lty, tyMin-1, tyMax);
-                    sidx = MAX(tyMin, ty) * rdr->_texture_stride + MAX(txMin, tx);
+                    PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac);
+                    sidx = MAX(0, ty) * txtStride + MAX(0, tx);
                     assert(pidx >= 0);
                     assert(pidx < rdr->_paint_length);
                     paint[pidx] = txtData[sidx];
@@ -697,7 +721,8 @@
                     vfrac = (jint)(lty & 0xffff);
                     checkBoundsRepeat(&tx, &ltx, txMin-1, txMax);
                     checkBoundsRepeat(&ty, &lty, tyMin-1, tyMax);
-                    sidx = MAX(tyMin, ty) * rdr->_texture_stride + MAX(txMin, tx);
+                    PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac);
+                    sidx = MAX(0, ty) * txtStride + MAX(0, tx);
                     assert(pidx >= 0);
                     assert(pidx < rdr->_paint_length);
                     paint[pidx] = txtData[sidx];
@@ -715,10 +740,12 @@
                     vfrac = (jint)(lty & 0xffff);
                     checkBoundsNoRepeat(&tx, &ltx, txMin-1, txMax);
                     checkBoundsNoRepeat(&ty, &lty, tyMin-1, tyMax);
-                    sidx = MAX(tyMin, ty) * rdr->_texture_stride + MAX(txMin, tx);
+                    PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac);
+                    sidx = MAX(0, ty) * txtStride + MAX(0, tx);
                     p00 = txtData[sidx];
-                    getPointsToInterpolate(pts, txtData, sidx, rdr->_texture_stride, p00,
-                        tx, txMin, txMax, ty, tyMin, tyMax);
+                    getPointsToInterpolate(pts, txtData, sidx, txtStride, p00,
+                        tx, txtWidth-1, ty, txtHeight-1);
+                    PISCES_DEBUG("cols[%x, %x, %x, %x] ", p00, pts[0], pts[1], pts[2]);
                     if (hfrac && vfrac) {
                         cval = interpolate4points(p00, pts[0], pts[1], pts[2], hfrac, vfrac);
                     } else if (hfrac) {
@@ -746,10 +773,12 @@
                     vfrac = (jint)(lty & 0xffff);
                     checkBoundsRepeat(&tx, &ltx, txMin-1, txMax);
                     checkBoundsRepeat(&ty, &lty, tyMin-1, tyMax);
-                    sidx = MAX(tyMin, ty) * rdr->_texture_stride + MAX(txMin, tx);
+                    PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac);
+                    sidx = MAX(0, ty) * txtStride + MAX(0, tx);
                     p00 = txtData[sidx];
-                    getPointsToInterpolateRepeat(pts, txtData, sidx, rdr->_texture_stride, p00,
-                        tx, txMin, txMax, ty, tyMin, tyMax);
+                    getPointsToInterpolateRepeat(pts, txtData, sidx, txtStride, p00,
+                        tx, txtWidth-1, ty, txtHeight-1);
+                    PISCES_DEBUG("cols[%x, %x, %x, %x] ", p00, pts[0], pts[1], pts[2]);
                     if (hfrac && vfrac) {
                         cval = interpolate4points(p00, pts[0], pts[1], pts[2], hfrac, vfrac);
                     } else if (hfrac) {
@@ -777,10 +806,12 @@
                     vfrac = (jint)(lty & 0xffff);
                     checkBoundsNoRepeat(&tx, &ltx, txMin-1, txMax);
                     checkBoundsNoRepeat(&ty, &lty, tyMin-1, tyMax);
-                    sidx = MAX(tyMin, ty) * rdr->_texture_stride + MAX(txMin, tx);
+                    PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac);
+                    sidx = MAX(0, ty) * txtStride + MAX(0, tx);
                     p00 = txtData[sidx];
-                    getPointsToInterpolate(pts, txtData, sidx, rdr->_texture_stride, p00,
-                        tx, txMin, txMax, ty, tyMin, tyMax);
+                    getPointsToInterpolate(pts, txtData, sidx, txtStride, p00,
+                        tx, txtWidth-1, ty, txtHeight-1);
+                    PISCES_DEBUG("cols[%x, %x, %x, %x] ", p00, pts[0], pts[1], pts[2]);
                     if (hfrac && vfrac) {
                         cval = interpolate4pointsNoAlpha(p00, pts[0], pts[1], pts[2], hfrac, vfrac);
                     } else if (hfrac) {
@@ -808,10 +839,12 @@
                     vfrac = (jint)(lty & 0xffff);
                     checkBoundsRepeat(&tx, &ltx, txMin-1, txMax);
                     checkBoundsRepeat(&ty, &lty, tyMin-1, tyMax);
-                    sidx = MAX(tyMin, ty) * rdr->_texture_stride + MAX(txMin, tx);
+                    PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac);
+                    sidx = MAX(0, ty) * txtStride + MAX(0, tx);
                     p00 = txtData[sidx];
-                    getPointsToInterpolateRepeat(pts, txtData, sidx, rdr->_texture_stride, p00,
-                        tx, txMin, txMax, ty, tyMin, tyMax);
+                    getPointsToInterpolateRepeat(pts, txtData, sidx, txtStride, p00,
+                        tx, txtWidth-1, ty, txtHeight-1);
+                    PISCES_DEBUG("cols[%x, %x, %x, %x] ", p00, pts[0], pts[1], pts[2]);
                     if (hfrac && vfrac) {
                         cval = interpolate4pointsNoAlpha(p00, pts[0], pts[1], pts[2], hfrac, vfrac);
                     } else if (hfrac) {
@@ -832,6 +865,7 @@
                 } // while (a < am)b
                 break;
             }
+            PISCES_DEBUG("\n");
             paintOffset += paintStride;
         }//for
         }
@@ -861,6 +895,9 @@
 
             a = paint + pidx;
             am = a + paintStride;
+
+            PISCES_DEBUG("GENERIC, txMin: %d, txMax: %d, tyMin: %d, tyMax: %d\n", txMin, txMax, tyMin, tyMax);
+
             switch (repeatInterpolateMode) {
             case NO_REPEAT_NO_INTERPOLATE:
                 while (a < am) {
@@ -872,8 +909,9 @@
                     inBounds =
                         isInBoundsNoRepeat(&tx, &ltx, txMin-1, txMax) &&
                         isInBoundsNoRepeat(&ty, &lty, tyMin-1, tyMax);
+                    PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac);
                     if (inBounds) {
-                        sidx = MAX(tyMin, ty) * rdr->_texture_stride + MAX(txMin, tx);
+                        sidx = MAX(0, ty) * txtStride + MAX(0, tx);
                         p00 = txtData[sidx];
                         assert(pidx >= 0);
                         assert(pidx < rdr->_paint_length);
@@ -897,7 +935,8 @@
                     vfrac = (jint)(lty & 0xffff);
                     checkBoundsRepeat(&tx, &ltx, txMin-1, txMax);
                     checkBoundsRepeat(&ty, &lty, tyMin-1, tyMax);
-                    sidx = MAX(tyMin, ty) * rdr->_texture_stride + MAX(txMin, tx);
+                    PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac);
+                    sidx = MAX(0, ty) * txtStride + MAX(0, tx);
                     p00 = txtData[sidx];
                     assert(pidx >= 0);
                     assert(pidx < rdr->_paint_length);
@@ -918,12 +957,14 @@
                     inBounds =
                         isInBoundsNoRepeat(&tx, &ltx, txMin-1, txMax) &&
                         isInBoundsNoRepeat(&ty, &lty, tyMin-1, tyMax);
+                    PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac);
                     if (inBounds) {
-                        sidx = MAX(tyMin, ty) * rdr->_texture_stride + MAX(txMin, tx);
+                        sidx = MAX(0, ty) * txtStride + MAX(0, tx);
                         p00 = txtData[sidx];
 
-                        getPointsToInterpolate(pts, txtData, sidx, rdr->_texture_stride, p00,
-                            tx, txMin, txMax, ty, tyMin, tyMax);
+                        getPointsToInterpolate(pts, txtData, sidx, txtStride, p00,
+                            tx, txtWidth-1, ty, txtHeight-1);
+                        PISCES_DEBUG("cols[%x, %x, %x, %x] ", p00, pts[0], pts[1], pts[2]);
                         if (hfrac && vfrac) {
                             cval = interpolate4points(p00, pts[0], pts[1], pts[2], hfrac, vfrac);
                         } else if (hfrac) {
@@ -955,10 +996,12 @@
                     vfrac = (jint)(lty & 0xffff);
                     checkBoundsRepeat(&tx, &ltx, txMin-1, txMax);
                     checkBoundsRepeat(&ty, &lty, tyMin-1, tyMax);
-                    sidx = MAX(tyMin, ty) * rdr->_texture_stride + MAX(txMin, tx);
+                    PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac);
+                    sidx = MAX(0, ty) * txtStride + MAX(0, tx);
                     p00 = txtData[sidx];
-                    getPointsToInterpolateRepeat(pts, txtData, sidx, rdr->_texture_stride, p00,
-                        tx, txMin, txMax, ty, tyMin, tyMax);
+                    getPointsToInterpolateRepeat(pts, txtData, sidx, txtStride, p00,
+                        tx, txtWidth-1, ty, txtHeight-1);
+                    PISCES_DEBUG("cols[%x, %x, %x, %x] ", p00, pts[0], pts[1], pts[2]);
                     if (hfrac && vfrac) {
                         cval = interpolate4points(p00, pts[0], pts[1], pts[2], hfrac, vfrac);
                     } else if (hfrac) {
@@ -987,12 +1030,14 @@
                     inBounds =
                         isInBoundsNoRepeat(&tx, &ltx, txMin-1, txMax) &&
                         isInBoundsNoRepeat(&ty, &lty, tyMin-1, tyMax);
+                    PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac);
                     if (inBounds) {
-                        sidx = MAX(tyMin, ty) * rdr->_texture_stride + MAX(txMin, tx);
+                        sidx = MAX(0, ty) * txtStride + MAX(0, tx);
                         p00 = txtData[sidx];
 
-                        getPointsToInterpolate(pts, txtData, sidx, rdr->_texture_stride, p00,
-                            tx, txMin, txMax, ty, tyMin, tyMax);
+                        getPointsToInterpolate(pts, txtData, sidx, txtStride, p00,
+                            tx, txtWidth-1, ty, txtHeight-1);
+                        PISCES_DEBUG("cols[%x, %x, %x, %x] ", p00, pts[0], pts[1], pts[2]);
                         if (hfrac && vfrac) {
                             cval = interpolate4pointsNoAlpha(p00, pts[0], pts[1], pts[2], hfrac, vfrac);
                         } else if (hfrac) {
@@ -1024,10 +1069,12 @@
                     vfrac = (jint)(lty & 0xffff);
                     checkBoundsRepeat(&tx, &ltx, txMin-1, txMax);
                     checkBoundsRepeat(&ty, &lty, tyMin-1, tyMax);
-                    sidx = MAX(tyMin, ty) * rdr->_texture_stride + MAX(txMin, tx);
+                    PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac);
+                    sidx = MAX(0, ty) * txtStride + MAX(0, tx);
                     p00 = txtData[sidx];
-                    getPointsToInterpolateRepeat(pts, txtData, sidx, rdr->_texture_stride, p00,
-                        tx, txMin, txMax, ty, tyMin, tyMax);
+                    getPointsToInterpolateRepeat(pts, txtData, sidx, txtStride, p00,
+                        tx, txtWidth-1, ty, txtHeight-1);
+                    PISCES_DEBUG("cols[%x, %x, %x, %x] ", p00, pts[0], pts[1], pts[2]);
                     if (hfrac && vfrac) {
                         cval = interpolate4pointsNoAlpha(p00, pts[0], pts[1], pts[2], hfrac, vfrac);
                     } else if (hfrac) {
@@ -1047,6 +1094,7 @@
                 } // while (a < am)b
                 break;
             }
+            PISCES_DEBUG("\n");
             paintOffset += paintStride;
         }//for
         }
--- a/modules/graphics/src/main/native-prism-sw/PiscesRenderer.h	Wed Oct 23 09:51:45 2013 +0200
+++ b/modules/graphics/src/main/native-prism-sw/PiscesRenderer.h	Wed Oct 23 13:29:25 2013 +0200
@@ -356,8 +356,8 @@
     jint _texture_imageWidth;
     jint _texture_imageHeight;
     jint _texture_stride;
-    jint _texture_interpolateMinX, _texture_interpolateMinY;
-    jint _texture_interpolateMaxX, _texture_interpolateMaxY;
+    jint _texture_txMin, _texture_tyMin;
+    jint _texture_txMax, _texture_tyMax;
     jboolean _texture_repeat;
     jlong _texture_m00, _texture_m01, _texture_m02;
     jlong _texture_m10, _texture_m11, _texture_m12;
--- a/modules/graphics/src/main/native-prism-sw/PiscesRenderer.inl	Wed Oct 23 09:51:45 2013 +0200
+++ b/modules/graphics/src/main/native-prism-sw/PiscesRenderer.inl	Wed Oct 23 13:29:25 2013 +0200
@@ -308,7 +308,7 @@
                     jboolean repeat, jboolean smooth, 
                     const Transform6* transform, jboolean freeData,
                     jboolean textureHasAlpha,
-                    jint interpolateMinX, jint interpolateMinY, jint interpolateMaxX, jint interpolateMaxY) {
+                    jint txMin, jint tyMin, jint txMax, jint tyMax) {
     Transform6 compoundTransform;
 
     pisces_transform_assign(&rdr->_paint_transform, transform);
@@ -337,10 +337,10 @@
     rdr->_texture_imageHeight = height;
     rdr->_texture_stride = stride;
     rdr->_texture_repeat = repeat;
-    rdr->_texture_interpolateMinX = interpolateMinX;
-    rdr->_texture_interpolateMinY = interpolateMinY;
-    rdr->_texture_interpolateMaxX = interpolateMaxX;
-    rdr->_texture_interpolateMaxY = interpolateMaxY;
+    rdr->_texture_txMin = txMin;
+    rdr->_texture_tyMin = tyMin;
+    rdr->_texture_txMax = txMax;
+    rdr->_texture_tyMax = tyMax;
 
     rdr->_texture_m00 = compoundTransform.m00;
     rdr->_texture_m01 = compoundTransform.m01;
--- a/modules/graphics/src/main/native-prism-sw/PiscesUtil.h	Wed Oct 23 09:51:45 2013 +0200
+++ b/modules/graphics/src/main/native-prism-sw/PiscesUtil.h	Wed Oct 23 13:29:25 2013 +0200
@@ -35,6 +35,14 @@
 
 #include <PiscesSysutils.h>
 
+#ifdef PISCES_DEBUG_FLAG
+#define PISCES_DEBUG(...) printf(__VAR_ARGS__)
+#define PISCES_DEBUG_FLUSH(x) fflush(x)
+#else
+#define PISCES_DEBUG(...) /* (__VAR_ARGS__) */
+#define PISCES_DEBUG_FLUSH(x)
+#endif
+
 #ifndef ABS
 /**
  * @def ABS(x)