[PATCH 2/2] glamor: Use float matrix for render transformations
walter harms
wharms at bfs.de
Mon Aug 18 10:37:19 PDT 2014
Am 18.08.2014 18:31, schrieb Siarhei Siamashka:
> On Sun, 17 Aug 2014 14:16:26 -0700
> Keith Packard <keithp at keithp.com> wrote:
>
>> Now that the core X server exposes pixman_f_transform matrices in each
>> picture with a transform, use those instead of the fixed point matrices.
>>
>> Signed-off-by: Keith Packard <keithp at keithp.com>
>> ---
>> glamor/glamor_render.c | 17 ++++++-----------
>> glamor/glamor_utils.h | 20 --------------------
>> 2 files changed, 6 insertions(+), 31 deletions(-)
>>
>> diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c
>> index 2386f2e..03a7b63 100644
>> --- a/glamor/glamor_render.c
>> +++ b/glamor/glamor_render.c
>> @@ -790,7 +790,7 @@ combine_pict_format(PictFormatShort * des, const PictFormatShort src,
>> static void
>> glamor_set_normalize_tcoords_generic(glamor_pixmap_private *priv,
>> int repeat_type,
>> - float *matrix,
>> + double *matrix,
>> float xscale, float yscale,
>> int x1, int y1, int x2, int y2,
>> float *texcoords,
>> @@ -1164,8 +1164,7 @@ glamor_composite_with_shader(CARD8 op,
>> int source_x_off, source_y_off;
>> int mask_x_off, mask_y_off;
>> PictFormatShort saved_source_format = 0;
>> - float src_matrix[9], mask_matrix[9];
>> - float *psrc_matrix = NULL, *pmask_matrix = NULL;
>> + double *psrc_matrix = NULL, *pmask_matrix = NULL;
>> int nrect_max;
>> Bool ret = FALSE;
>> glamor_composite_shader *shader = NULL, *shader_ca = NULL;
>> @@ -1210,10 +1209,8 @@ glamor_composite_with_shader(CARD8 op,
>> glamor_get_drawable_deltas(source->pDrawable,
>> source_pixmap, &source_x_off, &source_y_off);
>> pixmap_priv_get_scale(source_pixmap_priv, &src_xscale, &src_yscale);
>> - if (source->transform) {
>> - psrc_matrix = src_matrix;
>> - glamor_picture_get_matrixf(source, psrc_matrix);
>> - }
>> + if (source->transform)
>> + psrc_matrix = &(PictureTransformFloat(source)->m[0][0]);
>> }
>>
>> if (glamor_priv->has_mask_coords) {
>> @@ -1221,10 +1218,8 @@ glamor_composite_with_shader(CARD8 op,
>> glamor_get_drawable_deltas(mask->pDrawable, mask_pixmap,
>> &mask_x_off, &mask_y_off);
>> pixmap_priv_get_scale(mask_pixmap_priv, &mask_xscale, &mask_yscale);
>> - if (mask->transform) {
>> - pmask_matrix = mask_matrix;
>> - glamor_picture_get_matrixf(mask, pmask_matrix);
>> - }
>> + if (mask->transform)
>> + pmask_matrix = &(PictureTransformFloat(mask)->m[0][0]);
>> }
>>
>> nrect_max = MIN(nrect, GLAMOR_COMPOSITE_VBO_VERT_CNT / 4);
>> diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h
>> index c15d17c..29f221f 100644
>> --- a/glamor/glamor_utils.h
>> +++ b/glamor/glamor_utils.h
>> @@ -91,26 +91,6 @@
>> } \
>> } while(0)
>>
>> -#define xFixedToFloat(_val_) ((float)xFixedToInt(_val_) \
>> - + ((float)xFixedFrac(_val_) / 65536.0))
>> -
>> -#define glamor_picture_get_matrixf(_picture_, _matrix_) \
>> - do { \
>> - int _i_; \
>> - if ((_picture_)->transform) \
>> - { \
>> - for(_i_ = 0; _i_ < 3; _i_++) \
>> - { \
>> - (_matrix_)[_i_ * 3 + 0] = \
>> - xFixedToFloat((_picture_)->transform->matrix[_i_][0]); \
>> - (_matrix_)[_i_ * 3 + 1] = \
>> - xFixedToFloat((_picture_)->transform->matrix[_i_][1]); \
>> - (_matrix_)[_i_ * 3 + 2] = \
>> - xFixedToFloat((_picture_)->transform->matrix[_i_][2]); \
>> - } \
>> - } \
>> - } while(0)
>> -
>> #define fmod(x, w) (x - w * floor((float)x/w))
>>
>> #define fmodulus(x, w, c) do {c = fmod(x, w); \
>
> Okay, now I see what's going on. The old glamor code used to convert
> the 16.16 fixed point values to 32-bit floats. This is definitely not
> great because of http://en.wikipedia.org/wiki/Rounding#Double_rounding
> on the "64-bit float" -> "16.16 fixed point" -> "32-bit float"
> conversion path. Directly passing 32-bit floats to XRENDER should
> somewhat mitigate the accuracy loss, but not totally eliminate it.
>
> The fundamental problem here is that 16.16 fixed point is exactly
> borderline accurate. Any 16.16 fixed point value, with the integer part
> larger than 256, is going to lose some fractional bits when converted to
> 32-bit float (which only has 24-bit mantissa). The 32-bit floating
> point format is somewhat less accurate than necessary for XRENDER.
>
> And the introduction of the 32-bit floating point format in the
> protocol is going to be really harmful. If the new applications start
> using it for the sake of glamor, then the existing users of software
> rendering drivers (which used to be perfectly fine until now), are
> going to be messed up by the "64-bit float" -> "32-bit float" -> "16.16
> fixed point" double rounding penalty. Using the 64-bit floating point
> format in the protocol is not so bad, because it can store 16.16 fixed
> point values without any accuracy loss. However there would be some
> performance penalty, caused by the extra conversion. That's the usual
> "pick your poison" situation.
>
> Is the accuracy actually good enough with this patch applied and solves
> the "off by several pixels" problem? The patch still looks messed up
> with the use of a mix of double and float.
>
So it would be better to use the 16.16 format for transfer and use double
for internal calculations ?
re,
wh
More information about the xorg-devel
mailing list