diff options
Diffstat (limited to 'src/gallium/state_trackers/xorg/xorg_composite.c')
-rw-r--r-- | src/gallium/state_trackers/xorg/xorg_composite.c | 681 |
1 files changed, 304 insertions, 377 deletions
diff --git a/src/gallium/state_trackers/xorg/xorg_composite.c b/src/gallium/state_trackers/xorg/xorg_composite.c index c708ac3170..1bc3350e8b 100644 --- a/src/gallium/state_trackers/xorg/xorg_composite.c +++ b/src/gallium/state_trackers/xorg/xorg_composite.c @@ -1,97 +1,116 @@ #include "xorg_composite.h" +#include "xorg_renderer.h" #include "xorg_exa_tgsi.h" #include "cso_cache/cso_context.h" #include "util/u_draw_quad.h" +#include "util/u_math.h" #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; + int op : 8; - unsigned rgb_src_factor:5; /**< PIPE_BLENDFACTOR_x */ - unsigned rgb_dst_factor:5; /**< PIPE_BLENDFACTOR_x */ + unsigned alpha_dst : 4; + unsigned alpha_src : 4; - unsigned alpha_src_factor:5; /**< PIPE_BLENDFACTOR_x */ - unsigned alpha_dst_factor:5; /**< PIPE_BLENDFACTOR_x */ + unsigned rgb_src : 8; /**< PIPE_BLENDFACTOR_x */ + unsigned rgb_dst : 8; /**< PIPE_BLENDFACTOR_x */ }; #define BLEND_OP_OVER 3 static const struct xorg_composite_blend xorg_blends[] = { { PictOpClear, - PIPE_BLENDFACTOR_CONST_COLOR, PIPE_BLENDFACTOR_CONST_ALPHA, - PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO }, - + 0, 0, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO}, { PictOpSrc, - PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE, - PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO }, - + 0, 0, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ZERO}, { PictOpDst, - PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO, - PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE }, - + 0, 0, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ONE}, { PictOpOver, - PIPE_BLENDFACTOR_SRC_ALPHA, PIPE_BLENDFACTOR_ONE, - PIPE_BLENDFACTOR_INV_SRC_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA }, - + 0, 1, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_INV_SRC_ALPHA}, { PictOpOverReverse, - PIPE_BLENDFACTOR_SRC_ALPHA, PIPE_BLENDFACTOR_ONE, - PIPE_BLENDFACTOR_INV_SRC_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA }, + 1, 0, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_ONE}, + { PictOpIn, + 1, 0, PIPE_BLENDFACTOR_DST_ALPHA, PIPE_BLENDFACTOR_ZERO}, + { PictOpInReverse, + 0, 1, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_SRC_ALPHA}, + { PictOpOut, + 1, 0, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_ZERO}, + { PictOpOutReverse, + 0, 1, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_INV_SRC_ALPHA}, + { PictOpAtop, + 1, 1, PIPE_BLENDFACTOR_DST_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA}, + { PictOpAtopReverse, + 1, 1, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_SRC_ALPHA}, + { PictOpXor, + 1, 1, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA}, + { PictOpAdd, + 0, 0, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE}, }; + static INLINE void -pixel_to_float4(PictFormatPtr format, - CARD32 pixel, float *color) +pixel_to_float4(Pixel pixel, float *color) { CARD32 r, g, b, a; - debug_assert(format->type == PictTypeDirect); - - r = (pixel >> format->direct.red) & format->direct.redMask; - g = (pixel >> format->direct.green) & format->direct.greenMask; - b = (pixel >> format->direct.blue) & format->direct.blueMask; - a = (pixel >> format->direct.alpha) & format->direct.alphaMask; - color[0] = ((float)r) / ((float)format->direct.redMask); - color[1] = ((float)g) / ((float)format->direct.greenMask); - color[2] = ((float)b) / ((float)format->direct.blueMask); - color[3] = ((float)a) / ((float)format->direct.alphaMask); + a = (pixel >> 24) & 0xff; + r = (pixel >> 16) & 0xff; + g = (pixel >> 8) & 0xff; + b = (pixel >> 0) & 0xff; + color[0] = ((float)r) / 255.; + color[1] = ((float)g) / 255.; + color[2] = ((float)b) / 255.; + color[3] = ((float)a) / 255.; } -struct acceleration_info { - int op : 16; - int with_mask : 1; - int component_alpha : 1; -}; -static const struct acceleration_info accelerated_ops[] = { - {PictOpClear, 1, 0}, - {PictOpSrc, 1, 0}, - {PictOpDst, 1, 0}, - {PictOpOver, 1, 0}, - {PictOpOverReverse, 1, 0}, - {PictOpIn, 1, 0}, - {PictOpInReverse, 1, 0}, - {PictOpOut, 1, 0}, - {PictOpOutReverse, 1, 0}, - {PictOpAtop, 1, 0}, - {PictOpAtopReverse, 1, 0}, - {PictOpXor, 1, 0}, - {PictOpAdd, 1, 0}, - {PictOpSaturate, 1, 0}, -}; - -static struct xorg_composite_blend -blend_for_op(int op) +static boolean +blend_for_op(struct xorg_composite_blend *blend, + int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, + PicturePtr pDstPicture) { const int num_blends = sizeof(xorg_blends)/sizeof(struct xorg_composite_blend); int i; + boolean supported = FALSE; + + /* our default in case something goes wrong */ + *blend = xorg_blends[BLEND_OP_OVER]; for (i = 0; i < num_blends; ++i) { - if (xorg_blends[i].op == op) - return xorg_blends[i]; + if (xorg_blends[i].op == op) { + *blend = xorg_blends[i]; + supported = TRUE; + } + } + + /* If there's no dst alpha channel, adjust the blend op so that we'll treat + * it as always 1. */ + if (pDstPicture && + PICT_FORMAT_A(pDstPicture->format) == 0 && blend->alpha_dst) { + if (blend->rgb_src == PIPE_BLENDFACTOR_DST_ALPHA) + blend->rgb_src = PIPE_BLENDFACTOR_ONE; + else if (blend->rgb_src == PIPE_BLENDFACTOR_INV_DST_ALPHA) + blend->rgb_src = PIPE_BLENDFACTOR_ZERO; } - return xorg_blends[BLEND_OP_OVER]; + + /* If the source alpha is being used, then we should only be in a case where + * the source blend factor is 0, and the source blend value is the mask + * channels multiplied by the source picture's alpha. */ + if (pMaskPicture && pMaskPicture->componentAlpha && + PICT_FORMAT_RGB(pMaskPicture->format) && blend->alpha_src) { + if (blend->rgb_dst == PIPE_BLENDFACTOR_SRC_ALPHA) { + blend->rgb_dst = PIPE_BLENDFACTOR_SRC_COLOR; + } else if (blend->rgb_dst == PIPE_BLENDFACTOR_INV_SRC_ALPHA) { + blend->rgb_dst = PIPE_BLENDFACTOR_INV_SRC_COLOR; + } + } + + return supported; } static INLINE int @@ -112,150 +131,41 @@ render_repeat_to_gallium(int mode) return PIPE_TEX_WRAP_REPEAT; } - -static INLINE void -setup_vertex0(float vertex[2][4], float x, float y, - float color[4]) +static INLINE boolean +render_filter_to_gallium(int xrender_filter, int *out_filter) { - vertex[0][0] = x; - vertex[0][1] = y; - vertex[0][2] = 0.f; /*z*/ - vertex[0][3] = 1.f; /*w*/ - - vertex[1][0] = color[0]; /*r*/ - vertex[1][1] = color[1]; /*g*/ - vertex[1][2] = color[2]; /*b*/ - vertex[1][3] = color[3]; /*a*/ -} -static struct pipe_buffer * -setup_vertex_data0(struct exa_context *ctx, - int srcX, int srcY, int maskX, int maskY, - int dstX, int dstY, int width, int height) -{ - float vertices[4][2][4]; - - /* 1st vertex */ - setup_vertex0(vertices[0], dstX, dstY, - ctx->solid_color); - /* 2nd vertex */ - setup_vertex0(vertices[1], dstX + width, dstY, - ctx->solid_color); - /* 3rd vertex */ - setup_vertex0(vertices[2], dstX + width, dstY + height, - ctx->solid_color); - /* 4th vertex */ - setup_vertex0(vertices[3], dstX, dstY + height, - ctx->solid_color); - - return pipe_user_buffer_create(ctx->ctx->screen, - vertices, - sizeof(vertices)); -} - -static INLINE void -setup_vertex1(float vertex[2][4], float x, float y, float s, float t) -{ - vertex[0][0] = x; - vertex[0][1] = y; - vertex[0][2] = 0.f; /*z*/ - vertex[0][3] = 1.f; /*w*/ - - vertex[1][0] = s; /*s*/ - vertex[1][1] = t; /*t*/ - vertex[1][2] = 0.f; /*r*/ - vertex[1][3] = 1.f; /*q*/ -} + 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; + } -static struct pipe_buffer * -setup_vertex_data1(struct exa_context *ctx, - int srcX, int srcY, int maskX, int maskY, - int dstX, int dstY, int width, int height) -{ - float vertices[4][2][4]; - float s0, t0, s1, t1; - struct pipe_texture *src = ctx->bound_textures[0]; - - 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(vertices[0], dstX, dstY, - s0, t0); - /* 2nd vertex */ - setup_vertex1(vertices[1], dstX + width, dstY, - s1, t0); - /* 3rd vertex */ - setup_vertex1(vertices[2], dstX + width, dstY + height, - s1, t1); - /* 4th vertex */ - setup_vertex1(vertices[3], dstX, dstY + height, - s0, t1); - - return pipe_user_buffer_create(ctx->ctx->screen, - vertices, - sizeof(vertices)); + return TRUE; } - -static INLINE void -setup_vertex2(float vertex[3][4], float x, float y, - float s0, float t0, float s1, float t1) +static boolean is_filter_accelerated(PicturePtr pic) { - vertex[0][0] = x; - vertex[0][1] = y; - vertex[0][2] = 0.f; /*z*/ - vertex[0][3] = 1.f; /*w*/ - - vertex[1][0] = s0; /*s*/ - vertex[1][1] = t0; /*t*/ - vertex[1][2] = 0.f; /*r*/ - vertex[1][3] = 1.f; /*q*/ - - vertex[2][0] = s1; /*s*/ - vertex[2][1] = t1; /*t*/ - vertex[2][2] = 0.f; /*r*/ - vertex[2][3] = 1.f; /*q*/ -} - -static struct pipe_buffer * -setup_vertex_data2(struct exa_context *ctx, - int srcX, int srcY, int maskX, int maskY, - int dstX, int dstY, int width, int height) -{ - float vertices[4][3][4]; - float st0[4], st1[4]; - struct pipe_texture *src = ctx->bound_textures[0]; - struct pipe_texture *mask = ctx->bound_textures[0]; - - st0[0] = srcX / src->width[0]; - st0[1] = srcY / src->height[0]; - st0[2] = srcX + width / src->width[0]; - st0[3] = srcY + height / src->height[0]; - - st1[0] = maskX / mask->width[0]; - st1[1] = maskY / mask->height[0]; - st1[2] = maskX + width / mask->width[0]; - st1[3] = maskY + height / mask->height[0]; - - /* 1st vertex */ - setup_vertex2(vertices[0], dstX, dstY, - st0[0], st0[1], st1[0], st1[1]); - /* 2nd vertex */ - setup_vertex2(vertices[1], dstX + width, dstY, - st0[2], st0[1], st1[2], st1[1]); - /* 3rd vertex */ - setup_vertex2(vertices[2], dstX + width, dstY + height, - st0[2], st0[3], st1[2], st1[3]); - /* 4th vertex */ - setup_vertex2(vertices[3], dstX, dstY + height, - st0[0], st0[3], st1[0], st1[3]); - - return pipe_user_buffer_create(ctx->ctx->screen, - vertices, - sizeof(vertices)); + int filter; + if (pic && !render_filter_to_gallium(pic->filter, &filter)) + return FALSE; + return TRUE; } boolean xorg_composite_accelerated(int op, @@ -263,125 +173,60 @@ boolean xorg_composite_accelerated(int op, PicturePtr pMaskPicture, PicturePtr pDstPicture) { - unsigned i; - unsigned accel_ops_count = - sizeof(accelerated_ops)/sizeof(struct acceleration_info); - - - /*FIXME: currently accel is disabled */ - return FALSE; + ScreenPtr pScreen = pDstPicture->pDrawable->pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + modesettingPtr ms = modesettingPTR(pScrn); + struct xorg_composite_blend blend; + + if (!is_filter_accelerated(pSrcPicture) || + !is_filter_accelerated(pMaskPicture)) { + XORG_FALLBACK("Unsupported Xrender filter"); + } - if (pSrcPicture) { - /* component alpha not supported */ - if (pSrcPicture->componentAlpha) - return FALSE; - /* fills not supported */ - if (pSrcPicture->pSourcePict) - return FALSE; + if (pSrcPicture->pSourcePict) { + if (pSrcPicture->pSourcePict->type != SourcePictTypeSolidFill) + XORG_FALLBACK("Gradients not enabled (haven't been well tested)"); } - for (i = 0; i < accel_ops_count; ++i) { - if (op == accelerated_ops[i].op) { - if (pMaskPicture && !accelerated_ops[i].with_mask) - return FALSE; - return TRUE; + if (blend_for_op(&blend, op, + pSrcPicture, pMaskPicture, pDstPicture)) { + /* Check for component alpha */ + if (pMaskPicture && pMaskPicture->componentAlpha && + PICT_FORMAT_RGB(pMaskPicture->format)) { + if (blend.alpha_src && blend.rgb_src != PIPE_BLENDFACTOR_ZERO) { + XORG_FALLBACK("Component alpha not supported with source " + "alpha and source value blending. (op=%d)", + op); + } } + return TRUE; } - return FALSE; -} - -static void -bind_framebuffer_state(struct exa_context *exa, PicturePtr pDstPicture, - struct exa_pixmap_priv *pDst) -{ - unsigned i; - struct pipe_framebuffer_state state; - struct pipe_surface *surface = exa_gpu_surface(exa, pDst); - memset(&state, 0, sizeof(struct pipe_framebuffer_state)); - - state.width = pDstPicture->pDrawable->width; - state.height = pDstPicture->pDrawable->height; - - state.nr_cbufs = 1; - state.cbufs[0] = surface; - for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i) - state.cbufs[i] = 0; - - /* currently we don't use depth/stencil */ - state.zsbuf = 0; - - cso_set_framebuffer(exa->cso, &state); -} - -enum AxisOrientation { - Y0_BOTTOM, - Y0_TOP -}; - -static void -set_viewport(struct exa_context *exa, int width, int height, - enum AxisOrientation orientation) -{ - struct pipe_viewport_state viewport; - float y_scale = (orientation == Y0_BOTTOM) ? -2.f : 2.f; - - viewport.scale[0] = width / 2.f; - viewport.scale[1] = height / y_scale; - viewport.scale[2] = 1.0; - viewport.scale[3] = 1.0; - viewport.translate[0] = width / 2.f; - viewport.translate[1] = height / 2.f; - viewport.translate[2] = 0.0; - viewport.translate[3] = 0.0; - - cso_set_viewport(exa->cso, &viewport); -} - -static void -bind_viewport_state(struct exa_context *exa, PicturePtr pDstPicture) -{ - int width = pDstPicture->pDrawable->width; - int height = pDstPicture->pDrawable->height; - - set_viewport(exa, width, height, Y0_TOP); + XORG_FALLBACK("Unsupported composition operation = %d", op); } static void bind_blend_state(struct exa_context *exa, int op, - PicturePtr pSrcPicture, PicturePtr pMaskPicture) + PicturePtr pSrcPicture, + PicturePtr pMaskPicture, + PicturePtr pDstPicture) { - boolean component_alpha = pSrcPicture->componentAlpha; struct xorg_composite_blend blend_opt; struct pipe_blend_state blend; - if (component_alpha) { - op = PictOpOver; - } - blend_opt = blend_for_op(op); + blend_for_op(&blend_opt, op, pSrcPicture, pMaskPicture, pDstPicture); memset(&blend, 0, sizeof(struct pipe_blend_state)); blend.blend_enable = 1; - blend.colormask |= PIPE_MASK_R; - blend.colormask |= PIPE_MASK_G; - blend.colormask |= PIPE_MASK_B; - blend.colormask |= PIPE_MASK_A; + blend.colormask |= PIPE_MASK_RGBA; - blend.rgb_src_factor = blend_opt.rgb_src_factor; - blend.alpha_src_factor = blend_opt.alpha_src_factor; - blend.rgb_dst_factor = blend_opt.rgb_dst_factor; - blend.alpha_dst_factor = blend_opt.alpha_dst_factor; + blend.rgb_src_factor = blend_opt.rgb_src; + blend.alpha_src_factor = blend_opt.rgb_src; + blend.rgb_dst_factor = blend_opt.rgb_dst; + blend.alpha_dst_factor = blend_opt.rgb_dst; - cso_set_blend(exa->cso, &blend); + cso_set_blend(exa->renderer->cso, &blend); } -static void -bind_rasterizer_state(struct exa_context *exa) -{ - struct pipe_rasterizer_state raster; - memset(&raster, 0, sizeof(struct pipe_rasterizer_state)); - raster.gl_rasterization_rules = 1; - cso_set_rasterizer(exa->cso, &raster); -} static void bind_shaders(struct exa_context *exa, int op, @@ -390,14 +235,17 @@ bind_shaders(struct exa_context *exa, int op, unsigned vs_traits = 0, fs_traits = 0; struct xorg_shader shader; + exa->has_solid_color = FALSE; + if (pSrcPicture) { if (pSrcPicture->pSourcePict) { if (pSrcPicture->pSourcePict->type == SourcePictTypeSolidFill) { fs_traits |= FS_SOLID_FILL; vs_traits |= VS_SOLID_FILL; - pixel_to_float4(pSrcPicture->pFormat, - pSrcPicture->pSourcePict->solidFill.color, + debug_assert(pSrcPicture->format == PICT_a8r8g8b8); + pixel_to_float4(pSrcPicture->pSourcePict->solidFill.color, exa->solid_color); + exa->has_solid_color = TRUE; } else { debug_assert("!gradients not supported"); } @@ -410,14 +258,22 @@ bind_shaders(struct exa_context *exa, int op, if (pMaskPicture) { vs_traits |= VS_MASK; fs_traits |= FS_MASK; + if (pMaskPicture->componentAlpha) { + struct xorg_composite_blend blend; + blend_for_op(&blend, op, + pSrcPicture, pMaskPicture, NULL); + if (blend.alpha_src) { + fs_traits |= FS_CA_SRCALPHA; + } else + fs_traits |= FS_CA_FULL; + } } - shader = xorg_shaders_get(exa->shaders, vs_traits, fs_traits); - cso_set_vertex_shader_handle(exa->cso, shader.vs); - cso_set_fragment_shader_handle(exa->cso, shader.fs); + shader = xorg_shaders_get(exa->renderer->shaders, vs_traits, fs_traits); + cso_set_vertex_shader_handle(exa->renderer->cso, shader.vs); + cso_set_fragment_shader_handle(exa->renderer->cso, shader.fs); } - static void bind_samplers(struct exa_context *exa, int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, @@ -434,35 +290,57 @@ bind_samplers(struct exa_context *exa, int op, memset(&src_sampler, 0, sizeof(struct pipe_sampler_state)); memset(&mask_sampler, 0, sizeof(struct pipe_sampler_state)); + if ((pSrc && exa->pipe->is_texture_referenced(exa->pipe, pSrc->tex, 0, 0) & + PIPE_REFERENCED_FOR_WRITE) || + (pMask && exa->pipe->is_texture_referenced(exa->pipe, pMask->tex, 0, 0) & + PIPE_REFERENCED_FOR_WRITE)) + exa->pipe->flush(exa->pipe, PIPE_FLUSH_RENDER_CACHE, NULL); + if (pSrcPicture && pSrc) { - unsigned src_wrap = render_repeat_to_gallium( - pSrcPicture->repeatType); - 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.normalized_coords = 1; - samplers[0] = &src_sampler; - exa->bound_textures[0] = pSrc->tex; - ++exa->num_bound_samplers; + if (exa->has_solid_color) { + debug_assert(!"solid color with textures"); + samplers[0] = NULL; + exa->bound_textures[0] = NULL; + } else { + 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 = 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; + exa->num_bound_samplers = 1; + } } 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; - ++exa->num_bound_samplers; + exa->num_bound_samplers = 2; } - cso_set_samplers(exa->cso, exa->num_bound_samplers, + cso_set_samplers(exa->renderer->cso, exa->num_bound_samplers, (const struct pipe_sampler_state **)samplers); - cso_set_sampler_textures(exa->cso, exa->num_bound_samplers, + cso_set_sampler_textures(exa->renderer->cso, exa->num_bound_samplers, exa->bound_textures); } @@ -475,18 +353,8 @@ setup_vs_constant_buffer(struct exa_context *exa, 2.f/width, 2.f/height, 1, 1, -1, -1, 0, 0 }; - struct pipe_constant_buffer *cbuf = &exa->vs_const_buffer; - - pipe_buffer_reference(&cbuf->buffer, NULL); - cbuf->buffer = pipe_buffer_create(exa->ctx->screen, 16, - PIPE_BUFFER_USAGE_CONSTANT, - param_bytes); - - if (cbuf->buffer) { - pipe_buffer_write(exa->ctx->screen, cbuf->buffer, - 0, param_bytes, vs_consts); - } - exa->ctx->set_constant_buffer(exa->ctx, PIPE_SHADER_VERTEX, 0, cbuf); + renderer_set_constants(exa->renderer, PIPE_SHADER_VERTEX, + vs_consts, param_bytes); } @@ -494,33 +362,61 @@ static void setup_fs_constant_buffer(struct exa_context *exa) { const int param_bytes = 4 * sizeof(float); - float fs_consts[8] = { + const float fs_consts[8] = { 0, 0, 0, 1, }; - struct pipe_constant_buffer *cbuf = &exa->fs_const_buffer; - - pipe_buffer_reference(&cbuf->buffer, NULL); - cbuf->buffer = pipe_buffer_create(exa->ctx->screen, 16, - PIPE_BUFFER_USAGE_CONSTANT, - param_bytes); - - if (cbuf->buffer) { - pipe_buffer_write(exa->ctx->screen, cbuf->buffer, - 0, param_bytes, fs_consts); - } - exa->ctx->set_constant_buffer(exa->ctx, PIPE_SHADER_FRAGMENT, 0, cbuf); + renderer_set_constants(exa->renderer, PIPE_SHADER_FRAGMENT, + fs_consts, param_bytes); } static void -setup_constant_buffers(struct exa_context *exa, PicturePtr pDstPicture) +setup_constant_buffers(struct exa_context *exa, struct exa_pixmap_priv *pDst) { - int width = pDstPicture->pDrawable->width; - int height = pDstPicture->pDrawable->height; + int width = pDst->tex->width[0]; + int height = pDst->tex->height[0]; setup_vs_constant_buffer(exa, width, height); 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[3] = XFixedToDouble(trans->matrix[0][1]); + matrix[6] = XFixedToDouble(trans->matrix[0][2]); + + matrix[1] = XFixedToDouble(trans->matrix[1][0]); + matrix[4] = XFixedToDouble(trans->matrix[1][1]); + matrix[7] = XFixedToDouble(trans->matrix[1][2]); + + matrix[2] = XFixedToDouble(trans->matrix[2][0]); + matrix[5] = 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, @@ -530,17 +426,18 @@ boolean xorg_composite_bind_state(struct exa_context *exa, struct exa_pixmap_priv *pMask, struct exa_pixmap_priv *pDst) { - bind_framebuffer_state(exa, pDstPicture, pDst); - bind_viewport_state(exa, pDstPicture); - bind_blend_state(exa, op, pSrcPicture, pMaskPicture); - bind_rasterizer_state(exa); + renderer_bind_framebuffer(exa->renderer, pDst); + renderer_bind_viewport(exa->renderer, pDst); + bind_blend_state(exa, op, pSrcPicture, pMaskPicture, pDstPicture); + renderer_bind_rasterizer(exa->renderer); bind_shaders(exa, op, pSrcPicture, pMaskPicture); bind_samplers(exa, op, pSrcPicture, pMaskPicture, pDstPicture, pSrc, pMask, pDst); + setup_constant_buffers(exa, pDst); - setup_constant_buffers(exa, pDstPicture); + setup_transforms(exa, pSrcPicture, pMaskPicture); - return FALSE; + return TRUE; } void xorg_composite(struct exa_context *exa, @@ -548,37 +445,67 @@ void xorg_composite(struct exa_context *exa, int srcX, int srcY, int maskX, int maskY, int dstX, int dstY, int width, int height) { - struct pipe_context *pipe = exa->ctx; - struct pipe_buffer *buf = 0; - if (exa->num_bound_samplers == 0 ) { /* solid fill */ - buf = setup_vertex_data0(exa, - srcX, srcY, maskX, maskY, - dstX, dstY, width, height); - } else if (exa->num_bound_samplers == 1 ) /* src */ - buf = setup_vertex_data1(exa, - srcX, srcY, maskX, maskY, - dstX, dstY, width, height); - else if (exa->num_bound_samplers == 2) /* src + mask */ - buf = setup_vertex_data2(exa, - srcX, srcY, maskX, maskY, - dstX, dstY, width, height); - else if (exa->num_bound_samplers == 3) { /* src + mask + dst */ - debug_assert(!"src/mask/dst not handled right now"); + renderer_draw_solid_rect(exa->renderer, + dstX, dstY, dstX + width, dstY + height, + 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, + src_matrix, mask_matrix); + } +} + +boolean xorg_solid_bind_state(struct exa_context *exa, + struct exa_pixmap_priv *pixmap, + Pixel fg) +{ + unsigned vs_traits, fs_traits; + struct xorg_shader shader; + + pixel_to_float4(fg, exa->solid_color); + exa->has_solid_color = TRUE; + #if 0 - buf = setup_vertex_data2(exa, - srcX, srcY, maskX, maskY, - dstX, dstY, width, height); + debug_printf("Color Pixel=(%d, %d, %d, %d), RGBA=(%f, %f, %f, %f)\n", + (fg >> 24) & 0xff, (fg >> 16) & 0xff, + (fg >> 8) & 0xff, (fg >> 0) & 0xff, + exa->solid_color[0], exa->solid_color[1], + exa->solid_color[2], exa->solid_color[3]); #endif - } - if (buf) { - util_draw_vertex_buffer(pipe, buf, 0, - PIPE_PRIM_TRIANGLE_FAN, - 4, /* verts */ - 1 + exa->num_bound_samplers); /* attribs/vert */ + vs_traits = VS_SOLID_FILL; + fs_traits = FS_SOLID_FILL; - pipe_buffer_reference(&buf, NULL); - } + renderer_bind_framebuffer(exa->renderer, pixmap); + renderer_bind_viewport(exa->renderer, pixmap); + renderer_bind_rasterizer(exa->renderer); + bind_blend_state(exa, PictOpSrc, NULL, NULL, NULL); + setup_constant_buffers(exa, pixmap); + + shader = xorg_shaders_get(exa->renderer->shaders, vs_traits, fs_traits); + cso_set_vertex_shader_handle(exa->renderer->cso, shader.vs); + cso_set_fragment_shader_handle(exa->renderer->cso, shader.fs); + + return TRUE; +} + +void xorg_solid(struct exa_context *exa, + struct exa_pixmap_priv *pixmap, + int x0, int y0, int x1, int y1) +{ + renderer_draw_solid_rect(exa->renderer, + x0, y0, x1, y1, exa->solid_color); } |