X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fstate_trackers%2Fxorg%2Fxorg_composite.c;h=7ccb3fe4734fe5699ef1f351ea0ffacb3e480450;hb=337f21bc356a89a9c755aebabb64ba381a59e39b;hp=ed649a9d6525cb5d8b9653033f19cd95c2e479c4;hpb=bade906ed131e35ed1782f4687760dcdca233299;p=mesa.git diff --git a/src/gallium/state_trackers/xorg/xorg_composite.c b/src/gallium/state_trackers/xorg/xorg_composite.c index ed649a9d652..7ccb3fe4734 100644 --- a/src/gallium/state_trackers/xorg/xorg_composite.c +++ b/src/gallium/state_trackers/xorg/xorg_composite.c @@ -1,114 +1,114 @@ #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 "util/u_format.h" +#include "util/u_sampler.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 alpha_src_factor:5; /**< PIPE_BLENDFACTOR_x */ + unsigned alpha_dst : 4; + unsigned alpha_src : 4; - unsigned rgb_dst_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(Pixel pixel, float *color) +pixel_to_float4(Pixel pixel, float *color, enum pipe_format format) { - CARD32 r, g, b, a; - - 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.; -} + const struct util_format_description *format_desc; + uint8_t packed[4]; -static INLINE void -render_pixel_to_float4(PictFormatPtr format, - CARD32 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); + format_desc = util_format_description(format); + packed[0] = pixel; + packed[1] = pixel >> 8; + packed[2] = pixel >> 16; + packed[3] = pixel >> 24; + format_desc->unpack_rgba_float(color, 0, packed, 0, 1, 1); } -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; + } + + /* 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 xorg_blends[BLEND_OP_OVER]; + + return supported; } static INLINE int @@ -116,7 +116,7 @@ render_repeat_to_gallium(int mode) { switch(mode) { case RepeatNone: - return PIPE_TEX_WRAP_CLAMP; + return PIPE_TEX_WRAP_CLAMP_TO_BORDER; case RepeatNormal: return PIPE_TEX_WRAP_REPEAT; case RepeatReflect: @@ -129,177 +129,44 @@ 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; + case PictFilterConvolution: + *out_filter = PIPE_TEX_FILTER_NEAREST; + return FALSE; + default: + debug_printf("Unknown xrender filter\n"); + *out_filter = PIPE_TEX_FILTER_NEAREST; + return FALSE; + } -static INLINE void -setup_vertex0(float vertex[2][4], float x, float y, - float color[4]) -{ - 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->pipe->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*/ -} - -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->pipe->screen, - vertices, - sizeof(vertices)); -} - -static struct pipe_buffer * -setup_vertex_data_tex(struct exa_context *ctx, - float x0, float y0, float x1, float y1, - float s0, float t0, float s1, float t1, - float z) -{ - float vertices[4][2][4]; - - /* 1st vertex */ - setup_vertex1(vertices[0], x0, y0, - s0, t0); - /* 2nd vertex */ - setup_vertex1(vertices[1], x1, y0, - s1, t0); - /* 3rd vertex */ - setup_vertex1(vertices[2], x1, y1, - s1, t1); - /* 4th vertex */ - setup_vertex1(vertices[3], x0, y1, - s0, t1); - - return pipe_user_buffer_create(ctx->pipe->screen, - vertices, - sizeof(vertices)); -} - - - -static INLINE void -setup_vertex2(float vertex[3][4], float x, float y, - float s0, float t0, float s1, float t1) -{ - 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*/ + return TRUE; } -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) +static boolean is_filter_accelerated(PicturePtr pic) { - 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->pipe->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, @@ -307,139 +174,127 @@ 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 = xf86ScreenToScrn(pScreen); + modesettingPtr ms = modesettingPTR(pScrn); + struct xorg_composite_blend blend; - if (pSrcPicture) { - /* component alpha not supported */ - if (pSrcPicture->componentAlpha) - return FALSE; - /* fills not supported */ - if (pSrcPicture->pSourcePict) - return FALSE; + if (!is_filter_accelerated(pSrcPicture) || + !is_filter_accelerated(pMaskPicture)) { + XORG_FALLBACK("Unsupported Xrender filter"); } - 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 (pSrcPicture->pSourcePict) { + if (pSrcPicture->pSourcePict->type != SourcePictTypeSolidFill) + XORG_FALLBACK("Gradients not enabled (haven't been well tested)"); } - return FALSE; -} - -static void -bind_clip_state(struct exa_context *exa) -{ -} - -static void -bind_framebuffer_state(struct exa_context *exa, 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 = pDst->tex->width[0]; - state.height = pDst->tex->height[0]; - - 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); - - /* we do fire and forget for the framebuffer, this is the forget part */ - pipe_surface_reference(&surface, NULL); -} - -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, struct exa_pixmap_priv *pDst) -{ - int width = pDst->tex->width[0]; - int height = pDst->tex->height[0]; - debug_printf("Bind viewport (%d, %d)\n", width, height); + 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); + } + } - set_viewport(exa, width, height, Y0_TOP); + return TRUE; + } + 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) ? - pSrcPicture->componentAlpha : FALSE; 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.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; - - cso_set_blend(exa->cso, &blend); -} + blend.rt[0].blend_enable = 1; + blend.rt[0].colormask = PIPE_MASK_RGBA; + + blend.rt[0].rgb_src_factor = blend_opt.rgb_src; + blend.rt[0].alpha_src_factor = blend_opt.rgb_src; + blend.rt[0].rgb_dst_factor = blend_opt.rgb_dst; + blend.rt[0].alpha_dst_factor = blend_opt.rgb_dst; + + cso_set_blend(exa->renderer->cso, &blend); +} + +static unsigned +picture_format_fixups(struct exa_pixmap_priv *pSrc, PicturePtr pSrcPicture, boolean mask, + PicturePtr pDstPicture) +{ + boolean set_alpha = FALSE; + boolean swizzle = FALSE; + unsigned ret = 0; + + if (pSrc && pSrc->picture_format == pSrcPicture->format) { + if (pSrc->picture_format == PICT_a8) { + if (mask) + return FS_MASK_LUMINANCE; + else if (pDstPicture->format != PICT_a8) { + /* if both dst and src are luminance then + * we don't want to swizzle the alpha (X) of the + * source into W component of the dst because + * it will break our destination */ + return FS_SRC_LUMINANCE; + } + } + return 0; + } -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); + if (pSrc && pSrc->picture_format != PICT_a8r8g8b8) { + assert(!"can not handle formats"); + return 0; + } + + /* pSrc->picture_format == PICT_a8r8g8b8 */ + switch (pSrcPicture->format) { + case PICT_x8b8g8r8: + case PICT_b8g8r8: + set_alpha = TRUE; /* fall trough */ + case PICT_a8b8g8r8: + swizzle = TRUE; + break; + case PICT_x8r8g8b8: + case PICT_r8g8b8: + set_alpha = TRUE; /* fall through */ + case PICT_a8r8g8b8: + break; +#ifdef PICT_TYPE_BGRA + case PICT_b8g8r8a8: + case PICT_b8g8r8x8: + case PICT_a2r10g10b10: + case PICT_x2r10g10b10: + case PICT_a2b10g10r10: + case PICT_x2b10g10r10: +#endif + default: + assert(!"can not handle formats"); + return 0; + } + + if (set_alpha) + ret |= mask ? FS_MASK_SET_ALPHA : FS_SRC_SET_ALPHA; + if (swizzle) + ret |= mask ? FS_MASK_SWIZZLE_RGB : FS_SRC_SWIZZLE_RGB; + + return ret; } static void bind_shaders(struct exa_context *exa, int op, - PicturePtr pSrcPicture, PicturePtr pMaskPicture) + PicturePtr pSrcPicture, PicturePtr pMaskPicture, PicturePtr pDstPicture, + struct exa_pixmap_priv *pSrc, struct exa_pixmap_priv *pMask) { unsigned vs_traits = 0, fs_traits = 0; struct xorg_shader shader; @@ -447,13 +302,16 @@ bind_shaders(struct exa_context *exa, int op, exa->has_solid_color = FALSE; if (pSrcPicture) { + if (pSrcPicture->repeatType == RepeatNone && pSrcPicture->transform) + fs_traits |= FS_SRC_REPEAT_NONE; + if (pSrcPicture->pSourcePict) { if (pSrcPicture->pSourcePict->type == SourcePictTypeSolidFill) { fs_traits |= FS_SOLID_FILL; vs_traits |= VS_SOLID_FILL; - render_pixel_to_float4(pSrcPicture->pFormat, - pSrcPicture->pSourcePict->solidFill.color, - exa->solid_color); + debug_assert(pSrcPicture->format == PICT_a8r8g8b8); + pixel_to_float4(pSrcPicture->pSourcePict->solidFill.color, + exa->solid_color, PIPE_FORMAT_B8G8R8A8_UNORM); exa->has_solid_color = TRUE; } else { debug_assert("!gradients not supported"); @@ -462,19 +320,33 @@ bind_shaders(struct exa_context *exa, int op, fs_traits |= FS_COMPOSITE; vs_traits |= VS_COMPOSITE; } + + fs_traits |= picture_format_fixups(pSrc, pSrcPicture, FALSE, pDstPicture); } if (pMaskPicture) { vs_traits |= VS_MASK; fs_traits |= FS_MASK; + if (pMaskPicture->repeatType == RepeatNone && pMaskPicture->transform) + fs_traits |= FS_MASK_REPEAT_NONE; + 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; + } + + fs_traits |= picture_format_fixups(pMask, pMaskPicture, TRUE, pDstPicture); } - 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, @@ -483,8 +355,11 @@ bind_samplers(struct exa_context *exa, int op, struct exa_pixmap_priv *pMask, struct exa_pixmap_priv *pDst) { - struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; + struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS] = {0}; struct pipe_sampler_state src_sampler, mask_sampler; + struct pipe_sampler_view view_templ; + struct pipe_sampler_view *src_view; + struct pipe_context *pipe = exa->pipe; exa->num_bound_samplers = 0; @@ -492,90 +367,103 @@ bind_samplers(struct exa_context *exa, int op, memset(&mask_sampler, 0, sizeof(struct pipe_sampler_state)); 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; + pipe_sampler_view_reference(&exa->bound_sampler_views[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->num_bound_samplers = 1; + u_sampler_view_default_template(&view_templ, + pSrc->tex, + pSrc->tex->format); + src_view = pipe->create_sampler_view(pipe, pSrc->tex, &view_templ); + pipe_sampler_view_reference(&exa->bound_sampler_views[0], NULL); + exa->bound_sampler_views[0] = src_view; + } } 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; + u_sampler_view_default_template(&view_templ, + pMask->tex, + pMask->tex->format); + src_view = pipe->create_sampler_view(pipe, pMask->tex, &view_templ); + pipe_sampler_view_reference(&exa->bound_sampler_views[1], NULL); + exa->bound_sampler_views[1] = src_view; } - cso_set_samplers(exa->cso, exa->num_bound_samplers, + cso_set_samplers(exa->renderer->cso, PIPE_SHADER_FRAGMENT, + exa->num_bound_samplers, (const struct pipe_sampler_state **)samplers); - cso_set_sampler_textures(exa->cso, exa->num_bound_samplers, - exa->bound_textures); + cso_set_sampler_views(exa->renderer->cso, PIPE_SHADER_FRAGMENT, + exa->num_bound_samplers, + exa->bound_sampler_views); } -static void -setup_vs_constant_buffer(struct exa_context *exa, - int width, int height) -{ - const int param_bytes = 8 * sizeof(float); - float vs_consts[8] = { - 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->pipe->screen, 16, - PIPE_BUFFER_USAGE_CONSTANT, - param_bytes); - - if (cbuf->buffer) { - pipe_buffer_write(exa->pipe->screen, cbuf->buffer, - 0, param_bytes, vs_consts); - } - exa->pipe->set_constant_buffer(exa->pipe, PIPE_SHADER_VERTEX, 0, cbuf); -} -static void -setup_fs_constant_buffer(struct exa_context *exa) +static INLINE boolean matrix_from_pict_transform(PictTransform *trans, float *matrix) { - const int param_bytes = 4 * sizeof(float); - 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->pipe->screen, 16, - PIPE_BUFFER_USAGE_CONSTANT, - param_bytes); - - if (cbuf->buffer) { - pipe_buffer_write(exa->pipe->screen, cbuf->buffer, - 0, param_bytes, fs_consts); - } - exa->pipe->set_constant_buffer(exa->pipe, PIPE_SHADER_FRAGMENT, 0, cbuf); + 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_constant_buffers(struct exa_context *exa, struct exa_pixmap_priv *pDst) +setup_transforms(struct exa_context *exa, + PicturePtr pSrcPicture, PicturePtr pMaskPicture) { - int width = pDst->tex->width[0]; - int height = pDst->tex->height[0]; + PictTransform *src_t = NULL; + PictTransform *mask_t = NULL; + + if (pSrcPicture) + src_t = pSrcPicture->transform; + if (pMaskPicture) + mask_t = pMaskPicture->transform; - setup_vs_constant_buffer(exa, width, height); - setup_fs_constant_buffer(exa); + 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, @@ -587,17 +475,29 @@ boolean xorg_composite_bind_state(struct exa_context *exa, struct exa_pixmap_priv *pMask, struct exa_pixmap_priv *pDst) { - bind_framebuffer_state(exa, pDst); - bind_viewport_state(exa, pDst); - bind_blend_state(exa, op, pSrcPicture, pMaskPicture); - bind_rasterizer_state(exa); - bind_shaders(exa, op, pSrcPicture, pMaskPicture); + struct pipe_surface *dst_surf = xorg_gpu_surface(exa->pipe, pDst); + + renderer_bind_destination(exa->renderer, dst_surf, + pDst->width, + pDst->height); + + bind_blend_state(exa, op, pSrcPicture, pMaskPicture, pDstPicture); + bind_shaders(exa, op, pSrcPicture, pMaskPicture, pDstPicture, pSrc, pMask); bind_samplers(exa, op, pSrcPicture, pMaskPicture, pDstPicture, pSrc, pMask, pDst); - bind_clip_state(exa); - setup_constant_buffers(exa, pDst); - return FALSE; + setup_transforms(exa, pSrcPicture, pMaskPicture); + + if (exa->num_bound_samplers == 0 ) { /* solid fill */ + renderer_begin_solid(exa->renderer); + } else { + renderer_begin_textures(exa->renderer, + exa->num_bound_samplers); + } + + + pipe_surface_reference(&dst_surf, NULL); + return TRUE; } void xorg_composite(struct exa_context *exa, @@ -605,42 +505,25 @@ 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->pipe; - 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"); -#if 0 - buf = setup_vertex_data2(exa, - srcX, srcY, maskX, maskY, - dstX, dstY, width, height); -#endif - } - - if (buf) { - int num_attribs = 1; /*pos*/ - num_attribs += exa->num_bound_samplers; - if (exa->has_solid_color) - ++num_attribs; - - util_draw_vertex_buffer(pipe, buf, 0, - PIPE_PRIM_TRIANGLE_FAN, - 4, /* verts */ - num_attribs); /* attribs/vert */ - - pipe_buffer_reference(&buf, NULL); + renderer_solid(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_texture(exa->renderer, + pos, width, height, + exa->bound_sampler_views, + exa->num_bound_samplers, + src_matrix, mask_matrix); } } @@ -648,14 +531,13 @@ boolean xorg_solid_bind_state(struct exa_context *exa, struct exa_pixmap_priv *pixmap, Pixel fg) { + struct pipe_surface *dst_surf = xorg_gpu_surface(exa->pipe, pixmap); unsigned vs_traits, fs_traits; struct xorg_shader shader; - pixel_to_float4(fg, exa->solid_color); + pixel_to_float4(fg, exa->solid_color, pixmap->tex->format); exa->has_solid_color = TRUE; - exa->solid_color[3] = 1.f; - #if 0 debug_printf("Color Pixel=(%d, %d, %d, %d), RGBA=(%f, %f, %f, %f)\n", (fg >> 24) & 0xff, (fg >> 16) & 0xff, @@ -667,418 +549,37 @@ boolean xorg_solid_bind_state(struct exa_context *exa, vs_traits = VS_SOLID_FILL; fs_traits = FS_SOLID_FILL; - bind_framebuffer_state(exa, pixmap); - bind_viewport_state(exa, pixmap); - bind_rasterizer_state(exa); - bind_blend_state(exa, PictOpSrc, NULL, NULL); - setup_constant_buffers(exa, pixmap); - bind_clip_state(exa); + renderer_bind_destination(exa->renderer, dst_surf, + pixmap->width, pixmap->height); + bind_blend_state(exa, PictOpSrc, NULL, NULL, NULL); + cso_set_samplers(exa->renderer->cso, PIPE_SHADER_FRAGMENT, 0, NULL); + cso_set_sampler_views(exa->renderer->cso, PIPE_SHADER_FRAGMENT, 0, NULL); - 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); - return FALSE; + renderer_begin_solid(exa->renderer); + + pipe_surface_reference(&dst_surf, NULL); + return TRUE; } void xorg_solid(struct exa_context *exa, struct exa_pixmap_priv *pixmap, int x0, int y0, int x1, int y1) { - struct pipe_context *pipe = exa->pipe; - struct pipe_buffer *buf = 0; - float vertices[4][2][4]; - - /* 1st vertex */ - setup_vertex0(vertices[0], x0, y0, - exa->solid_color); - /* 2nd vertex */ - setup_vertex0(vertices[1], x1, y0, - exa->solid_color); - /* 3rd vertex */ - setup_vertex0(vertices[2], x1, y1, - exa->solid_color); - /* 4th vertex */ - setup_vertex0(vertices[3], x0, y1, - exa->solid_color); - - buf = pipe_user_buffer_create(exa->pipe->screen, - vertices, - sizeof(vertices)); - - - if (buf) { - debug_printf("Drawing buf is %p\n", buf); - util_draw_vertex_buffer(pipe, buf, 0, - PIPE_PRIM_TRIANGLE_FAN, - 4, /* verts */ - 2); /* attribs/vert */ - - pipe_buffer_reference(&buf, NULL); - } + renderer_solid(exa->renderer, + x0, y0, x1, y1, exa->solid_color); } - -static INLINE void shift_rectx(float coords[4], - const float *bounds, - const float shift) +void +xorg_composite_done(struct exa_context *exa) { - coords[0] += shift; - coords[2] -= shift; - if (bounds) { - coords[2] = MIN2(coords[2], bounds[2]); - /* bound x/y + width/height */ - if ((coords[0] + coords[2]) > (bounds[0] + bounds[2])) { - coords[2] = (bounds[0] + bounds[2]) - coords[0]; - } - } -} + renderer_draw_flush(exa->renderer); -static INLINE void shift_recty(float coords[4], - const float *bounds, - const float shift) -{ - coords[1] += shift; - coords[3] -= shift; - if (bounds) { - coords[3] = MIN2(coords[3], bounds[3]); - if ((coords[1] + coords[3]) > (bounds[1] + bounds[3])) { - coords[3] = (bounds[1] + bounds[3]) - coords[1]; - } - } -} - -static INLINE void bound_rect(float coords[4], - const float bounds[4], - float shift[4]) -{ - /* if outside the bounds */ - if (coords[0] > (bounds[0] + bounds[2]) || - coords[1] > (bounds[1] + bounds[3]) || - (coords[0] + coords[2]) < bounds[0] || - (coords[1] + coords[3]) < bounds[1]) { - coords[0] = 0.f; - coords[1] = 0.f; - coords[2] = 0.f; - coords[3] = 0.f; - shift[0] = 0.f; - shift[1] = 0.f; - return; - } - - /* bound x */ - if (coords[0] < bounds[0]) { - shift[0] = bounds[0] - coords[0]; - coords[2] -= shift[0]; - coords[0] = bounds[0]; - } else - shift[0] = 0.f; - - /* bound y */ - if (coords[1] < bounds[1]) { - shift[1] = bounds[1] - coords[1]; - coords[3] -= shift[1]; - coords[1] = bounds[1]; - } else - shift[1] = 0.f; - - shift[2] = bounds[2] - coords[2]; - shift[3] = bounds[3] - coords[3]; - /* bound width/height */ - coords[2] = MIN2(coords[2], bounds[2]); - coords[3] = MIN2(coords[3], bounds[3]); - - /* bound x/y + width/height */ - if ((coords[0] + coords[2]) > (bounds[0] + bounds[2])) { - coords[2] = (bounds[0] + bounds[2]) - coords[0]; - } - if ((coords[1] + coords[3]) > (bounds[1] + bounds[3])) { - coords[3] = (bounds[1] + bounds[3]) - coords[1]; - } - - /* if outside the bounds */ - if ((coords[0] + coords[2]) < bounds[0] || - (coords[1] + coords[3]) < bounds[1]) { - coords[0] = 0.f; - coords[1] = 0.f; - coords[2] = 0.f; - coords[3] = 0.f; - return; - } -} - -static INLINE void sync_size(float *src_loc, float *dst_loc) -{ - src_loc[2] = MIN2(src_loc[2], dst_loc[2]); - src_loc[3] = MIN2(src_loc[3], dst_loc[3]); - dst_loc[2] = src_loc[2]; - dst_loc[3] = src_loc[3]; -} - - -static void renderer_copy_texture(struct exa_context *exa, - struct pipe_texture *src, - float sx1, float sy1, - float sx2, float sy2, - struct pipe_texture *dst, - float dx1, float dy1, - float dx2, float dy2) -{ - struct pipe_context *pipe = exa->pipe; - struct pipe_screen *screen = pipe->screen; - struct pipe_buffer *buf; - struct pipe_surface *dst_surf = screen->get_tex_surface( - screen, dst, 0, 0, 0, - PIPE_BUFFER_USAGE_GPU_WRITE); - struct pipe_framebuffer_state fb; - float s0, t0, s1, t1; - struct xorg_shader shader; - - assert(src->width[0] != 0); - assert(src->height[0] != 0); - assert(dst->width[0] != 0); - assert(dst->height[0] != 0); - -#if 1 - s0 = sx1 / src->width[0]; - s1 = sx2 / src->width[0]; - t0 = sy1 / src->height[0]; - t1 = sy2 / src->height[0]; -#else - s0 = 0; - s1 = 1; - t0 = 0; - t1 = 1; -#endif - -#if 1 - debug_printf("copy texture src=[%f, %f, %f, %f], dst=[%f, %f, %f, %f], tex=[%f, %f, %f, %f]\n", - sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2, - s0, t0, s1, t1); -#endif - - assert(screen->is_format_supported(screen, dst_surf->format, - PIPE_TEXTURE_2D, - PIPE_TEXTURE_USAGE_RENDER_TARGET, - 0)); - - /* save state (restored below) */ - cso_save_blend(exa->cso); - cso_save_samplers(exa->cso); - cso_save_sampler_textures(exa->cso); - cso_save_framebuffer(exa->cso); - cso_save_fragment_shader(exa->cso); - cso_save_vertex_shader(exa->cso); - - cso_save_viewport(exa->cso); - - - /* set misc state we care about */ - { - struct pipe_blend_state blend; - memset(&blend, 0, sizeof(blend)); - blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE; - blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE; - blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; - blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; - blend.colormask = PIPE_MASK_RGBA; - cso_set_blend(exa->cso, &blend); - } - - /* sampler */ - { - struct pipe_sampler_state sampler; - memset(&sampler, 0, sizeof(sampler)); - sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; - sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; - sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; - sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; - sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; - sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; - sampler.normalized_coords = 1; - cso_single_sampler(exa->cso, 0, &sampler); - cso_single_sampler_done(exa->cso); - } - - set_viewport(exa, dst_surf->width, dst_surf->height, Y0_TOP); - - /* texture */ - cso_set_sampler_textures(exa->cso, 1, &src); - - /* shaders */ - shader = xorg_shaders_get(exa->shaders, - VS_COMPOSITE, - FS_COMPOSITE); - cso_set_vertex_shader_handle(exa->cso, shader.vs); - cso_set_fragment_shader_handle(exa->cso, shader.fs); - - /* drawing dest */ - memset(&fb, 0, sizeof(fb)); - fb.width = dst_surf->width; - fb.height = dst_surf->height; - fb.nr_cbufs = 1; - fb.cbufs[0] = dst_surf; - { - int i; - for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i) - fb.cbufs[i] = 0; - } - cso_set_framebuffer(exa->cso, &fb); - setup_vs_constant_buffer(exa, fb.width, fb.height); - setup_fs_constant_buffer(exa); - - /* draw quad */ - buf = setup_vertex_data_tex(exa, - dx1, dy1, - dx2, dy2, - s0, t0, s1, t1, - 0.0f); - - if (buf) { - util_draw_vertex_buffer(exa->pipe, buf, 0, - PIPE_PRIM_TRIANGLE_FAN, - 4, /* verts */ - 2); /* attribs/vert */ - - pipe_buffer_reference(&buf, NULL); - } - - /* restore state we changed */ - cso_restore_blend(exa->cso); - cso_restore_samplers(exa->cso); - cso_restore_sampler_textures(exa->cso); - cso_restore_framebuffer(exa->cso); - cso_restore_vertex_shader(exa->cso); - cso_restore_fragment_shader(exa->cso); - cso_restore_viewport(exa->cso); - - pipe_surface_reference(&dst_surf, NULL); -} - - -static struct pipe_texture * -create_sampler_texture(struct exa_context *ctx, - struct pipe_texture *src) -{ - enum pipe_format format; - struct pipe_context *pipe = ctx->pipe; - struct pipe_screen *screen = pipe->screen; - struct pipe_texture *pt; - struct pipe_texture templ; - - pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); - - /* the coming in texture should already have that invariance */ - debug_assert(screen->is_format_supported(screen, src->format, - PIPE_TEXTURE_2D, - PIPE_TEXTURE_USAGE_SAMPLER, 0)); - - format = src->format; - - memset(&templ, 0, sizeof(templ)); - templ.target = PIPE_TEXTURE_2D; - templ.format = format; - templ.last_level = 0; - templ.width[0] = src->width[0]; - templ.height[0] = src->height[0]; - templ.depth[0] = 1; - pf_get_block(format, &templ.block); - templ.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER; - - pt = screen->texture_create(screen, &templ); - - debug_assert(!pt || pipe_is_referenced(&pt->reference)); - - if (!pt) - return NULL; - - { - /* copy source framebuffer surface into texture */ - struct pipe_surface *ps_read = screen->get_tex_surface( - screen, src, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ); - struct pipe_surface *ps_tex = screen->get_tex_surface( - screen, pt, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE ); - pipe->surface_copy(pipe, - ps_tex, /* dest */ - 0, 0, /* destx/y */ - ps_read, - 0, 0, src->width[0], src->height[0]); - pipe_surface_reference(&ps_read, NULL); - pipe_surface_reference(&ps_tex, NULL); - } - - return pt; -} - -void xorg_copy_pixmap(struct exa_context *ctx, - struct exa_pixmap_priv *dst_priv, int dx, int dy, - struct exa_pixmap_priv *src_priv, int sx, int sy, - int width, int height) -{ - float dst_loc[4], src_loc[4]; - float dst_bounds[4], src_bounds[4]; - float src_shift[4], dst_shift[4], shift[4]; - struct pipe_texture *dst = dst_priv->tex; - struct pipe_texture *src = src_priv->tex; - - xorg_exa_finish(ctx); - - dst_loc[0] = dx; - dst_loc[1] = dy; - dst_loc[2] = width; - dst_loc[3] = height; - dst_bounds[0] = 0.f; - dst_bounds[1] = 0.f; - dst_bounds[2] = dst->width[0]; - dst_bounds[3] = dst->height[0]; - - src_loc[0] = sx; - src_loc[1] = sy; - src_loc[2] = width; - src_loc[3] = height; - src_bounds[0] = 0.f; - src_bounds[1] = 0.f; - src_bounds[2] = src->width[0]; - src_bounds[3] = src->height[0]; - - bound_rect(src_loc, src_bounds, src_shift); - bound_rect(dst_loc, dst_bounds, dst_shift); - shift[0] = src_shift[0] - dst_shift[0]; - shift[1] = src_shift[1] - dst_shift[1]; - - if (shift[0] < 0) - shift_rectx(src_loc, src_bounds, -shift[0]); - else - shift_rectx(dst_loc, dst_bounds, shift[0]); - - if (shift[1] < 0) - shift_recty(src_loc, src_bounds, -shift[1]); - else - shift_recty(dst_loc, dst_bounds, shift[1]); - - sync_size(src_loc, dst_loc); - - if (src_loc[2] >= 0 && src_loc[3] >= 0 && - dst_loc[2] >= 0 && dst_loc[3] >= 0) { - struct pipe_texture *temp_src = src; - - if (src == dst) - temp_src = create_sampler_texture(ctx, src); - - renderer_copy_texture(ctx, - temp_src, - src_loc[0], - src_loc[1], - src_loc[0] + src_loc[2], - src_loc[1] + src_loc[3], - dst, - dst_loc[0], - dst_loc[1], - dst_loc[0] + dst_loc[2], - dst_loc[1] + dst_loc[3]); - - if (src == dst) - pipe_texture_reference(&temp_src, NULL); - } + exa->transform.has_src = FALSE; + exa->transform.has_mask = FALSE; + exa->has_solid_color = FALSE; + exa->num_bound_samplers = 0; } -