st/xorg: implement basic src/mask transformations

plus fix filters
This commit is contained in:
Zack Rusin 2009-10-13 13:06:39 -04:00
parent e5f1f6a0be
commit a39a3cc14e
6 changed files with 231 additions and 40 deletions

View File

@ -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 \

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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");

View File

@ -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