summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZack Rusin <[email protected]>2009-10-13 13:06:39 -0400
committerZack Rusin <[email protected]>2009-10-19 23:45:31 -0400
commita39a3cc14e816cc91a81028a27c4dbd4816cdc9d (patch)
tree4f43ce8771d86403c1310806032c7e4881ea4359
parente5f1f6a0bece3d035bf5ac1685b5335af4862cea (diff)
st/xorg: implement basic src/mask transformations
plus fix filters
-rw-r--r--src/gallium/state_trackers/xorg/Makefile1
-rw-r--r--src/gallium/state_trackers/xorg/xorg_composite.c126
-rw-r--r--src/gallium/state_trackers/xorg/xorg_exa.c2
-rw-r--r--src/gallium/state_trackers/xorg/xorg_exa.h8
-rw-r--r--src/gallium/state_trackers/xorg/xorg_renderer.c130
-rw-r--r--src/gallium/state_trackers/xorg/xorg_renderer.h4
6 files changed, 231 insertions, 40 deletions
diff --git a/src/gallium/state_trackers/xorg/Makefile b/src/gallium/state_trackers/xorg/Makefile
index 27a1990724d..030bac5fff2 100644
--- a/src/gallium/state_trackers/xorg/Makefile
+++ b/src/gallium/state_trackers/xorg/Makefile
@@ -5,6 +5,7 @@ LIBNAME = xorgtracker
LIBRARY_INCLUDES = \
-DHAVE_CONFIG_H \
+ -DHAVE_XEXTPROTO_71=1 \
$(shell pkg-config --cflags-only-I pixman-1 xorg-server libdrm xproto) \
-I$(TOP)/src/gallium/include \
-I$(TOP)/src/gallium/auxiliary \
diff --git a/src/gallium/state_trackers/xorg/xorg_composite.c b/src/gallium/state_trackers/xorg/xorg_composite.c
index d6483fb72c4..7379e3b7461 100644
--- a/src/gallium/state_trackers/xorg/xorg_composite.c
+++ b/src/gallium/state_trackers/xorg/xorg_composite.c
@@ -9,6 +9,9 @@
#include "pipe/p_inlines.h"
+/*XXX also in Xrender.h but the including it here breaks compilition */
+#define XFixedToDouble(f) (((double) (f)) / 65536.)
+
struct xorg_composite_blend {
int op:8;
@@ -144,6 +147,43 @@ render_repeat_to_gallium(int mode)
return PIPE_TEX_WRAP_REPEAT;
}
+static INLINE boolean
+render_filter_to_gallium(int xrender_filter, int *out_filter)
+{
+
+ switch (xrender_filter) {
+ case PictFilterNearest:
+ *out_filter = PIPE_TEX_FILTER_NEAREST;
+ break;
+ case PictFilterBilinear:
+ *out_filter = PIPE_TEX_FILTER_LINEAR;
+ break;
+ case PictFilterFast:
+ *out_filter = PIPE_TEX_FILTER_NEAREST;
+ break;
+ case PictFilterGood:
+ *out_filter = PIPE_TEX_FILTER_LINEAR;
+ break;
+ case PictFilterBest:
+ *out_filter = PIPE_TEX_FILTER_LINEAR;
+ break;
+ default:
+ debug_printf("Unkown xrender filter");
+ *out_filter = PIPE_TEX_FILTER_NEAREST;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static boolean is_filter_accelerated(PicturePtr pic)
+{
+ int filter;
+ if (pic && !render_filter_to_gallium(pic->filter, &filter))
+ return FALSE;
+ return TRUE;
+}
+
boolean xorg_composite_accelerated(int op,
PicturePtr pSrcPicture,
PicturePtr pMaskPicture,
@@ -156,6 +196,11 @@ boolean xorg_composite_accelerated(int op,
unsigned accel_ops_count =
sizeof(accelerated_ops)/sizeof(struct acceleration_info);
+ if (!is_filter_accelerated(pSrcPicture) ||
+ !is_filter_accelerated(pMaskPicture)) {
+ XORG_FALLBACK("Unsupported Xrender filter");
+ }
+
if (pSrcPicture->pSourcePict) {
if (pSrcPicture->pSourcePict->type != SourcePictTypeSolidFill)
XORG_FALLBACK("gradients not enabled (haven't been well tested)");
@@ -163,13 +208,10 @@ boolean xorg_composite_accelerated(int op,
for (i = 0; i < accel_ops_count; ++i) {
if (op == accelerated_ops[i].op) {
- /* Check for unsupported component alpha */
- if ((pSrcPicture->componentAlpha &&
- !accelerated_ops[i].component_alpha) ||
- (pMaskPicture &&
- (!accelerated_ops[i].with_mask ||
- (pMaskPicture->componentAlpha &&
- !accelerated_ops[i].component_alpha))))
+ /* Check for component alpha */
+ if (pMaskPicture &&
+ (pMaskPicture->componentAlpha ||
+ (!accelerated_ops[i].with_mask)))
XORG_FALLBACK("component alpha unsupported (PictOpOver=%s(%d)",
(accelerated_ops[i].op == PictOpOver) ? "yes" : "no",
accelerated_ops[i].op);
@@ -238,7 +280,6 @@ bind_shaders(struct exa_context *exa, int op,
cso_set_fragment_shader_handle(exa->renderer->cso, shader.fs);
}
-
static void
bind_samplers(struct exa_context *exa, int op,
PicturePtr pSrcPicture, PicturePtr pMaskPicture,
@@ -264,10 +305,15 @@ bind_samplers(struct exa_context *exa, int op,
if (pSrcPicture && pSrc) {
unsigned src_wrap = render_repeat_to_gallium(
pSrcPicture->repeatType);
+ int filter;
+
+ render_filter_to_gallium(pSrcPicture->filter, &filter);
+
src_sampler.wrap_s = src_wrap;
src_sampler.wrap_t = src_wrap;
- src_sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
- src_sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
+ src_sampler.min_img_filter = filter;
+ src_sampler.mag_img_filter = filter;
+ src_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST;
src_sampler.normalized_coords = 1;
samplers[0] = &src_sampler;
exa->bound_textures[0] = pSrc->tex;
@@ -277,10 +323,15 @@ bind_samplers(struct exa_context *exa, int op,
if (pMaskPicture && pMask) {
unsigned mask_wrap = render_repeat_to_gallium(
pMaskPicture->repeatType);
+ int filter;
+
+ render_filter_to_gallium(pMaskPicture->filter, &filter);
+
mask_sampler.wrap_s = mask_wrap;
mask_sampler.wrap_t = mask_wrap;
- mask_sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
- mask_sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
+ mask_sampler.min_img_filter = filter;
+ mask_sampler.mag_img_filter = filter;
+ src_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST;
mask_sampler.normalized_coords = 1;
samplers[1] = &mask_sampler;
exa->bound_textures[1] = pMask->tex;
@@ -328,6 +379,44 @@ setup_constant_buffers(struct exa_context *exa, struct exa_pixmap_priv *pDst)
setup_fs_constant_buffer(exa);
}
+static INLINE boolean matrix_from_pict_transform(PictTransform *trans, float *matrix)
+{
+ if (!trans)
+ return FALSE;
+
+ matrix[0] = XFixedToDouble(trans->matrix[0][0]);
+ matrix[1] = XFixedToDouble(trans->matrix[0][1]);
+ matrix[2] = XFixedToDouble(trans->matrix[0][2]);
+
+ matrix[3] = XFixedToDouble(trans->matrix[1][0]);
+ matrix[4] = XFixedToDouble(trans->matrix[1][1]);
+ matrix[5] = XFixedToDouble(trans->matrix[1][2]);
+
+ matrix[6] = XFixedToDouble(trans->matrix[2][0]);
+ matrix[7] = XFixedToDouble(trans->matrix[2][1]);
+ matrix[8] = XFixedToDouble(trans->matrix[2][2]);
+
+ return TRUE;
+}
+
+static void
+setup_transforms(struct exa_context *exa,
+ PicturePtr pSrcPicture, PicturePtr pMaskPicture)
+{
+ PictTransform *src_t = NULL;
+ PictTransform *mask_t = NULL;
+
+ if (pSrcPicture)
+ src_t = pSrcPicture->transform;
+ if (pMaskPicture)
+ mask_t = pMaskPicture->transform;
+
+ exa->transform.has_src =
+ matrix_from_pict_transform(src_t, exa->transform.src);
+ exa->transform.has_mask =
+ matrix_from_pict_transform(mask_t, exa->transform.mask);
+}
+
boolean xorg_composite_bind_state(struct exa_context *exa,
int op,
PicturePtr pSrcPicture,
@@ -346,6 +435,8 @@ boolean xorg_composite_bind_state(struct exa_context *exa,
pDstPicture, pSrc, pMask, pDst);
setup_constant_buffers(exa, pDst);
+ setup_transforms(exa, pSrcPicture, pMaskPicture);
+
return TRUE;
}
@@ -360,10 +451,19 @@ void xorg_composite(struct exa_context *exa,
exa->solid_color);
} else {
int pos[6] = {srcX, srcY, maskX, maskY, dstX, dstY};
+ float *src_matrix = NULL;
+ float *mask_matrix = NULL;
+
+ if (exa->transform.has_src)
+ src_matrix = exa->transform.src;
+ if (exa->transform.has_mask)
+ mask_matrix = exa->transform.mask;
+
renderer_draw_textures(exa->renderer,
pos, width, height,
exa->bound_textures,
- exa->num_bound_samplers);
+ exa->num_bound_samplers,
+ src_matrix, mask_matrix);
}
}
diff --git a/src/gallium/state_trackers/xorg/xorg_exa.c b/src/gallium/state_trackers/xorg/xorg_exa.c
index ca25d905579..39c4d26ebe8 100644
--- a/src/gallium/state_trackers/xorg/xorg_exa.c
+++ b/src/gallium/state_trackers/xorg/xorg_exa.c
@@ -92,6 +92,8 @@ xorg_exa_common_done(struct exa_context *exa)
{
exa->copy.src = NULL;
exa->copy.dst = NULL;
+ exa->transform.has_src = FALSE;
+ exa->transform.has_mask = FALSE;
exa->has_solid_color = FALSE;
exa->num_bound_samplers = 0;
}
diff --git a/src/gallium/state_trackers/xorg/xorg_exa.h b/src/gallium/state_trackers/xorg/xorg_exa.h
index 292f964cec6..45f88d94048 100644
--- a/src/gallium/state_trackers/xorg/xorg_exa.h
+++ b/src/gallium/state_trackers/xorg/xorg_exa.h
@@ -24,6 +24,14 @@ struct exa_context
float solid_color[4];
boolean has_solid_color;
+ /* float[9] projective matrix bound to pictures */
+ struct {
+ float src[9];
+ float mask[9];
+ boolean has_src;
+ boolean has_mask;
+ } transform;
+
struct {
struct exa_pixmap_priv *src;
struct exa_pixmap_priv *dst;
diff --git a/src/gallium/state_trackers/xorg/xorg_renderer.c b/src/gallium/state_trackers/xorg/xorg_renderer.c
index ca69e1e0e92..3dd5e6e811d 100644
--- a/src/gallium/state_trackers/xorg/xorg_renderer.c
+++ b/src/gallium/state_trackers/xorg/xorg_renderer.c
@@ -11,11 +11,39 @@
#include "pipe/p_inlines.h"
+#include <math.h>
+
enum AxisOrientation {
Y0_BOTTOM,
Y0_TOP
};
+#define floatsEqual(x, y) (fabs(x - y) <= 0.00001f * MIN2(fabs(x), fabs(y)))
+#define floatIsZero(x) (floatsEqual((x) + 1, 1))
+
+static INLINE boolean is_affine(float *matrix)
+{
+ return floatIsZero(matrix[2]) && floatIsZero(matrix[5])
+ && floatsEqual(matrix[8], 1);
+}
+static INLINE void map_point(float *mat, float x, float y,
+ float *out_x, float *out_y)
+{
+ if (!mat) {
+ *out_x = x;
+ *out_y = y;
+ return;
+ }
+
+ *out_x = mat[0]*x + mat[3]*y + mat[6];
+ *out_y = mat[1]*x + mat[4]*y + mat[7];
+ if (!is_affine(mat)) {
+ float w = 1/(mat[2]*x + mat[5]*y + mat[8]);
+ *out_x *= w;
+ *out_y *= w;
+ }
+}
+
static void
renderer_init_state(struct xorg_renderer *r)
{
@@ -60,23 +88,38 @@ static struct pipe_buffer *
setup_vertex_data1(struct xorg_renderer *r,
int srcX, int srcY, int dstX, int dstY,
int width, int height,
- struct pipe_texture *src)
+ struct pipe_texture *src, float *src_matrix)
{
- float s0, t0, s1, t1;
+ float s0, t0, s1, t1, stmp, ttmp;
s0 = srcX / src->width[0];
s1 = srcX + width / src->width[0];
t0 = srcY / src->height[0];
t1 = srcY + height / src->height[0];
- /* 1st vertex */
- setup_vertex1(r->vertices2[0], dstX, dstY, s0, t0);
- /* 2nd vertex */
- setup_vertex1(r->vertices2[1], dstX + width, dstY, s1, t0);
- /* 3rd vertex */
- setup_vertex1(r->vertices2[2], dstX + width, dstY + height, s1, t1);
- /* 4th vertex */
- setup_vertex1(r->vertices2[3], dstX, dstY + height, s0, t1);
+ if (src_matrix) {
+ /* 1st vertex */
+ map_point(src_matrix, s0, t0, &stmp, &ttmp);
+ setup_vertex1(r->vertices2[0], dstX, dstY, stmp, ttmp);
+ /* 2nd vertex */
+ map_point(src_matrix, s1, t0, &stmp, &ttmp);
+ setup_vertex1(r->vertices2[1], dstX + width, dstY, stmp, ttmp);
+ /* 3rd vertex */
+ map_point(src_matrix, s1, t1, &stmp, &ttmp);
+ setup_vertex1(r->vertices2[2], dstX + width, dstY + height, stmp, ttmp);
+ /* 4th vertex */
+ map_point(src_matrix, s0, t1, &stmp, &ttmp);
+ setup_vertex1(r->vertices2[3], dstX, dstY + height, stmp, ttmp);
+ } else {
+ /* 1st vertex */
+ setup_vertex1(r->vertices2[0], dstX, dstY, s0, t0);
+ /* 2nd vertex */
+ setup_vertex1(r->vertices2[1], dstX + width, dstY, s1, t0);
+ /* 3rd vertex */
+ setup_vertex1(r->vertices2[2], dstX + width, dstY + height, s1, t1);
+ /* 4th vertex */
+ setup_vertex1(r->vertices2[3], dstX, dstY + height, s0, t1);
+ }
return pipe_user_buffer_create(r->pipe->screen,
r->vertices2,
@@ -128,9 +171,11 @@ setup_vertex_data2(struct xorg_renderer *r,
int srcX, int srcY, int maskX, int maskY,
int dstX, int dstY, int width, int height,
struct pipe_texture *src,
- struct pipe_texture *mask)
+ struct pipe_texture *mask,
+ float *src_matrix, float *mask_matrix)
{
float st0[4], st1[4];
+ float pt0[2], pt1[2];
st0[0] = srcX / src->width[0];
st0[1] = srcY / src->height[0];
@@ -142,18 +187,49 @@ setup_vertex_data2(struct xorg_renderer *r,
st1[2] = maskX + width / mask->width[0];
st1[3] = maskY + height / mask->height[0];
- /* 1st vertex */
- setup_vertex2(r->vertices3[0], dstX, dstY,
- st0[0], st0[1], st1[0], st1[1]);
- /* 2nd vertex */
- setup_vertex2(r->vertices3[1], dstX + width, dstY,
- st0[2], st0[1], st1[2], st1[1]);
- /* 3rd vertex */
- setup_vertex2(r->vertices3[2], dstX + width, dstY + height,
- st0[2], st0[3], st1[2], st1[3]);
- /* 4th vertex */
- setup_vertex2(r->vertices3[3], dstX, dstY + height,
- st0[0], st0[3], st1[0], st1[3]);
+ if (src_matrix || mask_matrix) {
+ /* 1st vertex */
+ map_point(src_matrix, st0[0], st0[1],
+ pt0 + 0, pt0 + 1);
+ map_point(mask_matrix, st1[0], st1[1],
+ pt1 + 0, pt1 + 1);
+ setup_vertex2(r->vertices3[0], dstX, dstY,
+ pt0[0], pt0[1], pt1[0], pt1[1]);
+ /* 2nd vertex */
+ map_point(src_matrix, st0[2], st0[1],
+ pt0 + 0, pt0 + 1);
+ map_point(mask_matrix, st1[2], st1[1],
+ pt1 + 0, pt1 + 1);
+ setup_vertex2(r->vertices3[1], dstX + width, dstY,
+ pt0[0], pt0[1], pt1[0], pt1[1]);
+ /* 3rd vertex */
+ map_point(src_matrix, st0[2], st0[3],
+ pt0 + 0, pt0 + 1);
+ map_point(mask_matrix, st1[2], st1[3],
+ pt1 + 0, pt1 + 1);
+ setup_vertex2(r->vertices3[2], dstX + width, dstY + height,
+ pt0[0], pt0[1], pt1[0], pt1[1]);
+ /* 4th vertex */
+ map_point(src_matrix, st0[0], st0[3],
+ pt0 + 0, pt0 + 1);
+ map_point(mask_matrix, st1[0], st1[3],
+ pt1 + 0, pt1 + 1);
+ setup_vertex2(r->vertices3[3], dstX, dstY + height,
+ pt0[0], pt0[1], pt1[0], pt1[1]);
+ } else {
+ /* 1st vertex */
+ setup_vertex2(r->vertices3[0], dstX, dstY,
+ st0[0], st0[1], st1[0], st1[1]);
+ /* 2nd vertex */
+ setup_vertex2(r->vertices3[1], dstX + width, dstY,
+ st0[2], st0[1], st1[2], st1[1]);
+ /* 3rd vertex */
+ setup_vertex2(r->vertices3[2], dstX + width, dstY + height,
+ st0[2], st0[3], st1[2], st1[3]);
+ /* 4th vertex */
+ setup_vertex2(r->vertices3[3], dstX, dstY + height,
+ st0[0], st0[3], st1[0], st1[3]);
+ }
return pipe_user_buffer_create(r->pipe->screen,
r->vertices3,
@@ -721,7 +797,8 @@ void renderer_draw_textures(struct xorg_renderer *r,
int *pos,
int width, int height,
struct pipe_texture **textures,
- int num_textures)
+ int num_textures,
+ float *src_matrix, float *mask_matrix)
{
struct pipe_context *pipe = r->pipe;
struct pipe_buffer *buf = 0;
@@ -732,7 +809,7 @@ void renderer_draw_textures(struct xorg_renderer *r,
pos[0], pos[1], /* src */
pos[4], pos[5], /* dst */
width, height,
- textures[0]);
+ textures[0], src_matrix);
break;
case 2:
buf = setup_vertex_data2(r,
@@ -740,7 +817,8 @@ void renderer_draw_textures(struct xorg_renderer *r,
pos[2], pos[3], /* mask */
pos[4], pos[5], /* dst */
width, height,
- textures[0], textures[1]);
+ textures[0], textures[1],
+ src_matrix, mask_matrix);
break;
default:
debug_assert(!"Unsupported number of textures");
diff --git a/src/gallium/state_trackers/xorg/xorg_renderer.h b/src/gallium/state_trackers/xorg/xorg_renderer.h
index b6296d5fd6b..3e37c9aa930 100644
--- a/src/gallium/state_trackers/xorg/xorg_renderer.h
+++ b/src/gallium/state_trackers/xorg/xorg_renderer.h
@@ -47,7 +47,9 @@ void renderer_draw_textures(struct xorg_renderer *r,
int *pos,
int width, int height,
struct pipe_texture **textures,
- int num_textures);
+ int num_textures,
+ float *src_matrix,
+ float *mask_matrix);
#endif