aboutsummaryrefslogtreecommitdiffstats
path: root/src/gallium/frontends/xa
diff options
context:
space:
mode:
authorMarek Olšák <[email protected]>2019-12-03 18:01:31 -0500
committerMarek Olšák <[email protected]>2020-05-13 13:46:53 -0400
commitd6287a94b697ffe12a4e576a38943cdf4e90cdb0 (patch)
treebb84357d98dc74412e983693e09875bb355b467e /src/gallium/frontends/xa
parentb408734e5e2fe1e1ef08080c4425ad8a7ed33579 (diff)
gallium: rename 'state tracker' to 'frontend'
Acked-by: Eric Anholt <[email protected]> Acked-by: Alyssa Rosenzweig <[email protected]> Acked-by: Pierre-Eric Pelloux-Prayer <[email protected]> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4902>
Diffstat (limited to 'src/gallium/frontends/xa')
-rw-r--r--src/gallium/frontends/xa/.editorconfig3
-rw-r--r--src/gallium/frontends/xa/Makefile.sources8
-rw-r--r--src/gallium/frontends/xa/README72
-rw-r--r--src/gallium/frontends/xa/meson.build45
-rwxr-xr-xsrc/gallium/frontends/xa/xa-indent.sh3
-rw-r--r--src/gallium/frontends/xa/xa_composite.c592
-rw-r--r--src/gallium/frontends/xa/xa_composite.h156
-rw-r--r--src/gallium/frontends/xa/xa_context.c419
-rw-r--r--src/gallium/frontends/xa/xa_context.h101
-rw-r--r--src/gallium/frontends/xa/xa_priv.h289
-rw-r--r--src/gallium/frontends/xa/xa_renderer.c636
-rw-r--r--src/gallium/frontends/xa/xa_tgsi.c500
-rw-r--r--src/gallium/frontends/xa/xa_tracker.c578
-rw-r--r--src/gallium/frontends/xa/xa_tracker.h.in217
-rw-r--r--src/gallium/frontends/xa/xa_yuv.c163
15 files changed, 3782 insertions, 0 deletions
diff --git a/src/gallium/frontends/xa/.editorconfig b/src/gallium/frontends/xa/.editorconfig
new file mode 100644
index 00000000000..7b12a40ca00
--- /dev/null
+++ b/src/gallium/frontends/xa/.editorconfig
@@ -0,0 +1,3 @@
+[*.{c,h}]
+indent_style = space
+indent_size = 4
diff --git a/src/gallium/frontends/xa/Makefile.sources b/src/gallium/frontends/xa/Makefile.sources
new file mode 100644
index 00000000000..cdcc4187ac1
--- /dev/null
+++ b/src/gallium/frontends/xa/Makefile.sources
@@ -0,0 +1,8 @@
+C_SOURCES := \
+ xa_composite.c \
+ xa_context.c \
+ xa_priv.h \
+ xa_renderer.c \
+ xa_tgsi.c \
+ xa_tracker.c \
+ xa_yuv.c
diff --git a/src/gallium/frontends/xa/README b/src/gallium/frontends/xa/README
new file mode 100644
index 00000000000..1f08861588c
--- /dev/null
+++ b/src/gallium/frontends/xa/README
@@ -0,0 +1,72 @@
+/**********************************************************
+ * Copyright 2009-2011 VMware, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ *********************************************************
+ * Authors:
+ * Zack Rusin <zackr-at-vmware-dot-com>
+ * Thomas Hellstrom <thellstrom-at-vmware-dot-com>
+ */
+
+The XA state tracker is intended as a versioned interface to gallium for
+xorg driver writers. Initially it's mostly based on Zack Rusin's
+composite / video work for the Xorg state tracker.
+
+The motivation behind this state tracker is that the Xorg state tracker has
+a number of interfaces to work with:
+
+1) The Xorg sdk (versioned)
+2) Gallium3D (not versioned)
+3) KMS modesetting (versioned)
+4) Driver-private (hopefully versioned)
+
+Since Gallium3D is not versioned, the Xorg state tracker needs to be compiled
+with Gallium, but it's really beneficial to be able to compile xorg drivers
+standalone.
+
+Therefore the xa state tracker is intended to supply the following
+functionality:
+
+1) Versioning.
+2) Surface functionality (creation and copying for a basic dri2 implementation)
+3) YUV blits for textured Xv.
+4) Solid fills without ROP functionality.
+5) Copies with format conversion and - reinterpretation but without ROP
+6) Xrender- type compositing for general acceleration.
+
+
+The first user will be the vmwgfx xorg driver. When there are more users,
+we need to be able to load the appropriate gallium pipe driver, and we
+should investigate sharing the loadig mechanism with the EGL state tracker.
+
+IMPORTANT:
+Version compatibilities:
+While this library remains OUTSIDE any mesa release branch,
+and the major version number is still 0. Any minor bump should be viewed as
+an incompatibility event, and any user of this library should test for that
+and refuse to use the library if minor versions differ.
+As soon as the library enters a mesa release branch, if not earlier, major
+will be bumped to 1, and normal incompatibility rules (major bump)
+will be followed.
+It is allowed to add function interfaces while only bumping minor. Any
+user that uses these function interfaces must therefore use lazy symbol
+lookups and test minor for compatibility before using such a function.
diff --git a/src/gallium/frontends/xa/meson.build b/src/gallium/frontends/xa/meson.build
new file mode 100644
index 00000000000..0c3540f0359
--- /dev/null
+++ b/src/gallium/frontends/xa/meson.build
@@ -0,0 +1,45 @@
+# Copyright © 2017 Intel Corporation
+
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+xa_version = ['2', '5', '0']
+
+xa_conf = configuration_data()
+xa_conf.set('XA_MAJOR', xa_version[0])
+xa_conf.set('XA_MINOR', xa_version[1])
+xa_conf.set('XA_PATCH', xa_version[2])
+
+xa_tracker_h = configure_file(
+ configuration : xa_conf,
+ input : 'xa_tracker.h.in',
+ output : 'xa_tracker.h',
+ install_dir : get_option('includedir'),
+)
+
+libxa_st = static_library(
+ 'xa_st',
+ [xa_tracker_h, files(
+ 'xa_composite.c', 'xa_context.c', 'xa_renderer.c', 'xa_tgsi.c',
+ 'xa_tracker.c', 'xa_yuv.c',
+ )],
+ c_args : [c_vis_args, '-pedantic'],
+ include_directories : [inc_include, inc_src, inc_mapi, inc_mesa, inc_gallium, inc_gallium_aux],
+)
+
+install_headers('xa_composite.h', 'xa_context.h')
diff --git a/src/gallium/frontends/xa/xa-indent.sh b/src/gallium/frontends/xa/xa-indent.sh
new file mode 100755
index 00000000000..90241a3772e
--- /dev/null
+++ b/src/gallium/frontends/xa/xa-indent.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+indent --linux-style -i4 -ip4 -bad -bap -psl $*
+
diff --git a/src/gallium/frontends/xa/xa_composite.c b/src/gallium/frontends/xa/xa_composite.c
new file mode 100644
index 00000000000..34d78027e27
--- /dev/null
+++ b/src/gallium/frontends/xa/xa_composite.c
@@ -0,0 +1,592 @@
+/**********************************************************
+ * Copyright 2009-2011 VMware, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ *********************************************************
+ * Authors:
+ * Zack Rusin <zackr-at-vmware-dot-com>
+ * Thomas Hellstrom <thellstrom-at-vmware-dot-com>
+ */
+
+#include "xa_composite.h"
+#include "xa_context.h"
+#include "xa_priv.h"
+#include "cso_cache/cso_context.h"
+#include "util/u_sampler.h"
+#include "util/u_inlines.h"
+
+
+/*XXX also in Xrender.h but the including it here breaks compilition */
+#define XFixedToDouble(f) (((double) (f)) / 65536.)
+
+struct xa_composite_blend {
+ unsigned op : 8;
+
+ unsigned alpha_dst : 4;
+ unsigned alpha_src : 4;
+
+ unsigned rgb_src : 8; /**< PIPE_BLENDFACTOR_x */
+ unsigned rgb_dst : 8; /**< PIPE_BLENDFACTOR_x */
+};
+
+#define XA_BLEND_OP_OVER 3
+static const struct xa_composite_blend xa_blends[] = {
+ { xa_op_clear,
+ 0, 0, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO},
+ { xa_op_src,
+ 0, 0, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ZERO},
+ { xa_op_dst,
+ 0, 0, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ONE},
+ { xa_op_over,
+ 0, 1, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_INV_SRC_ALPHA},
+ { xa_op_over_reverse,
+ 1, 0, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_ONE},
+ { xa_op_in,
+ 1, 0, PIPE_BLENDFACTOR_DST_ALPHA, PIPE_BLENDFACTOR_ZERO},
+ { xa_op_in_reverse,
+ 0, 1, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_SRC_ALPHA},
+ { xa_op_out,
+ 1, 0, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_ZERO},
+ { xa_op_out_reverse,
+ 0, 1, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_INV_SRC_ALPHA},
+ { xa_op_atop,
+ 1, 1, PIPE_BLENDFACTOR_DST_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA},
+ { xa_op_atop_reverse,
+ 1, 1, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_SRC_ALPHA},
+ { xa_op_xor,
+ 1, 1, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA},
+ { xa_op_add,
+ 0, 0, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE},
+};
+
+/*
+ * The alpha value stored in a L8 texture is read by the
+ * hardware as color, and R8 is read as red. The source alpha value
+ * at the end of the fragment shader is stored in all color channels,
+ * so the correct approach is to blend using DST_COLOR instead of
+ * DST_ALPHA and then output any color channel (L8) or the red channel (R8).
+ */
+static unsigned
+xa_convert_blend_for_luminance(unsigned factor)
+{
+ switch(factor) {
+ case PIPE_BLENDFACTOR_DST_ALPHA:
+ return PIPE_BLENDFACTOR_DST_COLOR;
+ case PIPE_BLENDFACTOR_INV_DST_ALPHA:
+ return PIPE_BLENDFACTOR_INV_DST_COLOR;
+ default:
+ break;
+ }
+ return factor;
+}
+
+static boolean
+blend_for_op(struct xa_composite_blend *blend,
+ enum xa_composite_op op,
+ struct xa_picture *src_pic,
+ struct xa_picture *mask_pic,
+ struct xa_picture *dst_pic)
+{
+ const int num_blends =
+ sizeof(xa_blends)/sizeof(struct xa_composite_blend);
+ int i;
+ boolean supported = FALSE;
+
+ /*
+ * our default in case something goes wrong
+ */
+ *blend = xa_blends[XA_BLEND_OP_OVER];
+
+ for (i = 0; i < num_blends; ++i) {
+ if (xa_blends[i].op == op) {
+ *blend = xa_blends[i];
+ supported = TRUE;
+ break;
+ }
+ }
+
+ /*
+ * No component alpha yet.
+ */
+ if (mask_pic && mask_pic->component_alpha && blend->alpha_src)
+ return FALSE;
+
+ if (!dst_pic->srf)
+ return supported;
+
+ if ((dst_pic->srf->tex->format == PIPE_FORMAT_L8_UNORM ||
+ dst_pic->srf->tex->format == PIPE_FORMAT_R8_UNORM)) {
+ blend->rgb_src = xa_convert_blend_for_luminance(blend->rgb_src);
+ blend->rgb_dst = xa_convert_blend_for_luminance(blend->rgb_dst);
+ }
+
+ /*
+ * If there's no dst alpha channel, adjust the blend op so that we'll treat
+ * it as always 1.
+ */
+
+ if (xa_format_a(dst_pic->pict_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 supported;
+}
+
+
+static inline int
+xa_repeat_to_gallium(int mode)
+{
+ switch(mode) {
+ case xa_wrap_clamp_to_border:
+ return PIPE_TEX_WRAP_CLAMP_TO_BORDER;
+ case xa_wrap_repeat:
+ return PIPE_TEX_WRAP_REPEAT;
+ case xa_wrap_mirror_repeat:
+ return PIPE_TEX_WRAP_MIRROR_REPEAT;
+ case xa_wrap_clamp_to_edge:
+ return PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ default:
+ break;
+ }
+ return PIPE_TEX_WRAP_REPEAT;
+}
+
+static inline boolean
+xa_filter_to_gallium(int xrender_filter, int *out_filter)
+{
+
+ switch (xrender_filter) {
+ case xa_filter_nearest:
+ *out_filter = PIPE_TEX_FILTER_NEAREST;
+ break;
+ case xa_filter_linear:
+ *out_filter = PIPE_TEX_FILTER_LINEAR;
+ break;
+ default:
+ *out_filter = PIPE_TEX_FILTER_NEAREST;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static int
+xa_is_filter_accelerated(struct xa_picture *pic)
+{
+ int filter;
+ if (pic && !xa_filter_to_gallium(pic->filter, &filter))
+ return 0;
+ return 1;
+}
+
+/**
+ * xa_src_pict_is_accelerated - Check whether we support acceleration
+ * of the given src_pict type
+ *
+ * \param src_pic[in]: Pointer to a union xa_source_pict to check.
+ *
+ * \returns TRUE if accelerated, FALSE otherwise.
+ */
+static boolean
+xa_src_pict_is_accelerated(const union xa_source_pict *src_pic)
+{
+ if (!src_pic)
+ return TRUE;
+
+ if (src_pic->type == xa_src_pict_solid_fill ||
+ src_pic->type == xa_src_pict_float_solid_fill)
+ return TRUE;
+
+ return FALSE;
+}
+
+XA_EXPORT int
+xa_composite_check_accelerated(const struct xa_composite *comp)
+{
+ struct xa_picture *src_pic = comp->src;
+ struct xa_picture *mask_pic = comp->mask;
+ struct xa_composite_blend blend;
+
+ if (!xa_is_filter_accelerated(src_pic) ||
+ !xa_is_filter_accelerated(comp->mask)) {
+ return -XA_ERR_INVAL;
+ }
+
+ if (!xa_src_pict_is_accelerated(src_pic->src_pict) ||
+ (mask_pic && !xa_src_pict_is_accelerated(mask_pic->src_pict)))
+ return -XA_ERR_INVAL;
+
+ if (!blend_for_op(&blend, comp->op, comp->src, comp->mask, comp->dst))
+ return -XA_ERR_INVAL;
+
+ /*
+ * No component alpha yet.
+ */
+ if (mask_pic && mask_pic->component_alpha && blend.alpha_src)
+ return -XA_ERR_INVAL;
+
+ return XA_ERR_NONE;
+}
+
+static int
+bind_composite_blend_state(struct xa_context *ctx,
+ const struct xa_composite *comp)
+{
+ struct xa_composite_blend blend_opt;
+ struct pipe_blend_state blend;
+
+ if (!blend_for_op(&blend_opt, comp->op, comp->src, comp->mask, comp->dst))
+ return -XA_ERR_INVAL;
+
+ memset(&blend, 0, sizeof(struct pipe_blend_state));
+ 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(ctx->cso, &blend);
+ return XA_ERR_NONE;
+}
+
+static unsigned int
+picture_format_fixups(struct xa_picture *src_pic,
+ int mask)
+{
+ boolean set_alpha = FALSE;
+ boolean swizzle = FALSE;
+ unsigned ret = 0;
+ struct xa_surface *src = src_pic->srf;
+ enum xa_formats src_hw_format, src_pic_format;
+ enum xa_surface_type src_hw_type, src_pic_type;
+
+ if (!src)
+ return 0;
+
+ src_hw_format = xa_surface_format(src);
+ src_pic_format = src_pic->pict_format;
+
+ set_alpha = (xa_format_type_is_color(src_hw_format) &&
+ xa_format_a(src_pic_format) == 0);
+
+ if (set_alpha)
+ ret |= mask ? FS_MASK_SET_ALPHA : FS_SRC_SET_ALPHA;
+
+ if (src_hw_format == src_pic_format) {
+ if (src->tex->format == PIPE_FORMAT_L8_UNORM ||
+ src->tex->format == PIPE_FORMAT_R8_UNORM)
+ return ((mask) ? FS_MASK_LUMINANCE : FS_SRC_LUMINANCE);
+
+ return ret;
+ }
+
+ src_hw_type = xa_format_type(src_hw_format);
+ src_pic_type = xa_format_type(src_pic_format);
+
+ swizzle = ((src_hw_type == xa_type_argb &&
+ src_pic_type == xa_type_abgr) ||
+ ((src_hw_type == xa_type_abgr &&
+ src_pic_type == xa_type_argb)));
+
+ if (!swizzle && (src_hw_type != src_pic_type))
+ return ret;
+
+ if (swizzle)
+ ret |= mask ? FS_MASK_SWIZZLE_RGB : FS_SRC_SWIZZLE_RGB;
+
+ return ret;
+}
+
+static void
+xa_src_in_mask(float src[4], const float mask[4])
+{
+ src[0] *= mask[3];
+ src[1] *= mask[3];
+ src[2] *= mask[3];
+ src[3] *= mask[3];
+}
+
+/**
+ * xa_handle_src_pict - Set up xa_context state and fragment shader
+ * input based on scr_pict type
+ *
+ * \param ctx[in, out]: Pointer to the xa context.
+ * \param src_pict[in]: Pointer to the union xa_source_pict to consider.
+ * \param is_mask[in]: Whether we're considering a mask picture.
+ *
+ * \returns TRUE if succesful, FALSE otherwise.
+ *
+ * This function computes some xa_context state used to determine whether
+ * to upload the solid color and also the solid color itself used as an input
+ * to the fragment shader.
+ */
+static boolean
+xa_handle_src_pict(struct xa_context *ctx,
+ const union xa_source_pict *src_pict,
+ boolean is_mask)
+{
+ float solid_color[4];
+
+ switch(src_pict->type) {
+ case xa_src_pict_solid_fill:
+ xa_pixel_to_float4(src_pict->solid_fill.color, solid_color);
+ break;
+ case xa_src_pict_float_solid_fill:
+ memcpy(solid_color, src_pict->float_solid_fill.color,
+ sizeof(solid_color));
+ break;
+ default:
+ return FALSE;
+ }
+
+ if (is_mask && ctx->has_solid_src)
+ xa_src_in_mask(ctx->solid_color, solid_color);
+ else
+ memcpy(ctx->solid_color, solid_color, sizeof(solid_color));
+
+ if (is_mask)
+ ctx->has_solid_mask = TRUE;
+ else
+ ctx->has_solid_src = TRUE;
+
+ return TRUE;
+}
+
+static int
+bind_shaders(struct xa_context *ctx, const struct xa_composite *comp)
+{
+ unsigned vs_traits = 0, fs_traits = 0;
+ struct xa_shader shader;
+ struct xa_picture *src_pic = comp->src;
+ struct xa_picture *mask_pic = comp->mask;
+ struct xa_picture *dst_pic = comp->dst;
+
+ ctx->has_solid_src = FALSE;
+ ctx->has_solid_mask = FALSE;
+
+ if (dst_pic && xa_format_type(dst_pic->pict_format) !=
+ xa_format_type(xa_surface_format(dst_pic->srf)))
+ return -XA_ERR_INVAL;
+
+ if (src_pic) {
+ if (src_pic->wrap == xa_wrap_clamp_to_border && src_pic->has_transform)
+ fs_traits |= FS_SRC_REPEAT_NONE;
+
+ fs_traits |= FS_COMPOSITE;
+ vs_traits |= VS_COMPOSITE;
+
+ if (src_pic->src_pict) {
+ if (!xa_handle_src_pict(ctx, src_pic->src_pict, false))
+ return -XA_ERR_INVAL;
+ fs_traits |= FS_SRC_SRC;
+ vs_traits |= VS_SRC_SRC;
+ } else
+ fs_traits |= picture_format_fixups(src_pic, 0);
+ }
+
+ if (mask_pic) {
+ vs_traits |= VS_MASK;
+ fs_traits |= FS_MASK;
+ if (mask_pic->component_alpha)
+ fs_traits |= FS_CA;
+ if (mask_pic->src_pict) {
+ if (!xa_handle_src_pict(ctx, mask_pic->src_pict, true))
+ return -XA_ERR_INVAL;
+
+ if (ctx->has_solid_src) {
+ vs_traits &= ~VS_MASK;
+ fs_traits &= ~FS_MASK;
+ } else {
+ vs_traits |= VS_MASK_SRC;
+ fs_traits |= FS_MASK_SRC;
+ }
+ } else {
+ if (mask_pic->wrap == xa_wrap_clamp_to_border &&
+ mask_pic->has_transform)
+ fs_traits |= FS_MASK_REPEAT_NONE;
+
+ fs_traits |= picture_format_fixups(mask_pic, 1);
+ }
+ }
+
+ if (ctx->srf->format == PIPE_FORMAT_L8_UNORM ||
+ ctx->srf->format == PIPE_FORMAT_R8_UNORM)
+ fs_traits |= FS_DST_LUMINANCE;
+
+ shader = xa_shaders_get(ctx->shaders, vs_traits, fs_traits);
+ cso_set_vertex_shader_handle(ctx->cso, shader.vs);
+ cso_set_fragment_shader_handle(ctx->cso, shader.fs);
+ return XA_ERR_NONE;
+}
+
+static void
+bind_samplers(struct xa_context *ctx,
+ const struct xa_composite *comp)
+{
+ struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
+ struct pipe_sampler_state src_sampler, mask_sampler;
+ struct pipe_sampler_view view_templ;
+ struct pipe_sampler_view *src_view;
+ struct pipe_context *pipe = ctx->pipe;
+ struct xa_picture *src_pic = comp->src;
+ struct xa_picture *mask_pic = comp->mask;
+ int num_samplers = 0;
+
+ xa_ctx_sampler_views_destroy(ctx);
+ memset(&src_sampler, 0, sizeof(struct pipe_sampler_state));
+ memset(&mask_sampler, 0, sizeof(struct pipe_sampler_state));
+
+ if (src_pic && !ctx->has_solid_src) {
+ unsigned src_wrap = xa_repeat_to_gallium(src_pic->wrap);
+ int filter;
+
+ (void) xa_filter_to_gallium(src_pic->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;
+ u_sampler_view_default_template(&view_templ,
+ src_pic->srf->tex,+ src_pic->srf->tex->format);
+ src_view = pipe->create_sampler_view(pipe, src_pic->srf->tex,
+ &view_templ);
+ ctx->bound_sampler_views[0] = src_view;
+ num_samplers++;
+ }
+
+ if (mask_pic && !ctx->has_solid_mask) {
+ unsigned mask_wrap = xa_repeat_to_gallium(mask_pic->wrap);
+ int filter;
+
+ (void) xa_filter_to_gallium(mask_pic->filter, &filter);
+
+ mask_sampler.wrap_s = mask_wrap;
+ mask_sampler.wrap_t = mask_wrap;
+ 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[num_samplers] = &mask_sampler;
+ u_sampler_view_default_template(&view_templ,
+ mask_pic->srf->tex,
+ mask_pic->srf->tex->format);
+ src_view = pipe->create_sampler_view(pipe, mask_pic->srf->tex,
+ &view_templ);
+ ctx->bound_sampler_views[num_samplers] = src_view;
+ num_samplers++;
+ }
+
+ cso_set_samplers(ctx->cso, PIPE_SHADER_FRAGMENT, num_samplers,
+ (const struct pipe_sampler_state **)samplers);
+ cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, num_samplers,
+ ctx->bound_sampler_views);
+ ctx->num_bound_samplers = num_samplers;
+}
+
+XA_EXPORT int
+xa_composite_prepare(struct xa_context *ctx,
+ const struct xa_composite *comp)
+{
+ struct xa_surface *dst_srf = comp->dst->srf;
+ int ret;
+
+ ret = xa_ctx_srf_create(ctx, dst_srf);
+ if (ret != XA_ERR_NONE)
+ return ret;
+
+ ctx->dst = dst_srf;
+ renderer_bind_destination(ctx, ctx->srf);
+
+ ret = bind_composite_blend_state(ctx, comp);
+ if (ret != XA_ERR_NONE)
+ return ret;
+ ret = bind_shaders(ctx, comp);
+ if (ret != XA_ERR_NONE)
+ return ret;
+ bind_samplers(ctx, comp);
+
+ if (ctx->num_bound_samplers == 0 ) { /* solid fill */
+ renderer_begin_solid(ctx);
+ } else {
+ renderer_begin_textures(ctx);
+ ctx->comp = comp;
+ }
+
+ xa_ctx_srf_destroy(ctx);
+ return XA_ERR_NONE;
+}
+
+XA_EXPORT void
+xa_composite_rect(struct xa_context *ctx,
+ int srcX, int srcY, int maskX, int maskY,
+ int dstX, int dstY, int width, int height)
+{
+ if (ctx->num_bound_samplers == 0 ) { /* solid fill */
+ xa_scissor_update(ctx, dstX, dstY, dstX + width, dstY + height);
+ renderer_solid(ctx, dstX, dstY, dstX + width, dstY + height);
+ } else {
+ const struct xa_composite *comp = ctx->comp;
+ int pos[6] = {srcX, srcY, maskX, maskY, dstX, dstY};
+ const float *src_matrix = NULL;
+ const float *mask_matrix = NULL;
+
+ xa_scissor_update(ctx, dstX, dstY, dstX + width, dstY + height);
+
+ if (comp->src->has_transform)
+ src_matrix = comp->src->transform;
+ if (comp->mask && comp->mask->has_transform)
+ mask_matrix = comp->mask->transform;
+
+ renderer_texture(ctx, pos, width, height,
+ src_matrix, mask_matrix);
+ }
+}
+
+XA_EXPORT void
+xa_composite_done(struct xa_context *ctx)
+{
+ renderer_draw_flush(ctx);
+
+ ctx->comp = NULL;
+ ctx->has_solid_src = FALSE;
+ ctx->has_solid_mask = FALSE;
+ xa_ctx_sampler_views_destroy(ctx);
+}
+
+static const struct xa_composite_allocation a = {
+ .xa_composite_size = sizeof(struct xa_composite),
+ .xa_picture_size = sizeof(struct xa_picture),
+ .xa_source_pict_size = sizeof(union xa_source_pict),
+};
+
+XA_EXPORT const struct xa_composite_allocation *
+xa_composite_allocation(void)
+{
+ return &a;
+}
diff --git a/src/gallium/frontends/xa/xa_composite.h b/src/gallium/frontends/xa/xa_composite.h
new file mode 100644
index 00000000000..7e3737a63d2
--- /dev/null
+++ b/src/gallium/frontends/xa/xa_composite.h
@@ -0,0 +1,156 @@
+/**********************************************************
+ * Copyright 2009-2011 VMware, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ *********************************************************
+ * Authors:
+ * Zack Rusin <zackr-at-vmware-dot-com>
+ * Thomas Hellstrom <thellstrom-at-vmware-dot-com>
+ */
+
+#ifndef _XA_COMPOSITE_H_
+#define _XA_COMPOSITE_H_
+
+#include "xa_tracker.h"
+#include "xa_context.h"
+
+/*
+ * Supported composite ops.
+ */
+enum xa_composite_op {
+ xa_op_clear,
+ xa_op_src,
+ xa_op_dst,
+ xa_op_over,
+ xa_op_over_reverse,
+ xa_op_in,
+ xa_op_in_reverse,
+ xa_op_out,
+ xa_op_out_reverse,
+ xa_op_atop,
+ xa_op_atop_reverse,
+ xa_op_xor,
+ xa_op_add
+};
+
+/*
+ * Supported filters.
+ */
+enum xa_composite_filter {
+ xa_filter_nearest,
+ xa_filter_linear
+};
+
+/*
+ * Supported clamp methods.
+ */
+enum xa_composite_wrap {
+ xa_wrap_clamp_to_border,
+ xa_wrap_repeat,
+ xa_wrap_mirror_repeat,
+ xa_wrap_clamp_to_edge
+};
+
+/*
+ * Src picture types.
+ */
+enum xa_composite_src_pict_type {
+ xa_src_pict_solid_fill,
+ xa_src_pict_float_solid_fill
+};
+
+
+/*
+ * struct xa_pict_solid_fill - Description of a solid_fill picture
+ * Deprecated. Use struct xa_pict_float_solid_fill instead.
+ */
+struct xa_pict_solid_fill {
+ enum xa_composite_src_pict_type type;
+ unsigned int class;
+ uint32_t color;
+};
+
+/*
+ * struct xa_pict_solid_fill - Description of a solid_fill picture
+ * with color channels represented by floats.
+ */
+struct xa_pict_float_solid_fill {
+ enum xa_composite_src_pict_type type;
+ float color[4]; /* R, G, B, A */
+};
+
+union xa_source_pict {
+ enum xa_composite_src_pict_type type;
+ struct xa_pict_solid_fill solid_fill;
+ struct xa_pict_float_solid_fill float_solid_fill;
+};
+
+struct xa_picture {
+ enum xa_formats pict_format;
+ struct xa_surface *srf;
+ struct xa_surface *alpha_map;
+ float transform[9];
+ int has_transform;
+ int component_alpha;
+ enum xa_composite_wrap wrap;
+ enum xa_composite_filter filter;
+ union xa_source_pict *src_pict;
+};
+
+struct xa_composite {
+ struct xa_picture *src, *mask, *dst;
+ int op;
+ int no_solid;
+};
+
+struct xa_composite_allocation {
+ unsigned int xa_composite_size;
+ unsigned int xa_picture_size;
+ unsigned int xa_source_pict_size;
+};
+
+/*
+ * Get allocation sizes for minor bump compatibility.
+ */
+
+extern const struct xa_composite_allocation *
+xa_composite_allocation(void);
+
+/*
+ * This function checks most things except the format of the hardware
+ * surfaces, since they are generally not available at the time this
+ * function is called. Returns usual XA error codes.
+ */
+extern int
+xa_composite_check_accelerated(const struct xa_composite *comp);
+
+extern int
+xa_composite_prepare(struct xa_context *ctx, const struct xa_composite *comp);
+
+extern void
+xa_composite_rect(struct xa_context *ctx,
+ int srcX, int srcY, int maskX, int maskY,
+ int dstX, int dstY, int width, int height);
+extern void
+xa_composite_done(struct xa_context *ctx);
+
+#endif
diff --git a/src/gallium/frontends/xa/xa_context.c b/src/gallium/frontends/xa/xa_context.c
new file mode 100644
index 00000000000..a4630cf09ca
--- /dev/null
+++ b/src/gallium/frontends/xa/xa_context.c
@@ -0,0 +1,419 @@
+/**********************************************************
+ * Copyright 2009-2011 VMware, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ *********************************************************
+ * Authors:
+ * Zack Rusin <zackr-at-vmware-dot-com>
+ * Thomas Hellstrom <thellstrom-at-vmware-dot-com>
+ */
+#include "xa_context.h"
+#include "xa_priv.h"
+#include "cso_cache/cso_context.h"
+#include "util/u_inlines.h"
+#include "util/u_rect.h"
+#include "util/u_surface.h"
+#include "pipe/p_context.h"
+
+XA_EXPORT void
+xa_context_flush(struct xa_context *ctx)
+{
+ if (ctx->last_fence) {
+ struct pipe_screen *screen = ctx->xa->screen;
+ screen->fence_reference(screen, &ctx->last_fence, NULL);
+ }
+ ctx->pipe->flush(ctx->pipe, &ctx->last_fence, 0);
+}
+
+XA_EXPORT struct xa_context *
+xa_context_default(struct xa_tracker *xa)
+{
+ return xa->default_ctx;
+}
+
+XA_EXPORT struct xa_context *
+xa_context_create(struct xa_tracker *xa)
+{
+ struct xa_context *ctx = calloc(1, sizeof(*ctx));
+
+ ctx->xa = xa;
+ ctx->pipe = xa->screen->context_create(xa->screen, NULL, 0);
+ ctx->cso = cso_create_context(ctx->pipe, 0);
+ ctx->shaders = xa_shaders_create(ctx);
+ renderer_init_state(ctx);
+
+ return ctx;
+}
+
+XA_EXPORT void
+xa_context_destroy(struct xa_context *r)
+{
+ struct pipe_resource **vsbuf = &r->vs_const_buffer;
+ struct pipe_resource **fsbuf = &r->fs_const_buffer;
+
+ if (*vsbuf)
+ pipe_resource_reference(vsbuf, NULL);
+
+ if (*fsbuf)
+ pipe_resource_reference(fsbuf, NULL);
+
+ if (r->shaders) {
+ xa_shaders_destroy(r->shaders);
+ r->shaders = NULL;
+ }
+
+ xa_ctx_sampler_views_destroy(r);
+ if (r->srf)
+ pipe_surface_reference(&r->srf, NULL);
+
+ if (r->cso) {
+ cso_destroy_context(r->cso);
+ r->cso = NULL;
+ }
+
+ r->pipe->destroy(r->pipe);
+ free(r);
+}
+
+XA_EXPORT int
+xa_surface_dma(struct xa_context *ctx,
+ struct xa_surface *srf,
+ void *data,
+ unsigned int pitch,
+ int to_surface, struct xa_box *boxes, unsigned int num_boxes)
+{
+ struct pipe_transfer *transfer;
+ void *map;
+ int w, h, i;
+ enum pipe_transfer_usage transfer_direction;
+ struct pipe_context *pipe = ctx->pipe;
+
+ transfer_direction = (to_surface ? PIPE_TRANSFER_WRITE :
+ PIPE_TRANSFER_READ);
+
+ for (i = 0; i < num_boxes; ++i, ++boxes) {
+ w = boxes->x2 - boxes->x1;
+ h = boxes->y2 - boxes->y1;
+
+ map = pipe_transfer_map(pipe, srf->tex, 0, 0,
+ transfer_direction, boxes->x1, boxes->y1,
+ w, h, &transfer);
+ if (!map)
+ return -XA_ERR_NORES;
+
+ if (to_surface) {
+ util_copy_rect(map, srf->tex->format, transfer->stride,
+ 0, 0, w, h, data, pitch, boxes->x1, boxes->y1);
+ } else {
+ util_copy_rect(data, srf->tex->format, pitch,
+ boxes->x1, boxes->y1, w, h, map, transfer->stride, 0,
+ 0);
+ }
+ pipe->transfer_unmap(pipe, transfer);
+ }
+ return XA_ERR_NONE;
+}
+
+XA_EXPORT void *
+xa_surface_map(struct xa_context *ctx,
+ struct xa_surface *srf, unsigned int usage)
+{
+ void *map;
+ unsigned int gallium_usage = 0;
+ struct pipe_context *pipe = ctx->pipe;
+
+ /*
+ * A surface may only have a single map.
+ */
+ if (srf->transfer)
+ return NULL;
+
+ if (usage & XA_MAP_READ)
+ gallium_usage |= PIPE_TRANSFER_READ;
+ if (usage & XA_MAP_WRITE)
+ gallium_usage |= PIPE_TRANSFER_WRITE;
+ if (usage & XA_MAP_MAP_DIRECTLY)
+ gallium_usage |= PIPE_TRANSFER_MAP_DIRECTLY;
+ if (usage & XA_MAP_UNSYNCHRONIZED)
+ gallium_usage |= PIPE_TRANSFER_UNSYNCHRONIZED;
+ if (usage & XA_MAP_DONTBLOCK)
+ gallium_usage |= PIPE_TRANSFER_DONTBLOCK;
+ if (usage & XA_MAP_DISCARD_WHOLE_RESOURCE)
+ gallium_usage |= PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE;
+
+ if (!(gallium_usage & (PIPE_TRANSFER_READ_WRITE)))
+ return NULL;
+
+ map = pipe_transfer_map(pipe, srf->tex, 0, 0,
+ gallium_usage, 0, 0,
+ srf->tex->width0, srf->tex->height0,
+ &srf->transfer);
+ if (!map)
+ return NULL;
+
+ srf->mapping_pipe = pipe;
+ return map;
+}
+
+XA_EXPORT void
+xa_surface_unmap(struct xa_surface *srf)
+{
+ if (srf->transfer) {
+ struct pipe_context *pipe = srf->mapping_pipe;
+
+ pipe->transfer_unmap(pipe, srf->transfer);
+ srf->transfer = NULL;
+ }
+}
+
+int
+xa_ctx_srf_create(struct xa_context *ctx, struct xa_surface *dst)
+{
+ struct pipe_screen *screen = ctx->pipe->screen;
+ struct pipe_surface srf_templ;
+
+ /*
+ * Cache surfaces unless we change render target
+ */
+ if (ctx->srf) {
+ if (ctx->srf->texture == dst->tex)
+ return XA_ERR_NONE;
+
+ pipe_surface_reference(&ctx->srf, NULL);
+ }
+
+ if (!screen->is_format_supported(screen, dst->tex->format,
+ PIPE_TEXTURE_2D, 0, 0,
+ PIPE_BIND_RENDER_TARGET))
+ return -XA_ERR_INVAL;
+
+ u_surface_default_template(&srf_templ, dst->tex);
+ ctx->srf = ctx->pipe->create_surface(ctx->pipe, dst->tex, &srf_templ);
+ if (!ctx->srf)
+ return -XA_ERR_NORES;
+
+ return XA_ERR_NONE;
+}
+
+void
+xa_ctx_srf_destroy(struct xa_context *ctx)
+{
+ /*
+ * Cache surfaces unless we change render target.
+ * Final destruction on context destroy.
+ */
+}
+
+XA_EXPORT int
+xa_copy_prepare(struct xa_context *ctx,
+ struct xa_surface *dst, struct xa_surface *src)
+{
+ if (src == dst)
+ return -XA_ERR_INVAL;
+
+ if (src->tex->format != dst->tex->format) {
+ int ret = xa_ctx_srf_create(ctx, dst);
+ if (ret != XA_ERR_NONE)
+ return ret;
+ renderer_copy_prepare(ctx, ctx->srf, src->tex,
+ src->fdesc.xa_format,
+ dst->fdesc.xa_format);
+ ctx->simple_copy = 0;
+ } else
+ ctx->simple_copy = 1;
+
+ ctx->src = src;
+ ctx->dst = dst;
+ xa_ctx_srf_destroy(ctx);
+
+ return 0;
+}
+
+XA_EXPORT void
+xa_copy(struct xa_context *ctx,
+ int dx, int dy, int sx, int sy, int width, int height)
+{
+ struct pipe_box src_box;
+
+ xa_scissor_update(ctx, dx, dy, dx + width, dy + height);
+
+ if (ctx->simple_copy) {
+ u_box_2d(sx, sy, width, height, &src_box);
+ ctx->pipe->resource_copy_region(ctx->pipe,
+ ctx->dst->tex, 0, dx, dy, 0,
+ ctx->src->tex,
+ 0, &src_box);
+ } else
+ renderer_copy(ctx, dx, dy, sx, sy, width, height,
+ (float) ctx->src->tex->width0,
+ (float) ctx->src->tex->height0);
+}
+
+XA_EXPORT void
+xa_copy_done(struct xa_context *ctx)
+{
+ if (!ctx->simple_copy) {
+ renderer_draw_flush(ctx);
+ }
+}
+
+static void
+bind_solid_blend_state(struct xa_context *ctx)
+{
+ struct pipe_blend_state blend;
+
+ memset(&blend, 0, sizeof(struct pipe_blend_state));
+ blend.rt[0].blend_enable = 0;
+ blend.rt[0].colormask = PIPE_MASK_RGBA;
+
+ blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
+
+ cso_set_blend(ctx->cso, &blend);
+}
+
+XA_EXPORT int
+xa_solid_prepare(struct xa_context *ctx, struct xa_surface *dst,
+ uint32_t fg)
+{
+ unsigned vs_traits, fs_traits;
+ struct xa_shader shader;
+ int ret;
+
+ ret = xa_ctx_srf_create(ctx, dst);
+ if (ret != XA_ERR_NONE)
+ return ret;
+
+ if (ctx->srf->format == PIPE_FORMAT_L8_UNORM)
+ xa_pixel_to_float4_a8(fg, ctx->solid_color);
+ else
+ xa_pixel_to_float4(fg, ctx->solid_color);
+ ctx->has_solid_src = 1;
+
+ ctx->dst = dst;
+
+#if 0
+ 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
+
+ vs_traits = VS_SRC_SRC | VS_COMPOSITE;
+ fs_traits = FS_SRC_SRC | VS_COMPOSITE;
+
+ renderer_bind_destination(ctx, ctx->srf);
+ bind_solid_blend_state(ctx);
+ cso_set_samplers(ctx->cso, PIPE_SHADER_FRAGMENT, 0, NULL);
+ cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 0, NULL);
+
+ shader = xa_shaders_get(ctx->shaders, vs_traits, fs_traits);
+ cso_set_vertex_shader_handle(ctx->cso, shader.vs);
+ cso_set_fragment_shader_handle(ctx->cso, shader.fs);
+
+ renderer_begin_solid(ctx);
+
+ xa_ctx_srf_destroy(ctx);
+ return XA_ERR_NONE;
+}
+
+XA_EXPORT void
+xa_solid(struct xa_context *ctx, int x, int y, int width, int height)
+{
+ xa_scissor_update(ctx, x, y, x + width, y + height);
+ renderer_solid(ctx, x, y, x + width, y + height);
+}
+
+XA_EXPORT void
+xa_solid_done(struct xa_context *ctx)
+{
+ renderer_draw_flush(ctx);
+ ctx->comp = NULL;
+ ctx->has_solid_src = FALSE;
+ ctx->num_bound_samplers = 0;
+}
+
+XA_EXPORT struct xa_fence *
+xa_fence_get(struct xa_context *ctx)
+{
+ struct xa_fence *fence = calloc(1, sizeof(*fence));
+ struct pipe_screen *screen = ctx->xa->screen;
+
+ if (!fence)
+ return NULL;
+
+ fence->xa = ctx->xa;
+
+ if (ctx->last_fence == NULL)
+ fence->pipe_fence = NULL;
+ else
+ screen->fence_reference(screen, &fence->pipe_fence, ctx->last_fence);
+
+ return fence;
+}
+
+XA_EXPORT int
+xa_fence_wait(struct xa_fence *fence, uint64_t timeout)
+{
+ if (!fence)
+ return XA_ERR_NONE;
+
+ if (fence->pipe_fence) {
+ struct pipe_screen *screen = fence->xa->screen;
+ boolean timed_out;
+
+ timed_out = !screen->fence_finish(screen, NULL, fence->pipe_fence, timeout);
+ if (timed_out)
+ return -XA_ERR_BUSY;
+
+ screen->fence_reference(screen, &fence->pipe_fence, NULL);
+ }
+ return XA_ERR_NONE;
+}
+
+XA_EXPORT void
+xa_fence_destroy(struct xa_fence *fence)
+{
+ if (!fence)
+ return;
+
+ if (fence->pipe_fence) {
+ struct pipe_screen *screen = fence->xa->screen;
+
+ screen->fence_reference(screen, &fence->pipe_fence, NULL);
+ }
+
+ free(fence);
+}
+
+void
+xa_ctx_sampler_views_destroy(struct xa_context *ctx)
+{
+ int i;
+
+ for (i = 0; i < ctx->num_bound_samplers; ++i)
+ pipe_sampler_view_reference(&ctx->bound_sampler_views[i], NULL);
+ ctx->num_bound_samplers = 0;
+}
diff --git a/src/gallium/frontends/xa/xa_context.h b/src/gallium/frontends/xa/xa_context.h
new file mode 100644
index 00000000000..202b8e56e23
--- /dev/null
+++ b/src/gallium/frontends/xa/xa_context.h
@@ -0,0 +1,101 @@
+/**********************************************************
+ * Copyright 2009-2011 VMware, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ *********************************************************
+ * Authors:
+ * Zack Rusin <zackr-at-vmware-dot-com>
+ * Thomas Hellstrom <thellstrom-at-vmware-dot-com>
+ */
+
+#ifndef _XA_CONTEXT_H_
+#define _XA_CONTEXT_H_
+#include "xa_tracker.h"
+#include <stdint.h>
+
+struct xa_context;
+
+extern struct xa_context *xa_context_default(struct xa_tracker *xa);
+
+extern struct xa_context *xa_context_create(struct xa_tracker *xa);
+
+extern void xa_context_destroy(struct xa_context *r);
+
+extern void xa_context_flush(struct xa_context *ctx);
+
+/**
+ * xa_yuv_planar_blit - 2D blit with color conversion and scaling.
+ *
+ * Performs a scaled blit with color conversion according to
+ * (R,G,B,A)^T = (CM)^T (Y,U,V,1)^T, where @conversion_matrix or CM in the
+ * formula is a four by four coefficient matrix. The input variable
+ * @yuv is an array of three xa_yuv_component surfaces.
+ */
+extern int xa_yuv_planar_blit(struct xa_context *r,
+ int src_x,
+ int src_y,
+ int src_w,
+ int src_h,
+ int dst_x,
+ int dst_y,
+ int dst_w,
+ int dst_h,
+ struct xa_box *box,
+ unsigned int num_boxes,
+ const float conversion_matrix[],
+ struct xa_surface *dst, struct xa_surface *yuv[]);
+
+extern int xa_copy_prepare(struct xa_context *ctx,
+ struct xa_surface *dst, struct xa_surface *src);
+
+extern void xa_copy(struct xa_context *ctx,
+ int dx, int dy, int sx, int sy, int width, int height);
+
+extern void xa_copy_done(struct xa_context *ctx);
+
+extern int xa_surface_dma(struct xa_context *ctx,
+ struct xa_surface *srf,
+ void *data,
+ unsigned int byte_pitch,
+ int to_surface, struct xa_box *boxes,
+ unsigned int num_boxes);
+
+extern void *xa_surface_map(struct xa_context *ctx,
+ struct xa_surface *srf, unsigned int usage);
+
+extern void xa_surface_unmap(struct xa_surface *srf);
+
+extern int
+xa_solid_prepare(struct xa_context *ctx, struct xa_surface *dst,
+ uint32_t fg);
+extern void
+xa_solid(struct xa_context *ctx, int x, int y, int width, int height);
+
+extern void
+xa_solid_done(struct xa_context *ctx);
+
+extern struct xa_fence *xa_fence_get(struct xa_context *ctx);
+
+extern int xa_fence_wait(struct xa_fence *fence, uint64_t timeout);
+
+extern void xa_fence_destroy(struct xa_fence *fence);
+#endif
diff --git a/src/gallium/frontends/xa/xa_priv.h b/src/gallium/frontends/xa/xa_priv.h
new file mode 100644
index 00000000000..f368de3b81f
--- /dev/null
+++ b/src/gallium/frontends/xa/xa_priv.h
@@ -0,0 +1,289 @@
+/**********************************************************
+ * Copyright 2009-2011 VMware, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ *********************************************************
+ * Authors:
+ * Zack Rusin <zackr-at-vmware-dot-com>
+ * Thomas Hellstrom <thellstrom-at-vmware-dot-com>
+ */
+
+#ifndef _XA_PRIV_H_
+#define _XA_PRIV_H_
+
+#include "xa_tracker.h"
+#include "xa_context.h"
+#include "xa_composite.h"
+
+#include "pipe/p_screen.h"
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+
+#include "util/u_math.h"
+
+#if defined(__GNUC__)
+#define XA_EXPORT __attribute__ ((visibility("default")))
+#else
+#define XA_EXPORT
+#endif
+
+#define XA_VB_SIZE (100 * 4 * 3 * 4)
+#define XA_LAST_SURFACE_TYPE (xa_type_yuv_component + 1)
+#define XA_MAX_SAMPLERS 3
+
+struct xa_fence {
+ struct pipe_fence_handle *pipe_fence;
+ struct xa_tracker *xa;
+};
+
+struct xa_format_descriptor {
+ enum pipe_format format;
+ enum xa_formats xa_format;
+};
+
+struct xa_surface {
+ int refcount;
+ struct pipe_resource template;
+ struct xa_tracker *xa;
+ struct pipe_resource *tex;
+ struct pipe_transfer *transfer;
+ unsigned int flags;
+ struct xa_format_descriptor fdesc;
+ struct pipe_context *mapping_pipe;
+};
+
+struct xa_tracker {
+ enum xa_formats *supported_formats;
+ unsigned int format_map[XA_LAST_SURFACE_TYPE][2];
+ struct pipe_loader_device *dev;
+ struct pipe_screen *screen;
+ struct xa_context *default_ctx;
+};
+
+struct xa_context {
+ struct xa_tracker *xa;
+ struct pipe_context *pipe;
+
+ struct cso_context *cso;
+ struct xa_shaders *shaders;
+
+ struct pipe_resource *vs_const_buffer;
+ struct pipe_resource *fs_const_buffer;
+
+ float buffer[XA_VB_SIZE];
+ unsigned int buffer_size;
+ struct pipe_vertex_element velems[3];
+
+ /* number of attributes per vertex for the current
+ * draw operation */
+ unsigned int attrs_per_vertex;
+
+ unsigned int fb_width;
+ unsigned int fb_height;
+
+ struct pipe_fence_handle *last_fence;
+ struct xa_surface *src;
+ struct xa_surface *dst;
+ struct pipe_surface *srf;
+
+ /* destination scissor state.. we scissor out untouched parts
+ * of the dst for the benefit of tilers:
+ */
+ struct pipe_scissor_state scissor;
+ int scissor_valid;
+
+ int simple_copy;
+
+ int has_solid_src;
+ int has_solid_mask;
+ float solid_color[4];
+
+ unsigned int num_bound_samplers;
+ struct pipe_sampler_view *bound_sampler_views[XA_MAX_SAMPLERS];
+ const struct xa_composite *comp;
+};
+
+static inline void
+xa_scissor_reset(struct xa_context *ctx)
+{
+ ctx->scissor.maxx = 0;
+ ctx->scissor.maxy = 0;
+ ctx->scissor.minx = ~0;
+ ctx->scissor.miny = ~0;
+ ctx->scissor_valid = FALSE;
+}
+
+static inline void
+xa_scissor_update(struct xa_context *ctx, unsigned minx, unsigned miny,
+ unsigned maxx, unsigned maxy)
+{
+ ctx->scissor.maxx = MAX2(ctx->scissor.maxx, maxx);
+ ctx->scissor.maxy = MAX2(ctx->scissor.maxy, maxy);
+ ctx->scissor.minx = MIN2(ctx->scissor.minx, minx);
+ ctx->scissor.miny = MIN2(ctx->scissor.miny, miny);
+ ctx->scissor_valid = TRUE;
+}
+
+enum xa_vs_traits {
+ VS_COMPOSITE = 1 << 0,
+ VS_MASK = 1 << 1,
+ VS_SRC_SRC = 1 << 2,
+ VS_MASK_SRC = 1 << 3,
+ VS_YUV = 1 << 4,
+};
+
+enum xa_fs_traits {
+ FS_COMPOSITE = 1 << 0,
+ FS_MASK = 1 << 1,
+ FS_SRC_SRC = 1 << 2,
+ FS_MASK_SRC = 1 << 3,
+ FS_YUV = 1 << 4,
+ FS_SRC_REPEAT_NONE = 1 << 5,
+ FS_MASK_REPEAT_NONE = 1 << 6,
+ FS_SRC_SWIZZLE_RGB = 1 << 7,
+ FS_MASK_SWIZZLE_RGB = 1 << 8,
+ FS_SRC_SET_ALPHA = 1 << 9,
+ FS_MASK_SET_ALPHA = 1 << 10,
+ FS_SRC_LUMINANCE = 1 << 11,
+ FS_MASK_LUMINANCE = 1 << 12,
+ FS_DST_LUMINANCE = 1 << 13,
+ FS_CA = 1 << 14,
+};
+
+struct xa_shader {
+ void *fs;
+ void *vs;
+};
+
+struct xa_shaders;
+
+/*
+ * Inline utilities
+ */
+
+static inline int
+xa_min(int a, int b)
+{
+ return ((a <= b) ? a : b);
+}
+
+static inline void
+xa_pixel_to_float4(uint32_t pixel, float *color)
+{
+ uint32_t 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.;
+}
+
+static inline void
+xa_pixel_to_float4_a8(uint32_t pixel, float *color)
+{
+ uint32_t a;
+
+ a = (pixel >> 24) & 0xff;
+ color[0] = ((float)a) / 255.;
+ color[1] = ((float)a) / 255.;
+ color[2] = ((float)a) / 255.;
+ color[3] = ((float)a) / 255.;
+}
+
+/*
+ * xa_tgsi.c
+ */
+
+extern struct xa_shaders *xa_shaders_create(struct xa_context *);
+
+void xa_shaders_destroy(struct xa_shaders *shaders);
+
+struct xa_shader xa_shaders_get(struct xa_shaders *shaders,
+ unsigned vs_traits, unsigned fs_traits);
+
+/*
+ * xa_context.c
+ */
+extern void
+xa_context_flush(struct xa_context *ctx);
+
+extern int
+xa_ctx_srf_create(struct xa_context *ctx, struct xa_surface *dst);
+
+extern void
+xa_ctx_srf_destroy(struct xa_context *ctx);
+
+extern void
+xa_ctx_sampler_views_destroy(struct xa_context *ctx);
+
+/*
+ * xa_renderer.c
+ */
+void renderer_set_constants(struct xa_context *r,
+ int shader_type, const float *params,
+ int param_bytes);
+
+void renderer_draw_yuv(struct xa_context *r,
+ float src_x,
+ float src_y,
+ float src_w,
+ float src_h,
+ int dst_x,
+ int dst_y, int dst_w, int dst_h,
+ struct xa_surface *srf[]);
+
+void renderer_bind_destination(struct xa_context *r,
+ struct pipe_surface *surface);
+
+void renderer_init_state(struct xa_context *r);
+void renderer_copy_prepare(struct xa_context *r,
+ struct pipe_surface *dst_surface,
+ struct pipe_resource *src_texture,
+ const enum xa_formats src_xa_format,
+ const enum xa_formats dst_xa_format);
+
+void renderer_copy(struct xa_context *r, int dx,
+ int dy,
+ int sx,
+ int sy,
+ int width, int height, float src_width, float src_height);
+
+void renderer_draw_flush(struct xa_context *r);
+
+void renderer_begin_solid(struct xa_context *r);
+void renderer_solid(struct xa_context *r,
+ int x0, int y0, int x1, int y1);
+void
+renderer_begin_textures(struct xa_context *r);
+
+void
+renderer_texture(struct xa_context *r,
+ int *pos,
+ int width, int height,
+ const float *src_matrix,
+ const float *mask_matrix);
+
+#endif
diff --git a/src/gallium/frontends/xa/xa_renderer.c b/src/gallium/frontends/xa/xa_renderer.c
new file mode 100644
index 00000000000..89548ad7019
--- /dev/null
+++ b/src/gallium/frontends/xa/xa_renderer.c
@@ -0,0 +1,636 @@
+/**********************************************************
+ * Copyright 2009-2011 VMware, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ *********************************************************
+ * Authors:
+ * Zack Rusin <zackr-at-vmware-dot-com>
+ */
+
+#include "xa_context.h"
+#include "xa_priv.h"
+#include <math.h>
+#include "cso_cache/cso_context.h"
+#include "util/u_inlines.h"
+#include "util/u_sampler.h"
+#include "util/u_draw_quad.h"
+
+#define floatsEqual(x, y) (fabsf(x - y) <= 0.00001f * MIN2(fabsf(x), fabsf(y)))
+#define floatIsZero(x) (floatsEqual((x) + 1, 1))
+
+#define NUM_COMPONENTS 4
+
+void
+
+
+renderer_set_constants(struct xa_context *r,
+ int shader_type, const float *params, int param_bytes);
+
+static inline boolean
+is_affine(const float *matrix)
+{
+ return floatIsZero(matrix[2]) && floatIsZero(matrix[5])
+ && floatsEqual(matrix[8], 1);
+}
+
+static inline void
+map_point(const 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 inline void
+renderer_draw(struct xa_context *r)
+{
+ int num_verts = r->buffer_size / (r->attrs_per_vertex * NUM_COMPONENTS);
+
+ if (!r->buffer_size)
+ return;
+
+ if (!r->scissor_valid) {
+ r->scissor.minx = 0;
+ r->scissor.miny = 0;
+ r->scissor.maxx = r->dst->tex->width0;
+ r->scissor.maxy = r->dst->tex->height0;
+ }
+
+ r->pipe->set_scissor_states(r->pipe, 0, 1, &r->scissor);
+
+ struct cso_velems_state velems;
+ velems.count = r->attrs_per_vertex;
+ memcpy(velems.velems, r->velems, sizeof(r->velems[0]) * velems.count);
+
+ cso_set_vertex_elements(r->cso, &velems);
+ util_draw_user_vertex_buffer(r->cso, r->buffer, PIPE_PRIM_QUADS,
+ num_verts, /* verts */
+ r->attrs_per_vertex); /* attribs/vert */
+ r->buffer_size = 0;
+
+ xa_scissor_reset(r);
+}
+
+static inline void
+renderer_draw_conditional(struct xa_context *r, int next_batch)
+{
+ if (r->buffer_size + next_batch >= XA_VB_SIZE ||
+ (next_batch == 0 && r->buffer_size)) {
+ renderer_draw(r);
+ }
+}
+
+void
+renderer_init_state(struct xa_context *r)
+{
+ struct pipe_depth_stencil_alpha_state dsa;
+ struct pipe_rasterizer_state raster;
+ unsigned i;
+
+ /* set common initial clip state */
+ memset(&dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
+ cso_set_depth_stencil_alpha(r->cso, &dsa);
+
+ /* XXX: move to renderer_init_state? */
+ memset(&raster, 0, sizeof(struct pipe_rasterizer_state));
+ raster.half_pixel_center = 1;
+ raster.bottom_edge_rule = 1;
+ raster.depth_clip_near = 1;
+ raster.depth_clip_far = 1;
+ raster.scissor = 1;
+ cso_set_rasterizer(r->cso, &raster);
+
+ /* vertex elements state */
+ memset(&r->velems[0], 0, sizeof(r->velems[0]) * 3);
+ for (i = 0; i < 3; i++) {
+ r->velems[i].src_offset = i * 4 * sizeof(float);
+ r->velems[i].instance_divisor = 0;
+ r->velems[i].vertex_buffer_index = 0;
+ r->velems[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ }
+}
+
+static inline void
+add_vertex_none(struct xa_context *r, float x, float y)
+{
+ float *vertex = r->buffer + r->buffer_size;
+
+ vertex[0] = x;
+ vertex[1] = y;
+ vertex[2] = 0.f; /*z */
+ vertex[3] = 1.f; /*w */
+
+ r->buffer_size += 4;
+}
+
+static inline void
+add_vertex_1tex(struct xa_context *r, float x, float y, float s, float t)
+{
+ float *vertex = r->buffer + r->buffer_size;
+
+ vertex[0] = x;
+ vertex[1] = y;
+ vertex[2] = 0.f; /*z */
+ vertex[3] = 1.f; /*w */
+
+ vertex[4] = s; /*s */
+ vertex[5] = t; /*t */
+ vertex[6] = 0.f; /*r */
+ vertex[7] = 1.f; /*q */
+
+ r->buffer_size += 8;
+}
+
+static inline void
+add_vertex_2tex(struct xa_context *r,
+ float x, float y, float s0, float t0, float s1, float t1)
+{
+ float *vertex = r->buffer + r->buffer_size;
+
+ vertex[0] = x;
+ vertex[1] = y;
+ vertex[2] = 0.f; /*z */
+ vertex[3] = 1.f; /*w */
+
+ vertex[4] = s0; /*s */
+ vertex[5] = t0; /*t */
+ vertex[6] = 0.f; /*r */
+ vertex[7] = 1.f; /*q */
+
+ vertex[8] = s1; /*s */
+ vertex[9] = t1; /*t */
+ vertex[10] = 0.f; /*r */
+ vertex[11] = 1.f; /*q */
+
+ r->buffer_size += 12;
+}
+
+static void
+compute_src_coords(float sx, float sy, const struct pipe_resource *src,
+ const float *src_matrix,
+ float width, float height,
+ float tc0[2], float tc1[2], float tc2[2], float tc3[2])
+{
+ tc0[0] = sx;
+ tc0[1] = sy;
+ tc1[0] = sx + width;
+ tc1[1] = sy;
+ tc2[0] = sx + width;
+ tc2[1] = sy + height;
+ tc3[0] = sx;
+ tc3[1] = sy + height;
+
+ if (src_matrix) {
+ map_point(src_matrix, tc0[0], tc0[1], &tc0[0], &tc0[1]);
+ map_point(src_matrix, tc1[0], tc1[1], &tc1[0], &tc1[1]);
+ map_point(src_matrix, tc2[0], tc2[1], &tc2[0], &tc2[1]);
+ map_point(src_matrix, tc3[0], tc3[1], &tc3[0], &tc3[1]);
+ }
+
+ tc0[0] /= src->width0;
+ tc1[0] /= src->width0;
+ tc2[0] /= src->width0;
+ tc3[0] /= src->width0;
+ tc0[1] /= src->height0;
+ tc1[1] /= src->height0;
+ tc2[1] /= src->height0;
+ tc3[1] /= src->height0;
+}
+
+static void
+add_vertex_data1(struct xa_context *r,
+ float srcX, float srcY, float dstX, float dstY,
+ float width, float height,
+ const struct pipe_resource *src, const float *src_matrix)
+{
+ float tc0[2], tc1[2], tc2[2], tc3[2];
+
+ compute_src_coords(srcX, srcY, src, src_matrix, width, height,
+ tc0, tc1, tc2, tc3);
+ /* 1st vertex */
+ add_vertex_1tex(r, dstX, dstY, tc0[0], tc0[1]);
+ /* 2nd vertex */
+ add_vertex_1tex(r, dstX + width, dstY, tc1[0], tc1[1]);
+ /* 3rd vertex */
+ add_vertex_1tex(r, dstX + width, dstY + height, tc2[0], tc2[1]);
+ /* 4th vertex */
+ add_vertex_1tex(r, dstX, dstY + height, tc3[0], tc3[1]);
+}
+
+static void
+add_vertex_data2(struct xa_context *r,
+ float srcX, float srcY, float maskX, float maskY,
+ float dstX, float dstY, float width, float height,
+ struct pipe_resource *src,
+ struct pipe_resource *mask,
+ const float *src_matrix, const float *mask_matrix)
+{
+ float spt0[2], spt1[2], spt2[2], spt3[2];
+ float mpt0[2], mpt1[2], mpt2[2], mpt3[2];
+
+ compute_src_coords(srcX, srcY, src, src_matrix, width, height,
+ spt0, spt1, spt2, spt3);
+ compute_src_coords(maskX, maskY, mask, mask_matrix, width, height,
+ mpt0, mpt1, mpt2, mpt3);
+
+ /* 1st vertex */
+ add_vertex_2tex(r, dstX, dstY,
+ spt0[0], spt0[1], mpt0[0], mpt0[1]);
+ /* 2nd vertex */
+ add_vertex_2tex(r, dstX + width, dstY,
+ spt1[0], spt1[1], mpt1[0], mpt1[1]);
+ /* 3rd vertex */
+ add_vertex_2tex(r, dstX + width, dstY + height,
+ spt2[0], spt2[1], mpt2[0], mpt2[1]);
+ /* 4th vertex */
+ add_vertex_2tex(r, dstX, dstY + height,
+ spt3[0], spt3[1], mpt3[0], mpt3[1]);
+}
+
+static void
+setup_vertex_data_yuv(struct xa_context *r,
+ float srcX,
+ float srcY,
+ float srcW,
+ float srcH,
+ float dstX,
+ float dstY,
+ float dstW, float dstH, struct xa_surface *srf[])
+{
+ float s0, t0, s1, t1;
+ float spt0[2], spt1[2];
+ struct pipe_resource *tex;
+
+ spt0[0] = srcX;
+ spt0[1] = srcY;
+ spt1[0] = srcX + srcW;
+ spt1[1] = srcY + srcH;
+
+ tex = srf[0]->tex;
+ s0 = spt0[0] / tex->width0;
+ t0 = spt0[1] / tex->height0;
+ s1 = spt1[0] / tex->width0;
+ t1 = spt1[1] / tex->height0;
+
+ /* 1st vertex */
+ add_vertex_1tex(r, dstX, dstY, s0, t0);
+ /* 2nd vertex */
+ add_vertex_1tex(r, dstX + dstW, dstY, s1, t0);
+ /* 3rd vertex */
+ add_vertex_1tex(r, dstX + dstW, dstY + dstH, s1, t1);
+ /* 4th vertex */
+ add_vertex_1tex(r, dstX, dstY + dstH, s0, t1);
+}
+
+/* Set up framebuffer, viewport and vertex shader constant buffer
+ * state for a particular destinaton surface. In all our rendering,
+ * these concepts are linked.
+ */
+void
+renderer_bind_destination(struct xa_context *r,
+ struct pipe_surface *surface)
+{
+ int width = surface->width;
+ int height = surface->height;
+
+ struct pipe_framebuffer_state fb;
+ struct pipe_viewport_state viewport;
+
+ xa_scissor_reset(r);
+
+ /* Framebuffer uses actual surface width/height
+ */
+ memset(&fb, 0, sizeof fb);
+ fb.width = surface->width;
+ fb.height = surface->height;
+ fb.nr_cbufs = 1;
+ fb.cbufs[0] = surface;
+ fb.zsbuf = 0;
+
+ /* Viewport just touches the bit we're interested in:
+ */
+ viewport.scale[0] = width / 2.f;
+ viewport.scale[1] = height / 2.f;
+ viewport.scale[2] = 1.0;
+ viewport.translate[0] = width / 2.f;
+ viewport.translate[1] = height / 2.f;
+ viewport.translate[2] = 0.0;
+
+ /* Constant buffer set up to match viewport dimensions:
+ */
+ if (r->fb_width != width || r->fb_height != height) {
+ float vs_consts[8] = {
+ 2.f / width, 2.f / height, 1, 1,
+ -1, -1, 0, 0
+ };
+
+ r->fb_width = width;
+ r->fb_height = height;
+
+ renderer_set_constants(r, PIPE_SHADER_VERTEX,
+ vs_consts, sizeof vs_consts);
+ }
+
+ cso_set_framebuffer(r->cso, &fb);
+ cso_set_viewport(r->cso, &viewport);
+}
+
+void
+renderer_set_constants(struct xa_context *r,
+ int shader_type, const float *params, int param_bytes)
+{
+ struct pipe_resource **cbuf =
+ (shader_type == PIPE_SHADER_VERTEX) ? &r->vs_const_buffer :
+ &r->fs_const_buffer;
+
+ pipe_resource_reference(cbuf, NULL);
+ *cbuf = pipe_buffer_create_const0(r->pipe->screen,
+ PIPE_BIND_CONSTANT_BUFFER,
+ PIPE_USAGE_DEFAULT,
+ param_bytes);
+
+ if (*cbuf) {
+ pipe_buffer_write(r->pipe, *cbuf, 0, param_bytes, params);
+ }
+ pipe_set_constant_buffer(r->pipe, shader_type, 0, *cbuf);
+}
+
+void
+renderer_copy_prepare(struct xa_context *r,
+ struct pipe_surface *dst_surface,
+ struct pipe_resource *src_texture,
+ const enum xa_formats src_xa_format,
+ const enum xa_formats dst_xa_format)
+{
+ struct pipe_context *pipe = r->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct xa_shader shader;
+ uint32_t fs_traits = FS_COMPOSITE;
+
+ assert(screen->is_format_supported(screen, dst_surface->format,
+ PIPE_TEXTURE_2D, 0, 0,
+ PIPE_BIND_RENDER_TARGET));
+ (void)screen;
+
+ renderer_bind_destination(r, dst_surface);
+
+ /* set misc state we care about */
+ {
+ struct pipe_blend_state blend;
+
+ memset(&blend, 0, sizeof(blend));
+ blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ blend.rt[0].colormask = PIPE_MASK_RGBA;
+ cso_set_blend(r->cso, &blend);
+ }
+
+ /* sampler */
+ {
+ struct pipe_sampler_state sampler;
+ const struct pipe_sampler_state *p_sampler = &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_set_samplers(r->cso, PIPE_SHADER_FRAGMENT, 1, &p_sampler);
+ r->num_bound_samplers = 1;
+ }
+
+ /* texture/sampler view */
+ {
+ struct pipe_sampler_view templ;
+ struct pipe_sampler_view *src_view;
+
+ u_sampler_view_default_template(&templ,
+ src_texture, src_texture->format);
+ src_view = pipe->create_sampler_view(pipe, src_texture, &templ);
+ cso_set_sampler_views(r->cso, PIPE_SHADER_FRAGMENT, 1, &src_view);
+ pipe_sampler_view_reference(&src_view, NULL);
+ }
+
+ /* shaders */
+ if (src_texture->format == PIPE_FORMAT_L8_UNORM ||
+ src_texture->format == PIPE_FORMAT_R8_UNORM)
+ fs_traits |= FS_SRC_LUMINANCE;
+ if (dst_surface->format == PIPE_FORMAT_L8_UNORM ||
+ dst_surface->format == PIPE_FORMAT_R8_UNORM)
+ fs_traits |= FS_DST_LUMINANCE;
+ if (xa_format_a(dst_xa_format) != 0 &&
+ xa_format_a(src_xa_format) == 0)
+ fs_traits |= FS_SRC_SET_ALPHA;
+
+ shader = xa_shaders_get(r->shaders, VS_COMPOSITE, fs_traits);
+ cso_set_vertex_shader_handle(r->cso, shader.vs);
+ cso_set_fragment_shader_handle(r->cso, shader.fs);
+
+ r->buffer_size = 0;
+ r->attrs_per_vertex = 2;
+}
+
+void
+renderer_copy(struct xa_context *r,
+ int dx,
+ int dy,
+ int sx,
+ int sy,
+ int width, int height, float src_width, float src_height)
+{
+ float s0, t0, s1, t1;
+ float x0, y0, x1, y1;
+
+ /* XXX: could put the texcoord scaling calculation into the vertex
+ * shader.
+ */
+ s0 = sx / src_width;
+ s1 = (sx + width) / src_width;
+ t0 = sy / src_height;
+ t1 = (sy + height) / src_height;
+
+ x0 = dx;
+ x1 = dx + width;
+ y0 = dy;
+ y1 = dy + height;
+
+ /* draw quad */
+ renderer_draw_conditional(r, 4 * 8);
+ add_vertex_1tex(r, x0, y0, s0, t0);
+ add_vertex_1tex(r, x1, y0, s1, t0);
+ add_vertex_1tex(r, x1, y1, s1, t1);
+ add_vertex_1tex(r, x0, y1, s0, t1);
+}
+
+void
+renderer_draw_yuv(struct xa_context *r,
+ float src_x,
+ float src_y,
+ float src_w,
+ float src_h,
+ int dst_x,
+ int dst_y, int dst_w, int dst_h, struct xa_surface *srf[])
+{
+ const int num_attribs = 2; /*pos + tex coord */
+
+ setup_vertex_data_yuv(r,
+ src_x, src_y, src_w, src_h,
+ dst_x, dst_y, dst_w, dst_h, srf);
+
+ if (!r->scissor_valid) {
+ r->scissor.minx = 0;
+ r->scissor.miny = 0;
+ r->scissor.maxx = r->dst->tex->width0;
+ r->scissor.maxy = r->dst->tex->height0;
+ }
+
+ r->pipe->set_scissor_states(r->pipe, 0, 1, &r->scissor);
+
+ struct cso_velems_state velems;
+ velems.count = num_attribs;
+ memcpy(velems.velems, r->velems, sizeof(r->velems[0]) * velems.count);
+
+ cso_set_vertex_elements(r->cso, &velems);
+ util_draw_user_vertex_buffer(r->cso, r->buffer, PIPE_PRIM_QUADS,
+ 4, /* verts */
+ num_attribs); /* attribs/vert */
+ r->buffer_size = 0;
+
+ xa_scissor_reset(r);
+}
+
+void
+renderer_begin_solid(struct xa_context *r)
+{
+ r->buffer_size = 0;
+ r->attrs_per_vertex = 1;
+ renderer_set_constants(r, PIPE_SHADER_FRAGMENT, r->solid_color,
+ 4 * sizeof(float));
+}
+
+void
+renderer_solid(struct xa_context *r,
+ int x0, int y0, int x1, int y1)
+{
+ /*
+ * debug_printf("solid rect[(%d, %d), (%d, %d)], rgba[%f, %f, %f, %f]\n",
+ * x0, y0, x1, y1, color[0], color[1], color[2], color[3]); */
+
+ renderer_draw_conditional(r, 4 * 4);
+
+ /* 1st vertex */
+ add_vertex_none(r, x0, y0);
+ /* 2nd vertex */
+ add_vertex_none(r, x1, y0);
+ /* 3rd vertex */
+ add_vertex_none(r, x1, y1);
+ /* 4th vertex */
+ add_vertex_none(r, x0, y1);
+}
+
+void
+renderer_draw_flush(struct xa_context *r)
+{
+ renderer_draw_conditional(r, 0);
+}
+
+void
+renderer_begin_textures(struct xa_context *r)
+{
+ r->attrs_per_vertex = 1 + r->num_bound_samplers;
+ r->buffer_size = 0;
+ if (r->has_solid_src || r->has_solid_mask)
+ renderer_set_constants(r, PIPE_SHADER_FRAGMENT, r->solid_color,
+ 4 * sizeof(float));
+}
+
+void
+renderer_texture(struct xa_context *r,
+ int *pos,
+ int width, int height,
+ const float *src_matrix,
+ const float *mask_matrix)
+{
+ struct pipe_sampler_view **sampler_view = r->bound_sampler_views;
+
+#if 0
+ if (src_matrix) {
+ debug_printf("src_matrix = \n");
+ debug_printf("%f, %f, %f\n", src_matrix[0], src_matrix[1], src_matrix[2]);
+ debug_printf("%f, %f, %f\n", src_matrix[3], src_matrix[4], src_matrix[5]);
+ debug_printf("%f, %f, %f\n", src_matrix[6], src_matrix[7], src_matrix[8]);
+ }
+ if (mask_matrix) {
+ debug_printf("mask_matrix = \n");
+ debug_printf("%f, %f, %f\n", mask_matrix[0], mask_matrix[1], mask_matrix[2]);
+ debug_printf("%f, %f, %f\n", mask_matrix[3], mask_matrix[4], mask_matrix[5]);
+ debug_printf("%f, %f, %f\n", mask_matrix[6], mask_matrix[7], mask_matrix[8]);
+ }
+#endif
+
+ switch(r->attrs_per_vertex) {
+ case 2:
+ renderer_draw_conditional(r, 4 * 8);
+ if (!r->has_solid_src) {
+ add_vertex_data1(r,
+ pos[0], pos[1], /* src */
+ pos[4], pos[5], /* dst */
+ width, height,
+ sampler_view[0]->texture, src_matrix);
+ } else {
+ add_vertex_data1(r,
+ pos[2], pos[3], /* mask */
+ pos[4], pos[5], /* dst */
+ width, height,
+ sampler_view[0]->texture, mask_matrix);
+ }
+ break;
+ case 3:
+ renderer_draw_conditional(r, 4 * 12);
+ add_vertex_data2(r,
+ pos[0], pos[1], /* src */
+ pos[2], pos[3], /* mask */
+ pos[4], pos[5], /* dst */
+ width, height,
+ sampler_view[0]->texture, sampler_view[1]->texture,
+ src_matrix, mask_matrix);
+ break;
+ default:
+ break;
+ }
+}
diff --git a/src/gallium/frontends/xa/xa_tgsi.c b/src/gallium/frontends/xa/xa_tgsi.c
new file mode 100644
index 00000000000..83f6db128c3
--- /dev/null
+++ b/src/gallium/frontends/xa/xa_tgsi.c
@@ -0,0 +1,500 @@
+/**********************************************************
+ * Copyright 2009-2011 VMware, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ *********************************************************
+ * Authors:
+ * Zack Rusin <zackr-at-vmware-dot-com>
+ */
+#include "xa_priv.h"
+
+#include "pipe/p_format.h"
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+#include "pipe/p_shader_tokens.h"
+
+#include "util/u_memory.h"
+
+#include "tgsi/tgsi_ureg.h"
+
+#include "cso_cache/cso_context.h"
+#include "cso_cache/cso_hash.h"
+
+/* Vertex shader:
+ * IN[0] = vertex pos
+ * IN[1] = src tex coord | solid fill color
+ * IN[2] = mask tex coord
+ * IN[3] = dst tex coord
+ * CONST[0] = (2/dst_width, 2/dst_height, 1, 1)
+ * CONST[1] = (-1, -1, 0, 0)
+ *
+ * OUT[0] = vertex pos
+ * OUT[1] = src tex coord
+ * OUT[2] = mask tex coord
+ * OUT[3] = dst tex coord
+ */
+
+/* Fragment shader. Samplers are allocated when needed.
+ * SAMP[0] = sampler for first texture (src or mask if src is solid)
+ * SAMP[1] = sampler for second texture (mask or none)
+ * IN[0] = first texture coordinates if present
+ * IN[1] = second texture coordinates if present
+ * CONST[0] = Solid color (src if src solid or mask if mask solid
+ * or src in mask if both solid).
+ *
+ * OUT[0] = color
+ */
+
+static void
+print_fs_traits(int fs_traits)
+{
+ const char *strings[] = {
+ "FS_COMPOSITE", /* = 1 << 0, */
+ "FS_MASK", /* = 1 << 1, */
+ "FS_SRC_SRC", /* = 1 << 2, */
+ "FS_MASK_SRC", /* = 1 << 3, */
+ "FS_YUV", /* = 1 << 4, */
+ "FS_SRC_REPEAT_NONE", /* = 1 << 5, */
+ "FS_MASK_REPEAT_NONE", /* = 1 << 6, */
+ "FS_SRC_SWIZZLE_RGB", /* = 1 << 7, */
+ "FS_MASK_SWIZZLE_RGB", /* = 1 << 8, */
+ "FS_SRC_SET_ALPHA", /* = 1 << 9, */
+ "FS_MASK_SET_ALPHA", /* = 1 << 10, */
+ "FS_SRC_LUMINANCE", /* = 1 << 11, */
+ "FS_MASK_LUMINANCE", /* = 1 << 12, */
+ "FS_DST_LUMINANCE", /* = 1 << 13, */
+ "FS_CA", /* = 1 << 14, */
+ };
+ int i, k;
+
+ debug_printf("%s: ", __func__);
+
+ for (i = 0, k = 1; k < (1 << 16); i++, k <<= 1) {
+ if (fs_traits & k)
+ debug_printf("%s, ", strings[i]);
+ }
+
+ debug_printf("\n");
+}
+
+struct xa_shaders {
+ struct xa_context *r;
+
+ struct cso_hash vs_hash;
+ struct cso_hash fs_hash;
+};
+
+static inline void
+src_in_mask(struct ureg_program *ureg,
+ struct ureg_dst dst,
+ struct ureg_src src,
+ struct ureg_src mask,
+ unsigned mask_luminance, boolean component_alpha)
+{
+ if (mask_luminance)
+ if (component_alpha) {
+ ureg_MOV(ureg, dst, src);
+ ureg_MUL(ureg, ureg_writemask(dst, TGSI_WRITEMASK_W),
+ src, ureg_scalar(mask, TGSI_SWIZZLE_X));
+ } else {
+ ureg_MUL(ureg, dst, src, ureg_scalar(mask, TGSI_SWIZZLE_X));
+ }
+ else if (!component_alpha)
+ ureg_MUL(ureg, dst, src, ureg_scalar(mask, TGSI_SWIZZLE_W));
+ else
+ ureg_MUL(ureg, dst, src, mask);
+}
+
+static struct ureg_src
+vs_normalize_coords(struct ureg_program *ureg,
+ struct ureg_src coords,
+ struct ureg_src const0, struct ureg_src const1)
+{
+ struct ureg_dst tmp = ureg_DECL_temporary(ureg);
+ struct ureg_src ret;
+
+ ureg_MAD(ureg, tmp, coords, const0, const1);
+ ret = ureg_src(tmp);
+ ureg_release_temporary(ureg, tmp);
+ return ret;
+}
+
+static void *
+create_vs(struct pipe_context *pipe, unsigned vs_traits)
+{
+ struct ureg_program *ureg;
+ struct ureg_src src;
+ struct ureg_dst dst;
+ struct ureg_src const0, const1;
+ boolean is_composite = (vs_traits & VS_COMPOSITE) != 0;
+ boolean has_mask = (vs_traits & VS_MASK) != 0;
+ boolean is_yuv = (vs_traits & VS_YUV) != 0;
+ boolean is_src_src = (vs_traits & VS_SRC_SRC) != 0;
+ boolean is_mask_src = (vs_traits & VS_MASK_SRC) != 0;
+ unsigned input_slot = 0;
+
+ ureg = ureg_create(PIPE_SHADER_VERTEX);
+ if (ureg == NULL)
+ return 0;
+
+ const0 = ureg_DECL_constant(ureg, 0);
+ const1 = ureg_DECL_constant(ureg, 1);
+
+ /* it has to be either a fill or a composite op */
+ src = ureg_DECL_vs_input(ureg, input_slot++);
+ dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);
+ src = vs_normalize_coords(ureg, src, const0, const1);
+ ureg_MOV(ureg, dst, src);
+
+ if (is_yuv) {
+ src = ureg_DECL_vs_input(ureg, input_slot++);
+ dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 0);
+ ureg_MOV(ureg, dst, src);
+ }
+
+ if (is_composite) {
+ if (!is_src_src || (has_mask && !is_mask_src)) {
+ src = ureg_DECL_vs_input(ureg, input_slot++);
+ dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 0);
+ ureg_MOV(ureg, dst, src);
+ }
+
+ if (!is_src_src && (has_mask && !is_mask_src)) {
+ src = ureg_DECL_vs_input(ureg, input_slot++);
+ dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 1);
+ ureg_MOV(ureg, dst, src);
+ }
+ }
+
+ ureg_END(ureg);
+
+ return ureg_create_shader_and_destroy(ureg, pipe);
+}
+
+static void *
+create_yuv_shader(struct pipe_context *pipe, struct ureg_program *ureg)
+{
+ struct ureg_src y_sampler, u_sampler, v_sampler;
+ struct ureg_src pos;
+ struct ureg_src matrow0, matrow1, matrow2, matrow3;
+ struct ureg_dst y, u, v, rgb;
+ struct ureg_dst out = ureg_DECL_output(ureg,
+ TGSI_SEMANTIC_COLOR,
+ 0);
+
+ pos = ureg_DECL_fs_input(ureg,
+ TGSI_SEMANTIC_GENERIC, 0,
+ TGSI_INTERPOLATE_PERSPECTIVE);
+
+ rgb = ureg_DECL_temporary(ureg);
+ y = ureg_DECL_temporary(ureg);
+ u = ureg_DECL_temporary(ureg);
+ v = ureg_DECL_temporary(ureg);
+
+ y_sampler = ureg_DECL_sampler(ureg, 0);
+ u_sampler = ureg_DECL_sampler(ureg, 1);
+ v_sampler = ureg_DECL_sampler(ureg, 2);
+
+ ureg_DECL_sampler_view(ureg, 0, TGSI_TEXTURE_2D,
+ TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT,
+ TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT);
+ ureg_DECL_sampler_view(ureg, 1, TGSI_TEXTURE_2D,
+ TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT,
+ TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT);
+ ureg_DECL_sampler_view(ureg, 2, TGSI_TEXTURE_2D,
+ TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT,
+ TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT);
+
+ matrow0 = ureg_DECL_constant(ureg, 0);
+ matrow1 = ureg_DECL_constant(ureg, 1);
+ matrow2 = ureg_DECL_constant(ureg, 2);
+ matrow3 = ureg_DECL_constant(ureg, 3);
+
+ ureg_TEX(ureg, y, TGSI_TEXTURE_2D, pos, y_sampler);
+ ureg_TEX(ureg, u, TGSI_TEXTURE_2D, pos, u_sampler);
+ ureg_TEX(ureg, v, TGSI_TEXTURE_2D, pos, v_sampler);
+
+ ureg_MOV(ureg, rgb, matrow3);
+ ureg_MAD(ureg, rgb,
+ ureg_scalar(ureg_src(y), TGSI_SWIZZLE_X), matrow0, ureg_src(rgb));
+ ureg_MAD(ureg, rgb,
+ ureg_scalar(ureg_src(u), TGSI_SWIZZLE_X), matrow1, ureg_src(rgb));
+ ureg_MAD(ureg, rgb,
+ ureg_scalar(ureg_src(v), TGSI_SWIZZLE_X), matrow2, ureg_src(rgb));
+
+ ureg_MOV(ureg, out, ureg_src(rgb));
+
+ ureg_release_temporary(ureg, rgb);
+ ureg_release_temporary(ureg, y);
+ ureg_release_temporary(ureg, u);
+ ureg_release_temporary(ureg, v);
+
+ ureg_END(ureg);
+
+ return ureg_create_shader_and_destroy(ureg, pipe);
+}
+
+static inline void
+xrender_tex(struct ureg_program *ureg,
+ struct ureg_dst dst,
+ struct ureg_src coords,
+ struct ureg_src sampler,
+ const struct ureg_src *imm0,
+ boolean repeat_none, boolean swizzle, boolean set_alpha)
+{
+ if (repeat_none) {
+ struct ureg_dst tmp0 = ureg_DECL_temporary(ureg);
+ struct ureg_dst tmp1 = ureg_DECL_temporary(ureg);
+
+ ureg_SGT(ureg, tmp1, ureg_swizzle(coords,
+ TGSI_SWIZZLE_X,
+ TGSI_SWIZZLE_Y,
+ TGSI_SWIZZLE_X,
+ TGSI_SWIZZLE_Y), ureg_scalar(*imm0,
+ TGSI_SWIZZLE_X));
+ ureg_SLT(ureg, tmp0,
+ ureg_swizzle(coords, TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y,
+ TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y), ureg_scalar(*imm0,
+ TGSI_SWIZZLE_W));
+ ureg_MIN(ureg, tmp0, ureg_src(tmp0), ureg_src(tmp1));
+ ureg_MIN(ureg, tmp0, ureg_scalar(ureg_src(tmp0), TGSI_SWIZZLE_X),
+ ureg_scalar(ureg_src(tmp0), TGSI_SWIZZLE_Y));
+ ureg_TEX(ureg, tmp1, TGSI_TEXTURE_2D, coords, sampler);
+ if (swizzle)
+ ureg_MOV(ureg, tmp1, ureg_swizzle(ureg_src(tmp1),
+ TGSI_SWIZZLE_Z,
+ TGSI_SWIZZLE_Y, TGSI_SWIZZLE_X,
+ TGSI_SWIZZLE_W));
+ if (set_alpha)
+ ureg_MOV(ureg,
+ ureg_writemask(tmp1, TGSI_WRITEMASK_W),
+ ureg_scalar(*imm0, TGSI_SWIZZLE_W));
+ ureg_MUL(ureg, dst, ureg_src(tmp1), ureg_src(tmp0));
+ ureg_release_temporary(ureg, tmp0);
+ ureg_release_temporary(ureg, tmp1);
+ } else {
+ if (swizzle) {
+ struct ureg_dst tmp = ureg_DECL_temporary(ureg);
+
+ ureg_TEX(ureg, tmp, TGSI_TEXTURE_2D, coords, sampler);
+ ureg_MOV(ureg, dst, ureg_swizzle(ureg_src(tmp),
+ TGSI_SWIZZLE_Z,
+ TGSI_SWIZZLE_Y, TGSI_SWIZZLE_X,
+ TGSI_SWIZZLE_W));
+ ureg_release_temporary(ureg, tmp);
+ } else {
+ ureg_TEX(ureg, dst, TGSI_TEXTURE_2D, coords, sampler);
+ }
+ if (set_alpha)
+ ureg_MOV(ureg,
+ ureg_writemask(dst, TGSI_WRITEMASK_W),
+ ureg_scalar(*imm0, TGSI_SWIZZLE_W));
+ }
+}
+
+static void
+read_input(struct ureg_program *ureg,
+ struct ureg_dst dst,
+ const struct ureg_src *imm0,
+ boolean repeat_none, boolean swizzle, boolean set_alpha,
+ boolean is_src, unsigned *cur_constant, unsigned *cur_sampler)
+{
+ struct ureg_src input, sampler;
+
+ if (is_src) {
+ input = ureg_DECL_constant(ureg, (*cur_constant)++);
+ ureg_MOV(ureg, dst, input);
+ } else {
+ sampler = ureg_DECL_sampler(ureg, *cur_sampler);
+ ureg_DECL_sampler_view(ureg, *cur_sampler, TGSI_TEXTURE_2D,
+ TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT,
+ TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT);
+ input = ureg_DECL_fs_input(ureg,
+ TGSI_SEMANTIC_GENERIC, (*cur_sampler)++,
+ TGSI_INTERPOLATE_PERSPECTIVE);
+ xrender_tex(ureg, dst, input, sampler, imm0,
+ repeat_none, swizzle, set_alpha);
+ }
+}
+
+static void *
+create_fs(struct pipe_context *pipe, unsigned fs_traits)
+{
+ struct ureg_program *ureg;
+ struct ureg_dst src, mask;
+ struct ureg_dst out;
+ struct ureg_src imm0 = { 0 };
+ unsigned has_mask = (fs_traits & FS_MASK) != 0;
+ unsigned is_yuv = (fs_traits & FS_YUV) != 0;
+ unsigned src_repeat_none = (fs_traits & FS_SRC_REPEAT_NONE) != 0;
+ unsigned mask_repeat_none = (fs_traits & FS_MASK_REPEAT_NONE) != 0;
+ unsigned src_swizzle = (fs_traits & FS_SRC_SWIZZLE_RGB) != 0;
+ unsigned mask_swizzle = (fs_traits & FS_MASK_SWIZZLE_RGB) != 0;
+ unsigned src_set_alpha = (fs_traits & FS_SRC_SET_ALPHA) != 0;
+ unsigned mask_set_alpha = (fs_traits & FS_MASK_SET_ALPHA) != 0;
+ unsigned src_luminance = (fs_traits & FS_SRC_LUMINANCE) != 0;
+ unsigned mask_luminance = (fs_traits & FS_MASK_LUMINANCE) != 0;
+ unsigned dst_luminance = (fs_traits & FS_DST_LUMINANCE) != 0;
+ unsigned is_src_src = (fs_traits & FS_SRC_SRC) != 0;
+ unsigned is_mask_src = (fs_traits & FS_MASK_SRC) != 0;
+ boolean component_alpha = (fs_traits & FS_CA) != 0;
+ unsigned cur_sampler = 0;
+ unsigned cur_constant = 0;
+
+#if 0
+ print_fs_traits(fs_traits);
+#else
+ (void)print_fs_traits;
+#endif
+
+ ureg = ureg_create(PIPE_SHADER_FRAGMENT);
+ if (ureg == NULL)
+ return 0;
+
+ if (is_yuv)
+ return create_yuv_shader(pipe, ureg);
+
+ out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
+
+ if (src_repeat_none || mask_repeat_none ||
+ src_set_alpha || mask_set_alpha || src_luminance) {
+ imm0 = ureg_imm4f(ureg, 0, 0, 0, 1);
+ }
+
+ src = (has_mask || src_luminance || dst_luminance) ?
+ ureg_DECL_temporary(ureg) : out;
+
+ read_input(ureg, src, &imm0, src_repeat_none, src_swizzle,
+ src_set_alpha, is_src_src, &cur_constant, &cur_sampler);
+
+ if (src_luminance) {
+ ureg_MOV(ureg, src, ureg_scalar(ureg_src(src), TGSI_SWIZZLE_X));
+ ureg_MOV(ureg, ureg_writemask(src, TGSI_WRITEMASK_XYZ),
+ ureg_scalar(imm0, TGSI_SWIZZLE_X));
+ if (!has_mask && !dst_luminance)
+ ureg_MOV(ureg, out, ureg_src(src));
+ }
+
+ if (has_mask) {
+ mask = ureg_DECL_temporary(ureg);
+ read_input(ureg, mask, &imm0, mask_repeat_none,
+ mask_swizzle, mask_set_alpha, is_mask_src, &cur_constant,
+ &cur_sampler);
+
+ src_in_mask(ureg, (dst_luminance) ? src : out, ureg_src(src),
+ ureg_src(mask), mask_luminance, component_alpha);
+
+ ureg_release_temporary(ureg, mask);
+ }
+
+ if (dst_luminance) {
+ /*
+ * Make sure the alpha channel goes into the output L8 surface.
+ */
+ ureg_MOV(ureg, out, ureg_scalar(ureg_src(src), TGSI_SWIZZLE_W));
+ }
+
+ ureg_END(ureg);
+
+ return ureg_create_shader_and_destroy(ureg, pipe);
+}
+
+struct xa_shaders *
+xa_shaders_create(struct xa_context *r)
+{
+ struct xa_shaders *sc = CALLOC_STRUCT(xa_shaders);
+
+ sc->r = r;
+ cso_hash_init(&sc->vs_hash);
+ cso_hash_init(&sc->fs_hash);
+
+ return sc;
+}
+
+static void
+cache_destroy(struct pipe_context *pipe,
+ struct cso_hash *hash, unsigned processor)
+{
+ struct cso_hash_iter iter = cso_hash_first_node(hash);
+
+ while (!cso_hash_iter_is_null(iter)) {
+ void *shader = (void *)cso_hash_iter_data(iter);
+
+ if (processor == PIPE_SHADER_FRAGMENT) {
+ pipe->delete_fs_state(pipe, shader);
+ } else if (processor == PIPE_SHADER_VERTEX) {
+ pipe->delete_vs_state(pipe, shader);
+ }
+ iter = cso_hash_erase(hash, iter);
+ }
+ cso_hash_deinit(hash);
+}
+
+void
+xa_shaders_destroy(struct xa_shaders *sc)
+{
+ cache_destroy(sc->r->pipe, &sc->vs_hash, PIPE_SHADER_VERTEX);
+ cache_destroy(sc->r->pipe, &sc->fs_hash, PIPE_SHADER_FRAGMENT);
+
+ FREE(sc);
+}
+
+static inline void *
+shader_from_cache(struct pipe_context *pipe,
+ unsigned type, struct cso_hash *hash, unsigned key)
+{
+ void *shader = 0;
+
+ struct cso_hash_iter iter = cso_hash_find(hash, key);
+
+ if (cso_hash_iter_is_null(iter)) {
+ if (type == PIPE_SHADER_VERTEX)
+ shader = create_vs(pipe, key);
+ else
+ shader = create_fs(pipe, key);
+ cso_hash_insert(hash, key, shader);
+ } else
+ shader = (void *)cso_hash_iter_data(iter);
+
+ return shader;
+}
+
+struct xa_shader
+xa_shaders_get(struct xa_shaders *sc, unsigned vs_traits, unsigned fs_traits)
+{
+ struct xa_shader shader = { NULL, NULL };
+ void *vs, *fs;
+
+ vs = shader_from_cache(sc->r->pipe, PIPE_SHADER_VERTEX,
+ &sc->vs_hash, vs_traits);
+ fs = shader_from_cache(sc->r->pipe, PIPE_SHADER_FRAGMENT,
+ &sc->fs_hash, fs_traits);
+
+ debug_assert(vs && fs);
+ if (!vs || !fs)
+ return shader;
+
+ shader.vs = vs;
+ shader.fs = fs;
+
+ return shader;
+}
diff --git a/src/gallium/frontends/xa/xa_tracker.c b/src/gallium/frontends/xa/xa_tracker.c
new file mode 100644
index 00000000000..31162606375
--- /dev/null
+++ b/src/gallium/frontends/xa/xa_tracker.c
@@ -0,0 +1,578 @@
+/**********************************************************
+ * Copyright 2009-2011 VMware, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ *********************************************************
+ * Authors:
+ * Thomas Hellstrom <thellstrom-at-vmware-dot-com>
+ */
+
+#include <unistd.h>
+#include "xa_tracker.h"
+#include "xa_priv.h"
+#include "pipe/p_state.h"
+#include "pipe/p_format.h"
+#include "pipe-loader/pipe_loader.h"
+#include "frontend/drm_driver.h"
+#include "util/u_inlines.h"
+
+/*
+ * format_map [xa_surface_type][first..last in list].
+ * Needs to be updated when enum xa_formats is updated.
+ */
+
+static const enum xa_formats preferred_a[] = { xa_format_a8 };
+
+static const enum xa_formats preferred_argb[] =
+ { xa_format_a8r8g8b8, xa_format_x8r8g8b8, xa_format_r5g6b5,
+ xa_format_x1r5g5b5
+};
+static const enum xa_formats preferred_z[] =
+ { xa_format_z32, xa_format_z24, xa_format_z16 };
+static const enum xa_formats preferred_sz[] =
+ { xa_format_x8z24, xa_format_s8z24 };
+static const enum xa_formats preferred_zs[] =
+ { xa_format_z24x8, xa_format_z24s8 };
+static const enum xa_formats preferred_yuv[] = { xa_format_yuv8 };
+
+static const enum xa_formats *preferred[] =
+ { NULL, preferred_a, preferred_argb, NULL, NULL,
+ preferred_z, preferred_zs, preferred_sz, preferred_yuv
+};
+
+static const unsigned int num_preferred[] = { 0,
+ sizeof(preferred_a) / sizeof(enum xa_formats),
+ sizeof(preferred_argb) / sizeof(enum xa_formats),
+ 0,
+ 0,
+ sizeof(preferred_z) / sizeof(enum xa_formats),
+ sizeof(preferred_zs) / sizeof(enum xa_formats),
+ sizeof(preferred_sz) / sizeof(enum xa_formats),
+ sizeof(preferred_yuv) / sizeof(enum xa_formats)
+};
+
+static const unsigned int stype_bind[XA_LAST_SURFACE_TYPE] = { 0,
+ PIPE_BIND_SAMPLER_VIEW,
+ PIPE_BIND_SAMPLER_VIEW,
+ PIPE_BIND_SAMPLER_VIEW,
+ PIPE_BIND_SAMPLER_VIEW,
+ PIPE_BIND_DEPTH_STENCIL,
+ PIPE_BIND_DEPTH_STENCIL,
+ PIPE_BIND_DEPTH_STENCIL,
+ PIPE_BIND_SAMPLER_VIEW
+};
+
+static struct xa_format_descriptor
+xa_get_pipe_format(struct xa_tracker *xa, enum xa_formats xa_format)
+{
+ struct xa_format_descriptor fdesc;
+
+ fdesc.xa_format = xa_format;
+
+ switch (xa_format) {
+ case xa_format_a8:
+ if (xa->screen->is_format_supported(xa->screen, PIPE_FORMAT_R8_UNORM,
+ PIPE_TEXTURE_2D, 0, 0,
+ stype_bind[xa_type_a] |
+ PIPE_BIND_RENDER_TARGET))
+ fdesc.format = PIPE_FORMAT_R8_UNORM;
+ else
+ fdesc.format = PIPE_FORMAT_L8_UNORM;
+ break;
+ case xa_format_a8r8g8b8:
+ fdesc.format = PIPE_FORMAT_B8G8R8A8_UNORM;
+ break;
+ case xa_format_x8r8g8b8:
+ fdesc.format = PIPE_FORMAT_B8G8R8X8_UNORM;
+ break;
+ case xa_format_r5g6b5:
+ fdesc.format = PIPE_FORMAT_B5G6R5_UNORM;
+ break;
+ case xa_format_x1r5g5b5:
+ fdesc.format = PIPE_FORMAT_B5G5R5A1_UNORM;
+ break;
+ case xa_format_a4r4g4b4:
+ fdesc.format = PIPE_FORMAT_B4G4R4A4_UNORM;
+ break;
+ case xa_format_a2b10g10r10:
+ fdesc.format = PIPE_FORMAT_R10G10B10A2_UNORM;
+ break;
+ case xa_format_x2b10g10r10:
+ fdesc.format = PIPE_FORMAT_R10G10B10X2_UNORM;
+ break;
+ case xa_format_b8g8r8a8:
+ fdesc.format = PIPE_FORMAT_A8R8G8B8_UNORM;
+ break;
+ case xa_format_b8g8r8x8:
+ fdesc.format = PIPE_FORMAT_X8R8G8B8_UNORM;
+ break;
+ case xa_format_z24:
+ fdesc.format = PIPE_FORMAT_Z24X8_UNORM;
+ break;
+ case xa_format_z16:
+ fdesc.format = PIPE_FORMAT_Z16_UNORM;
+ break;
+ case xa_format_z32:
+ fdesc.format = PIPE_FORMAT_Z32_UNORM;
+ break;
+ case xa_format_x8z24:
+ fdesc.format = PIPE_FORMAT_Z24X8_UNORM;
+ break;
+ case xa_format_z24x8:
+ fdesc.format = PIPE_FORMAT_X8Z24_UNORM;
+ break;
+ case xa_format_s8z24:
+ fdesc.format = PIPE_FORMAT_Z24_UNORM_S8_UINT;
+ break;
+ case xa_format_z24s8:
+ fdesc.format = PIPE_FORMAT_S8_UINT_Z24_UNORM;
+ break;
+ case xa_format_yuv8:
+ if (xa->screen->is_format_supported(xa->screen, PIPE_FORMAT_R8_UNORM,
+ PIPE_TEXTURE_2D, 0, 0,
+ stype_bind[xa_type_yuv_component]))
+ fdesc.format = PIPE_FORMAT_R8_UNORM;
+ else
+ fdesc.format = PIPE_FORMAT_L8_UNORM;
+ break;
+ default:
+ fdesc.xa_format = xa_format_unknown;
+ break;
+ }
+ return fdesc;
+}
+
+XA_EXPORT struct xa_tracker *
+xa_tracker_create(int drm_fd)
+{
+ struct xa_tracker *xa = calloc(1, sizeof(struct xa_tracker));
+ enum xa_surface_type stype;
+ unsigned int num_formats;
+
+ if (!xa)
+ return NULL;
+
+ if (pipe_loader_drm_probe_fd(&xa->dev, drm_fd))
+ xa->screen = pipe_loader_create_screen(xa->dev);
+
+ if (!xa->screen)
+ goto out_no_screen;
+
+ xa->default_ctx = xa_context_create(xa);
+ if (!xa->default_ctx)
+ goto out_no_pipe;
+
+ num_formats = 0;
+ for (stype = 0; stype < XA_LAST_SURFACE_TYPE; ++stype)
+ num_formats += num_preferred[stype];
+
+ num_formats += 1;
+ xa->supported_formats = calloc(num_formats, sizeof(*xa->supported_formats));
+ if (!xa->supported_formats)
+ goto out_sf_alloc_fail;
+
+ xa->supported_formats[0] = xa_format_unknown;
+ num_formats = 1;
+ memset(xa->format_map, 0, sizeof(xa->format_map));
+
+ for (stype = 0; stype < XA_LAST_SURFACE_TYPE; ++stype) {
+ unsigned int bind = stype_bind[stype];
+ enum xa_formats xa_format;
+ int i;
+
+ for (i = 0; i < num_preferred[stype]; ++i) {
+ xa_format = preferred[stype][i];
+
+ struct xa_format_descriptor fdesc =
+ xa_get_pipe_format(xa, xa_format);
+
+ if (xa->screen->is_format_supported(xa->screen, fdesc.format,
+ PIPE_TEXTURE_2D, 0, 0, bind)) {
+ if (xa->format_map[stype][0] == 0)
+ xa->format_map[stype][0] = num_formats;
+ xa->format_map[stype][1] = num_formats;
+ xa->supported_formats[num_formats++] = xa_format;
+ }
+ }
+ }
+ return xa;
+
+ out_sf_alloc_fail:
+ xa_context_destroy(xa->default_ctx);
+ out_no_pipe:
+ xa->screen->destroy(xa->screen);
+ out_no_screen:
+ if (xa->dev)
+ pipe_loader_release(&xa->dev, 1);
+
+ free(xa);
+ return NULL;
+}
+
+XA_EXPORT void
+xa_tracker_destroy(struct xa_tracker *xa)
+{
+ free(xa->supported_formats);
+ xa_context_destroy(xa->default_ctx);
+ xa->screen->destroy(xa->screen);
+ pipe_loader_release(&xa->dev, 1);
+ /* CHECK: The XA API user preserves ownership of the original fd */
+ free(xa);
+}
+
+static int
+xa_flags_compat(unsigned int old_flags, unsigned int new_flags)
+{
+ unsigned int flag_diff = (old_flags ^ new_flags);
+
+ if (flag_diff == 0)
+ return 1;
+
+ if (flag_diff & XA_FLAG_SHARED)
+ return 0;
+ /*
+ * Don't recreate if we're dropping the render target flag.
+ */
+ if (flag_diff & XA_FLAG_RENDER_TARGET)
+ return ((new_flags & XA_FLAG_RENDER_TARGET) == 0);
+
+ /*
+ * Don't recreate if we're dropping the scanout flag.
+ */
+ if (flag_diff & XA_FLAG_SCANOUT)
+ return ((new_flags & XA_FLAG_SCANOUT) == 0);
+
+ /*
+ * Always recreate for unknown / unimplemented flags.
+ */
+ return 0;
+}
+
+static struct xa_format_descriptor
+xa_get_format_stype_depth(struct xa_tracker *xa,
+ enum xa_surface_type stype, unsigned int depth)
+{
+ unsigned int i;
+ struct xa_format_descriptor fdesc;
+ int found = 0;
+
+ for (i = xa->format_map[stype][0]; i <= xa->format_map[stype][1]; ++i) {
+ fdesc = xa_get_pipe_format(xa, xa->supported_formats[i]);
+ if (fdesc.xa_format != xa_format_unknown &&
+ xa_format_depth(fdesc.xa_format) == depth) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found)
+ fdesc.xa_format = xa_format_unknown;
+
+ return fdesc;
+}
+
+XA_EXPORT int
+xa_format_check_supported(struct xa_tracker *xa,
+ enum xa_formats xa_format, unsigned int flags)
+{
+ struct xa_format_descriptor fdesc = xa_get_pipe_format(xa, xa_format);
+ unsigned int bind;
+
+ if (fdesc.xa_format == xa_format_unknown)
+ return -XA_ERR_INVAL;
+
+ bind = stype_bind[xa_format_type(fdesc.xa_format)];
+ if (flags & XA_FLAG_SHARED)
+ bind |= PIPE_BIND_SHARED;
+ if (flags & XA_FLAG_RENDER_TARGET)
+ bind |= PIPE_BIND_RENDER_TARGET;
+ if (flags & XA_FLAG_SCANOUT)
+ bind |= PIPE_BIND_SCANOUT;
+
+ if (!xa->screen->is_format_supported(xa->screen, fdesc.format,
+ PIPE_TEXTURE_2D, 0, 0, bind))
+ return -XA_ERR_INVAL;
+
+ return XA_ERR_NONE;
+}
+
+static unsigned
+handle_type(enum xa_handle_type type)
+{
+ switch (type) {
+ case xa_handle_type_kms:
+ return WINSYS_HANDLE_TYPE_KMS;
+ case xa_handle_type_fd:
+ return WINSYS_HANDLE_TYPE_FD;
+ case xa_handle_type_shared:
+ default:
+ return WINSYS_HANDLE_TYPE_SHARED;
+ }
+}
+
+static struct xa_surface *
+surface_create(struct xa_tracker *xa,
+ int width,
+ int height,
+ int depth,
+ enum xa_surface_type stype,
+ enum xa_formats xa_format, unsigned int flags,
+ struct winsys_handle *whandle)
+{
+ struct pipe_resource *template;
+ struct xa_surface *srf;
+ struct xa_format_descriptor fdesc;
+
+ if (xa_format == xa_format_unknown)
+ fdesc = xa_get_format_stype_depth(xa, stype, depth);
+ else
+ fdesc = xa_get_pipe_format(xa, xa_format);
+
+ if (fdesc.xa_format == xa_format_unknown)
+ return NULL;
+
+ srf = calloc(1, sizeof(*srf));
+ if (!srf)
+ return NULL;
+
+ template = &srf->template;
+ template->format = fdesc.format;
+ template->target = PIPE_TEXTURE_2D;
+ template->width0 = width;
+ template->height0 = height;
+ template->depth0 = 1;
+ template->array_size = 1;
+ template->last_level = 0;
+ template->bind = stype_bind[xa_format_type(fdesc.xa_format)];
+
+ if (flags & XA_FLAG_SHARED)
+ template->bind |= PIPE_BIND_SHARED;
+ if (flags & XA_FLAG_RENDER_TARGET)
+ template->bind |= PIPE_BIND_RENDER_TARGET;
+ if (flags & XA_FLAG_SCANOUT)
+ template->bind |= PIPE_BIND_SCANOUT;
+
+ if (whandle)
+ srf->tex = xa->screen->resource_from_handle(xa->screen, template, whandle,
+ PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE);
+ else
+ srf->tex = xa->screen->resource_create(xa->screen, template);
+ if (!srf->tex)
+ goto out_no_tex;
+
+ srf->refcount = 1;
+ srf->xa = xa;
+ srf->flags = flags;
+ srf->fdesc = fdesc;
+
+ return srf;
+ out_no_tex:
+ free(srf);
+ return NULL;
+}
+
+
+XA_EXPORT struct xa_surface *
+xa_surface_create(struct xa_tracker *xa,
+ int width,
+ int height,
+ int depth,
+ enum xa_surface_type stype,
+ enum xa_formats xa_format, unsigned int flags)
+{
+ return surface_create(xa, width, height, depth, stype, xa_format, flags, NULL);
+}
+
+
+XA_EXPORT struct xa_surface *
+xa_surface_from_handle(struct xa_tracker *xa,
+ int width,
+ int height,
+ int depth,
+ enum xa_surface_type stype,
+ enum xa_formats xa_format, unsigned int flags,
+ uint32_t handle, uint32_t stride)
+{
+ return xa_surface_from_handle2(xa, width, height, depth, stype, xa_format,
+ WINSYS_HANDLE_TYPE_SHARED, flags, handle,
+ stride);
+}
+
+XA_EXPORT struct xa_surface *
+xa_surface_from_handle2(struct xa_tracker *xa,
+ int width,
+ int height,
+ int depth,
+ enum xa_surface_type stype,
+ enum xa_formats xa_format, unsigned int flags,
+ enum xa_handle_type type,
+ uint32_t handle, uint32_t stride)
+{
+ struct winsys_handle whandle;
+ memset(&whandle, 0, sizeof(whandle));
+ whandle.type = handle_type(type);
+ whandle.handle = handle;
+ whandle.stride = stride;
+ return surface_create(xa, width, height, depth, stype, xa_format, flags, &whandle);
+}
+
+XA_EXPORT int
+xa_surface_redefine(struct xa_surface *srf,
+ int width,
+ int height,
+ int depth,
+ enum xa_surface_type stype,
+ enum xa_formats xa_format,
+ unsigned int new_flags,
+ int copy_contents)
+{
+ struct pipe_resource *template = &srf->template;
+ struct pipe_resource *texture;
+ struct pipe_box src_box;
+ struct xa_tracker *xa = srf->xa;
+ int save_width;
+ int save_height;
+ unsigned int save_format;
+ struct xa_format_descriptor fdesc;
+
+
+ if (xa_format == xa_format_unknown)
+ fdesc = xa_get_format_stype_depth(xa, stype, depth);
+ else
+ fdesc = xa_get_pipe_format(xa, xa_format);
+
+ if (width == template->width0 && height == template->height0 &&
+ template->format == fdesc.format &&
+ xa_flags_compat(srf->flags, new_flags))
+ return XA_ERR_NONE;
+
+ template->bind = stype_bind[xa_format_type(fdesc.xa_format)];
+ if (new_flags & XA_FLAG_SHARED)
+ template->bind |= PIPE_BIND_SHARED;
+ if (new_flags & XA_FLAG_RENDER_TARGET)
+ template->bind |= PIPE_BIND_RENDER_TARGET;
+ if (new_flags & XA_FLAG_SCANOUT)
+ template->bind |= PIPE_BIND_SCANOUT;
+
+ if (copy_contents) {
+ if (!xa_format_type_is_color(fdesc.xa_format) ||
+ xa_format_type(fdesc.xa_format) == xa_type_a)
+ return -XA_ERR_INVAL;
+
+ if (!xa->screen->is_format_supported(xa->screen, fdesc.format,
+ PIPE_TEXTURE_2D, 0, 0,
+ template->bind |
+ PIPE_BIND_RENDER_TARGET))
+ return -XA_ERR_INVAL;
+ }
+
+ save_width = template->width0;
+ save_height = template->height0;
+ save_format = template->format;
+
+ template->width0 = width;
+ template->height0 = height;
+ template->format = fdesc.format;
+
+ texture = xa->screen->resource_create(xa->screen, template);
+ if (!texture) {
+ template->width0 = save_width;
+ template->height0 = save_height;
+ template->format = save_format;
+ return -XA_ERR_NORES;
+ }
+
+ if (copy_contents) {
+ struct pipe_context *pipe = xa->default_ctx->pipe;
+
+ u_box_origin_2d(xa_min(save_width, template->width0),
+ xa_min(save_height, template->height0), &src_box);
+ pipe->resource_copy_region(pipe, texture,
+ 0, 0, 0, 0, srf->tex, 0, &src_box);
+ xa_context_flush(xa->default_ctx);
+ }
+
+ pipe_resource_reference(&srf->tex, texture);
+ pipe_resource_reference(&texture, NULL);
+ srf->fdesc = fdesc;
+ srf->flags = new_flags;
+
+ return XA_ERR_NONE;
+}
+
+XA_EXPORT struct xa_surface*
+xa_surface_ref(struct xa_surface *srf)
+{
+ if (srf == NULL) {
+ return NULL;
+ }
+ srf->refcount++;
+ return srf;
+}
+
+XA_EXPORT void
+xa_surface_unref(struct xa_surface *srf)
+{
+ if (srf == NULL || --srf->refcount) {
+ return;
+ }
+ pipe_resource_reference(&srf->tex, NULL);
+ free(srf);
+}
+
+XA_EXPORT void
+xa_tracker_version(int *major, int *minor, int *patch)
+{
+ *major = XA_TRACKER_VERSION_MAJOR;
+ *minor = XA_TRACKER_VERSION_MINOR;
+ *patch = XA_TRACKER_VERSION_PATCH;
+}
+
+XA_EXPORT int
+xa_surface_handle(struct xa_surface *srf,
+ enum xa_handle_type type,
+ uint32_t * handle, unsigned int *stride)
+{
+ struct winsys_handle whandle;
+
+ struct pipe_screen *screen = srf->xa->screen;
+ boolean res;
+
+ memset(&whandle, 0, sizeof(whandle));
+ whandle.type = handle_type(type);
+ res = screen->resource_get_handle(screen, srf->xa->default_ctx->pipe,
+ srf->tex, &whandle,
+ PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE);
+ if (!res)
+ return -XA_ERR_INVAL;
+
+ *handle = whandle.handle;
+ *stride = whandle.stride;
+
+ return XA_ERR_NONE;
+}
+
+XA_EXPORT enum xa_formats
+xa_surface_format(const struct xa_surface *srf)
+{
+ return srf->fdesc.xa_format;
+}
diff --git a/src/gallium/frontends/xa/xa_tracker.h.in b/src/gallium/frontends/xa/xa_tracker.h.in
new file mode 100644
index 00000000000..3d136707152
--- /dev/null
+++ b/src/gallium/frontends/xa/xa_tracker.h.in
@@ -0,0 +1,217 @@
+/**********************************************************
+ * Copyright 2009-2011 VMware, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * The format encoding idea is partially borrowed from libpixman, but it is not
+ * considered a "substantial part of the software", so the pixman copyright
+ * is left out for simplicity, and acknowledgment is instead given in this way.
+ *
+ *********************************************************
+ * Authors:
+ * Zack Rusin <zackr-at-vmware-dot-com>
+ * Thomas Hellstrom <thellstrom-at-vmware-dot-com>
+ */
+
+#ifndef _XA_TRACKER_H_
+#define _XA_TRACKER_H_
+
+#include <stdint.h>
+
+#define XA_TRACKER_VERSION_MAJOR @XA_MAJOR@
+#define XA_TRACKER_VERSION_MINOR @XA_MINOR@
+#define XA_TRACKER_VERSION_PATCH @XA_PATCH@
+
+#define XA_FLAG_SHARED (1 << 0)
+#define XA_FLAG_RENDER_TARGET (1 << 1)
+#define XA_FLAG_SCANOUT (1 << 2)
+
+#define XA_MAP_READ (1 << 0)
+#define XA_MAP_WRITE (1 << 1)
+#define XA_MAP_MAP_DIRECTLY (1 << 2)
+#define XA_MAP_UNSYNCHRONIZED (1 << 3)
+#define XA_MAP_DONTBLOCK (1 << 4)
+#define XA_MAP_DISCARD_WHOLE_RESOURCE (1 << 5)
+
+#define XA_ERR_NONE 0
+#define XA_ERR_NORES 1
+#define XA_ERR_INVAL 2
+#define XA_ERR_BUSY 3
+
+enum xa_surface_type {
+ xa_type_other,
+ xa_type_a,
+ xa_type_argb,
+ xa_type_abgr,
+ xa_type_bgra,
+ xa_type_z,
+ xa_type_zs,
+ xa_type_sz,
+ xa_type_yuv_component
+};
+
+/*
+ * Note that these formats should not be assumed to be binary compatible with
+ * pixman formats, but with the below macros and a format type map,
+ * conversion should be simple. Macros for now. We might replace with
+ * inline functions.
+ */
+
+#define xa_format(bpp,type,a,r,g,b) (((bpp) << 24) | \
+ ((type) << 16) | \
+ ((a) << 12) | \
+ ((r) << 8) | \
+ ((g) << 4) | \
+ ((b)))
+/*
+ * Non-RGBA one- and two component formats.
+ */
+
+#define xa_format_c(bpp,type,c1,c2) (((bpp) << 24) | \
+ ((type) << 16) | \
+ ((c1) << 8) | \
+ ((c2)))
+#define xa_format_bpp(f) (((f) >> 24) )
+#define xa_format_type(f) (((f) >> 16) & 0xff)
+#define xa_format_a(f) (((f) >> 12) & 0x0f)
+#define xa_format_r(f) (((f) >> 8) & 0x0f)
+#define xa_format_g(f) (((f) >> 4) & 0x0f)
+#define xa_format_b(f) (((f) ) & 0x0f)
+#define xa_format_rgb(f) (((f) ) & 0xfff)
+#define xa_format_c1(f) (((f) >> 8 ) & 0xff)
+#define xa_format_c2(f) (((f) ) & 0xff)
+#define xa_format_argb_depth(f) (xa_format_a(f) + \
+ xa_format_r(f) + \
+ xa_format_g(f) + \
+ xa_format_b(f))
+#define xa_format_c_depth(f) (xa_format_c1(f) + \
+ xa_format_c2(f))
+
+static inline int
+xa_format_type_is_color(uint32_t xa_format)
+{
+ return (xa_format_type(xa_format) < xa_type_z);
+}
+
+static inline unsigned int
+xa_format_depth(uint32_t xa_format)
+{
+ return ((xa_format_type_is_color(xa_format)) ?
+ xa_format_argb_depth(xa_format) : xa_format_c_depth(xa_format));
+}
+
+enum xa_formats {
+ xa_format_unknown = 0,
+ xa_format_a8 = xa_format(8, xa_type_a, 8, 0, 0, 0),
+
+ xa_format_a8r8g8b8 = xa_format(32, xa_type_argb, 8, 8, 8, 8),
+ xa_format_x8r8g8b8 = xa_format(32, xa_type_argb, 0, 8, 8, 8),
+ xa_format_r5g6b5 = xa_format(16, xa_type_argb, 0, 5, 6, 5),
+ xa_format_x1r5g5b5 = xa_format(16, xa_type_argb, 0, 5, 5, 5),
+ xa_format_a4r4g4b4 = xa_format(16, xa_type_argb, 4, 4, 4, 4),
+ xa_format_a2b10g10r10 = xa_format(32, xa_type_abgr, 2, 10, 10, 10),
+ xa_format_x2b10g10r10 = xa_format(32, xa_type_abgr, 0, 10, 10, 10),
+ xa_format_b8g8r8a8 = xa_format(32, xa_type_bgra, 8, 8, 8, 8),
+ xa_format_b8g8r8x8 = xa_format(32, xa_type_bgra, 0, 8, 8, 8),
+
+ xa_format_z16 = xa_format_c(16, xa_type_z, 16, 0),
+ xa_format_z32 = xa_format_c(32, xa_type_z, 32, 0),
+ xa_format_z24 = xa_format_c(32, xa_type_z, 24, 0),
+
+ xa_format_x8z24 = xa_format_c(32, xa_type_sz, 24, 0),
+ xa_format_s8z24 = xa_format_c(32, xa_type_sz, 24, 8),
+ xa_format_z24x8 = xa_format_c(32, xa_type_zs, 24, 0),
+ xa_format_z24s8 = xa_format_c(32, xa_type_zs, 24, 8),
+
+ xa_format_yuv8 = xa_format_c(8, xa_type_yuv_component, 8, 0)
+};
+
+struct xa_tracker;
+struct xa_surface;
+
+struct xa_box {
+ uint16_t x1, y1, x2, y2;
+};
+
+enum xa_handle_type {
+ xa_handle_type_shared,
+ xa_handle_type_kms,
+ xa_handle_type_fd,
+};
+
+extern void xa_tracker_version(int *major, int *minor, int *patch);
+
+extern struct xa_tracker *xa_tracker_create(int drm_fd);
+
+extern void xa_tracker_destroy(struct xa_tracker *xa);
+
+extern int xa_format_check_supported(struct xa_tracker *xa,
+ enum xa_formats xa_format,
+ unsigned int flags);
+
+extern struct xa_surface *xa_surface_create(struct xa_tracker *xa,
+ int width,
+ int height,
+ int depth,
+ enum xa_surface_type stype,
+ enum xa_formats pform,
+ unsigned int flags);
+
+extern struct xa_surface * xa_surface_from_handle(struct xa_tracker *xa,
+ int width,
+ int height,
+ int depth,
+ enum xa_surface_type stype,
+ enum xa_formats pform,
+ unsigned int flags,
+ uint32_t handle, uint32_t stride);
+extern struct xa_surface *
+xa_surface_from_handle2(struct xa_tracker *xa,
+ int width,
+ int height,
+ int depth,
+ enum xa_surface_type stype,
+ enum xa_formats xa_format,
+ unsigned int flags,
+ enum xa_handle_type type,
+ uint32_t handle,
+ uint32_t stride);
+
+enum xa_formats xa_surface_format(const struct xa_surface *srf);
+
+extern struct xa_surface *xa_surface_ref(struct xa_surface *srf);
+extern void xa_surface_unref(struct xa_surface *srf);
+
+extern int xa_surface_redefine(struct xa_surface *srf,
+ int width,
+ int height,
+ int depth,
+ enum xa_surface_type stype,
+ enum xa_formats rgb_format,
+ unsigned int new_flags,
+ int copy_contents);
+
+extern int xa_surface_handle(struct xa_surface *srf,
+ enum xa_handle_type type,
+ uint32_t * handle,
+ unsigned int *byte_stride);
+
+#endif
diff --git a/src/gallium/frontends/xa/xa_yuv.c b/src/gallium/frontends/xa/xa_yuv.c
new file mode 100644
index 00000000000..97a1833ff15
--- /dev/null
+++ b/src/gallium/frontends/xa/xa_yuv.c
@@ -0,0 +1,163 @@
+/**********************************************************
+ * Copyright 2009-2011 VMware, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ *********************************************************
+ * Authors:
+ * Zack Rusin <zackr-at-vmware-dot-com>
+ * Thomas Hellstrom <thellstrom-at-vmware-dot-com>
+ */
+
+#include "xa_context.h"
+#include "xa_priv.h"
+#include "util/u_inlines.h"
+#include "util/u_sampler.h"
+#include "util/u_surface.h"
+#include "cso_cache/cso_context.h"
+
+static void
+xa_yuv_bind_blend_state(struct xa_context *r)
+{
+ struct pipe_blend_state blend;
+
+ memset(&blend, 0, sizeof(struct pipe_blend_state));
+ blend.rt[0].blend_enable = 0;
+ blend.rt[0].colormask = PIPE_MASK_RGBA;
+
+ /* porter&duff src */
+ blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
+
+ cso_set_blend(r->cso, &blend);
+}
+
+static void
+xa_yuv_bind_shaders(struct xa_context *r)
+{
+ unsigned vs_traits = 0, fs_traits = 0;
+ struct xa_shader shader;
+
+ vs_traits |= VS_YUV;
+ fs_traits |= FS_YUV;
+
+ shader = xa_shaders_get(r->shaders, vs_traits, fs_traits);
+ cso_set_vertex_shader_handle(r->cso, shader.vs);
+ cso_set_fragment_shader_handle(r->cso, shader.fs);
+}
+
+static void
+xa_yuv_bind_samplers(struct xa_context *r, struct xa_surface *yuv[])
+{
+ struct pipe_sampler_state *samplers[3];
+ struct pipe_sampler_state sampler;
+ struct pipe_sampler_view view_templ;
+ unsigned int i;
+
+ memset(&sampler, 0, sizeof(struct pipe_sampler_state));
+
+ sampler.wrap_s = PIPE_TEX_WRAP_CLAMP;
+ sampler.wrap_t = PIPE_TEX_WRAP_CLAMP;
+ sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR;
+ sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
+ sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST;
+ sampler.normalized_coords = 1;
+
+ for (i = 0; i < 3; ++i) {
+ samplers[i] = &sampler;
+ u_sampler_view_default_template(&view_templ, yuv[i]->tex,
+ yuv[i]->tex->format);
+
+ r->bound_sampler_views[i] =
+ r->pipe->create_sampler_view(r->pipe, yuv[i]->tex, &view_templ);
+ }
+ r->num_bound_samplers = 3;
+ cso_set_samplers(r->cso, PIPE_SHADER_FRAGMENT, 3, (const struct pipe_sampler_state **)samplers);
+ cso_set_sampler_views(r->cso, PIPE_SHADER_FRAGMENT, 3, r->bound_sampler_views);
+}
+
+static void
+xa_yuv_fs_constants(struct xa_context *r, const float conversion_matrix[])
+{
+ const int param_bytes = 16 * sizeof(float);
+
+ renderer_set_constants(r, PIPE_SHADER_FRAGMENT,
+ conversion_matrix, param_bytes);
+}
+
+XA_EXPORT int
+xa_yuv_planar_blit(struct xa_context *r,
+ int src_x,
+ int src_y,
+ int src_w,
+ int src_h,
+ int dst_x,
+ int dst_y,
+ int dst_w,
+ int dst_h,
+ struct xa_box *box,
+ unsigned int num_boxes,
+ const float conversion_matrix[],
+ struct xa_surface *dst, struct xa_surface *yuv[])
+{
+ float scale_x;
+ float scale_y;
+ int ret;
+
+ if (dst_w == 0 || dst_h == 0)
+ return XA_ERR_NONE;
+
+ ret = xa_ctx_srf_create(r, dst);
+ if (ret != XA_ERR_NONE)
+ return -XA_ERR_NORES;
+
+ renderer_bind_destination(r, r->srf);
+ xa_yuv_bind_blend_state(r);
+ xa_yuv_bind_shaders(r);
+ xa_yuv_bind_samplers(r, yuv);
+ xa_yuv_fs_constants(r, conversion_matrix);
+
+ scale_x = (float)src_w / (float)dst_w;
+ scale_y = (float)src_h / (float)dst_h;
+
+ while (num_boxes--) {
+ int x = box->x1;
+ int y = box->y1;
+ int w = box->x2 - box->x1;
+ int h = box->y2 - box->y1;
+
+ xa_scissor_update(r, x, y, box->x2, box->y2);
+ renderer_draw_yuv(r,
+ (float)src_x + scale_x * (x - dst_x),
+ (float)src_y + scale_y * (y - dst_y),
+ scale_x * w, scale_y * h, x, y, w, h, yuv);
+ box++;
+ }
+
+ xa_context_flush(r);
+
+ xa_ctx_sampler_views_destroy(r);
+ xa_ctx_srf_destroy(r);
+
+ return XA_ERR_NONE;
+}