st/xorg: implement basic src/mask transformations
plus fix filters
This commit is contained in:
parent
e5f1f6a0be
commit
a39a3cc14e
|
@ -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 \
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue