summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2008-03-21 03:08:24 -0700
committerKeith Packard <keithp@keithp.com>2008-03-21 03:12:36 -0700
commit645980596450ed21c3b8927410a6bfe38a0c55d1 (patch)
treedd5ab9dbbc1786fd5c631d2a181aaaa9b3f1c39a
parentbf725b92cf93d74a6f414f81f319dddbc2c78525 (diff)
Transformed coord computed using floats. Don't move bilinear composite dst.
The homogeneous coordinate computation in the core server cannot be used for many legal matrices as it overflows. Just use floats in the driver; faster and avoids troubles. When compositing with bilinear filter, don't push the dst coordinates around as that makes the output blurry when pixels are aligned.
-rw-r--r--src/i830.h5
-rw-r--r--src/i830_exa.c55
-rw-r--r--src/i830_render.c118
-rw-r--r--src/i915_render.c10
-rw-r--r--src/i965_render.c42
5 files changed, 143 insertions, 87 deletions
diff --git a/src/i830.h b/src/i830.h
index c84e8023..1319c6a0 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -524,6 +524,7 @@ typedef struct _I830Rec {
float scale_units[2][2];
/** Transform pointers for src/mask, or NULL if identity */
PictTransform *transform[2];
+ float coord_adjust;
/* i915 EXA render state */
uint32_t mapstate[6];
uint32_t samplerstate[6];
@@ -827,11 +828,11 @@ Bool i965_prepare_composite(int op, PicturePtr pSrc, PicturePtr pMask,
void i965_composite(PixmapPtr pDst, int srcX, int srcY,
int maskX, int maskY, int dstX, int dstY, int w, int h);
-void
+Bool
i830_get_transformed_coordinates(int x, int y, PictTransformPtr transform,
float *x_out, float *y_out);
-void
+Bool
i830_get_transformed_coordinates_3d(int x, int y, PictTransformPtr transform,
float *x_out, float *y_out, float *z_out);
diff --git a/src/i830_exa.c b/src/i830_exa.c
index f9df277e..9b5bb936 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -339,12 +339,31 @@ I830EXADoneCopy(PixmapPtr pDstPixmap)
#define xFixedToFloat(val) \
((float)xFixedToInt(val) + ((float)xFixedFrac(val) / 65536.0))
+static Bool
+_i830_transform_point (PictTransformPtr transform,
+ float x,
+ float y,
+ float result[3])
+{
+ int j;
+
+ for (j = 0; j < 3; j++)
+ {
+ result[j] = (xFixedToFloat (transform->matrix[j][0]) * x +
+ xFixedToFloat (transform->matrix[j][1]) * y +
+ xFixedToFloat (transform->matrix[j][2]));
+ }
+ if (!result[2])
+ return FALSE;
+ return TRUE;
+}
+
/**
* Returns the floating-point coordinates transformed by the given transform.
*
* transform may be null.
*/
-void
+Bool
i830_get_transformed_coordinates(int x, int y, PictTransformPtr transform,
float *x_out, float *y_out)
{
@@ -352,15 +371,14 @@ i830_get_transformed_coordinates(int x, int y, PictTransformPtr transform,
*x_out = x;
*y_out = y;
} else {
- PictVector v;
-
- v.vector[0] = IntToxFixed(x);
- v.vector[1] = IntToxFixed(y);
- v.vector[2] = xFixed1;
- PictureTransformPoint(transform, &v);
- *x_out = xFixedToFloat(v.vector[0]);
- *y_out = xFixedToFloat(v.vector[1]);
+ float result[3];
+
+ if (!_i830_transform_point (transform, (float) x, (float) y, result))
+ return FALSE;
+ *x_out = result[0] / result[2];
+ *y_out = result[1] / result[2];
}
+ return TRUE;
}
/**
@@ -368,7 +386,7 @@ i830_get_transformed_coordinates(int x, int y, PictTransformPtr transform,
*
* transform may be null.
*/
-void
+Bool
i830_get_transformed_coordinates_3d(int x, int y, PictTransformPtr transform,
float *x_out, float *y_out, float *w_out)
{
@@ -377,16 +395,15 @@ i830_get_transformed_coordinates_3d(int x, int y, PictTransformPtr transform,
*y_out = y;
*w_out = 1;
} else {
- PictVector v;
-
- v.vector[0] = IntToxFixed(x);
- v.vector[1] = IntToxFixed(y);
- v.vector[2] = xFixed1;
- PictureTransformPoint3d(transform, &v);
- *x_out = xFixedToFloat(v.vector[0]);
- *y_out = xFixedToFloat(v.vector[1]);
- *w_out = xFixedToFloat(v.vector[2]);
+ float result[3];
+
+ if (!_i830_transform_point (transform, (float) x, (float) y, result))
+ return FALSE;
+ *x_out = result[0];
+ *y_out = result[1];
+ *w_out = result[2];
}
+ return TRUE;
}
/**
diff --git a/src/i830_render.c b/src/i830_render.c
index 87543ef6..195e9a8c 100644
--- a/src/i830_render.c
+++ b/src/i830_render.c
@@ -396,6 +396,7 @@ i830_prepare_composite(int op, PicturePtr pSrcPicture,
I830Ptr pI830 = I830PTR(pScrn);
uint32_t dst_format, dst_offset, dst_pitch;
Bool is_affine_src, is_affine_mask;
+ Bool is_nearest = FALSE;
IntelEmitInvarientState(pScrn);
*pI830->last_3d = LAST_3D_RENDER;
@@ -407,9 +408,13 @@ i830_prepare_composite(int op, PicturePtr pSrcPicture,
if (!i830_texture_setup(pSrcPicture, pSrc, 0))
I830FALLBACK("fail to setup src texture\n");
+ if (pSrcPicture->filter == PictFilterNearest)
+ is_nearest = TRUE;
if (pMask != NULL) {
if (!i830_texture_setup(pMaskPicture, pMask, 1))
I830FALLBACK("fail to setup mask texture\n");
+ if (pMaskPicture->filter == PictFilterNearest)
+ is_nearest = TRUE;
} else {
pI830->transform[1] = NULL;
pI830->scale_units[1][0] = -1;
@@ -419,6 +424,11 @@ i830_prepare_composite(int op, PicturePtr pSrcPicture,
is_affine_src = i830_transform_is_affine (pI830->transform[0]);
is_affine_mask = i830_transform_is_affine (pI830->transform[1]);
+ if (is_nearest)
+ pI830->coord_adjust = -0.125;
+ else
+ pI830->coord_adjust = 0;
+
if (!is_affine_src || !is_affine_mask)
I830FALLBACK("non-affine transform unsupported on 8xx hardware\n");
@@ -591,56 +601,68 @@ i830_composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
per_vertex = 2; /* dest x/y */
if (is_affine_src)
{
- i830_get_transformed_coordinates(srcX, srcY,
- pI830->transform[0],
- &src_x[0], &src_y[0]);
- i830_get_transformed_coordinates(srcX, srcY + h,
- pI830->transform[0],
- &src_x[1], &src_y[1]);
- i830_get_transformed_coordinates(srcX + w, srcY + h,
- pI830->transform[0],
- &src_x[2], &src_y[2]);
+ if (!i830_get_transformed_coordinates(srcX, srcY,
+ pI830->transform[0],
+ &src_x[0], &src_y[0]))
+ return;
+ if (!i830_get_transformed_coordinates(srcX, srcY + h,
+ pI830->transform[0],
+ &src_x[1], &src_y[1]))
+ return;
+ if (!i830_get_transformed_coordinates(srcX + w, srcY + h,
+ pI830->transform[0],
+ &src_x[2], &src_y[2]))
+ return;
per_vertex += 2; /* src x/y */
} else {
- i830_get_transformed_coordinates_3d(srcX, srcY,
- pI830->transform[0],
- &src_x[0], &src_y[0],
- &src_w[0]);
- i830_get_transformed_coordinates_3d(srcX, srcY + h,
- pI830->transform[0],
- &src_x[1], &src_y[1],
- &src_w[1]);
- i830_get_transformed_coordinates_3d(srcX + w, srcY + h,
- pI830->transform[0],
- &src_x[2], &src_y[2],
- &src_w[2]);
+ if (!i830_get_transformed_coordinates_3d(srcX, srcY,
+ pI830->transform[0],
+ &src_x[0], &src_y[0],
+ &src_w[0]))
+ return;
+ if (!i830_get_transformed_coordinates_3d(srcX, srcY + h,
+ pI830->transform[0],
+ &src_x[1], &src_y[1],
+ &src_w[1]))
+ return;
+ if (!i830_get_transformed_coordinates_3d(srcX + w, srcY + h,
+ pI830->transform[0],
+ &src_x[2], &src_y[2],
+ &src_w[2]))
+ return;
per_vertex += 4; /* src x/y/z/w */
}
if (has_mask) {
if (is_affine_mask) {
- i830_get_transformed_coordinates(maskX, maskY,
- pI830->transform[1],
- &mask_x[0], &mask_y[0]);
- i830_get_transformed_coordinates(maskX, maskY + h,
- pI830->transform[1],
- &mask_x[1], &mask_y[1]);
- i830_get_transformed_coordinates(maskX + w, maskY + h,
- pI830->transform[1],
- &mask_x[2], &mask_y[2]);
+ if (!i830_get_transformed_coordinates(maskX, maskY,
+ pI830->transform[1],
+ &mask_x[0], &mask_y[0]))
+ return;
+ if (!i830_get_transformed_coordinates(maskX, maskY + h,
+ pI830->transform[1],
+ &mask_x[1], &mask_y[1]))
+ return;
+ if (!i830_get_transformed_coordinates(maskX + w, maskY + h,
+ pI830->transform[1],
+ &mask_x[2], &mask_y[2]))
+ return;
per_vertex += 2; /* mask x/y */
} else {
- i830_get_transformed_coordinates_3d(maskX, maskY,
- pI830->transform[1],
- &mask_x[0], &mask_y[0],
- &mask_w[0]);
- i830_get_transformed_coordinates_3d(maskX, maskY + h,
- pI830->transform[1],
- &mask_x[1], &mask_y[1],
- &mask_w[1]);
- i830_get_transformed_coordinates_3d(maskX + w, maskY + h,
- pI830->transform[1],
- &mask_x[2], &mask_y[2],
- &mask_w[2]);
+ if (!i830_get_transformed_coordinates_3d(maskX, maskY,
+ pI830->transform[1],
+ &mask_x[0], &mask_y[0],
+ &mask_w[0]))
+ return;
+ if (!i830_get_transformed_coordinates_3d(maskX, maskY + h,
+ pI830->transform[1],
+ &mask_x[1], &mask_y[1],
+ &mask_w[1]))
+ return;
+ if (!i830_get_transformed_coordinates_3d(maskX + w, maskY + h,
+ pI830->transform[1],
+ &mask_x[2], &mask_y[2],
+ &mask_w[2]))
+ return;
per_vertex += 4; /* mask x/y/z/w */
}
}
@@ -655,8 +677,8 @@ i830_composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
OUT_BATCH(MI_NOOP);
OUT_BATCH(PRIM3D_INLINE | PRIM3D_RECTLIST | (num_floats-1));
- OUT_BATCH_F(-0.125 + dstX + w);
- OUT_BATCH_F(-0.125 + dstY + h);
+ OUT_BATCH_F(pI830->coord_adjust + dstX + w);
+ OUT_BATCH_F(pI830->coord_adjust + dstY + h);
OUT_BATCH_F(src_x[2] / pI830->scale_units[0][0]);
OUT_BATCH_F(src_y[2] / pI830->scale_units[0][1]);
if (!is_affine_src) {
@@ -672,8 +694,8 @@ i830_composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
}
}
- OUT_BATCH_F(-0.125 + dstX);
- OUT_BATCH_F(-0.125 + dstY + h);
+ OUT_BATCH_F(pI830->coord_adjust + dstX);
+ OUT_BATCH_F(pI830->coord_adjust + dstY + h);
OUT_BATCH_F(src_x[1] / pI830->scale_units[0][0]);
OUT_BATCH_F(src_y[1] / pI830->scale_units[0][1]);
if (!is_affine_src) {
@@ -689,8 +711,8 @@ i830_composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
}
}
- OUT_BATCH_F(-0.125 + dstX);
- OUT_BATCH_F(-0.125 + dstY);
+ OUT_BATCH_F(pI830->coord_adjust + dstX);
+ OUT_BATCH_F(pI830->coord_adjust + dstY);
OUT_BATCH_F(src_x[0] / pI830->scale_units[0][0]);
OUT_BATCH_F(src_y[0] / pI830->scale_units[0][1]);
if (!is_affine_src) {
diff --git a/src/i915_render.c b/src/i915_render.c
index 9c6da095..2b9ed04e 100644
--- a/src/i915_render.c
+++ b/src/i915_render.c
@@ -321,6 +321,7 @@ i915_prepare_composite(int op, PicturePtr pSrcPicture,
int out_reg = FS_OC;
FS_LOCALS(20);
Bool is_affine_src, is_affine_mask;
+ Bool is_nearest = FALSE;
IntelEmitInvarientState(pScrn);
*pI830->last_3d = LAST_3D_RENDER;
@@ -332,9 +333,13 @@ i915_prepare_composite(int op, PicturePtr pSrcPicture,
if (!i915_texture_setup(pSrcPicture, pSrc, 0))
I830FALLBACK("fail to setup src texture\n");
+ if (pSrcPicture->filter == PictFilterNearest)
+ is_nearest = TRUE;
if (pMask != NULL) {
if (!i915_texture_setup(pMaskPicture, pMask, 1))
I830FALLBACK("fail to setup mask texture\n");
+ if (pMaskPicture->filter == PictFilterNearest)
+ is_nearest = TRUE;
} else {
pI830->transform[1] = NULL;
pI830->scale_units[1][0] = -1;
@@ -343,6 +348,11 @@ i915_prepare_composite(int op, PicturePtr pSrcPicture,
is_affine_src = i830_transform_is_affine (pI830->transform[0]);
is_affine_mask = i830_transform_is_affine (pI830->transform[1]);
+ if (is_nearest)
+ pI830->coord_adjust = -0.125;
+ else
+ pI830->coord_adjust = 0;
+
if (pMask == NULL) {
BEGIN_BATCH(10);
OUT_BATCH(_3DSTATE_MAP_STATE | 3);
diff --git a/src/i965_render.c b/src/i965_render.c
index ada3919a..93583b0a 100644
--- a/src/i965_render.c
+++ b/src/i965_render.c
@@ -1093,29 +1093,35 @@ i965_composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
float src_x[3], src_y[3], mask_x[3], mask_y[3];
int i;
- i830_get_transformed_coordinates(srcX, srcY,
- pI830->transform[0],
- &src_x[0], &src_y[0]);
- i830_get_transformed_coordinates(srcX, srcY + h,
- pI830->transform[0],
- &src_x[1], &src_y[1]);
- i830_get_transformed_coordinates(srcX + w, srcY + h,
- pI830->transform[0],
- &src_x[2], &src_y[2]);
+ if (!i830_get_transformed_coordinates(srcX, srcY,
+ pI830->transform[0],
+ &src_x[0], &src_y[0]))
+ return;
+ if (!i830_get_transformed_coordinates(srcX, srcY + h,
+ pI830->transform[0],
+ &src_x[1], &src_y[1]))
+ return;
+ if (!i830_get_transformed_coordinates(srcX + w, srcY + h,
+ pI830->transform[0],
+ &src_x[2], &src_y[2]))
+ return;
if (pI830->scale_units[1][0] == -1 || pI830->scale_units[1][1] == -1) {
has_mask = FALSE;
} else {
has_mask = TRUE;
- i830_get_transformed_coordinates(maskX, maskY,
- pI830->transform[1],
- &mask_x[0], &mask_y[0]);
- i830_get_transformed_coordinates(maskX, maskY + h,
- pI830->transform[1],
- &mask_x[1], &mask_y[1]);
- i830_get_transformed_coordinates(maskX + w, maskY + h,
- pI830->transform[1],
- &mask_x[2], &mask_y[2]);
+ if (!i830_get_transformed_coordinates(maskX, maskY,
+ pI830->transform[1],
+ &mask_x[0], &mask_y[0]))
+ return;
+ if (!i830_get_transformed_coordinates(maskX, maskY + h,
+ pI830->transform[1],
+ &mask_x[1], &mask_y[1]))
+ return;
+ if (!i830_get_transformed_coordinates(maskX + w, maskY + h,
+ pI830->transform[1],
+ &mask_x[2], &mask_y[2]))
+ return;
}
/* Wait for any existing composite rectangles to land before we overwrite