summaryrefslogtreecommitdiff
path: root/src/gallium/state_trackers/xorg
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/state_trackers/xorg')
-rw-r--r--src/gallium/state_trackers/xorg/Makefile2
-rw-r--r--src/gallium/state_trackers/xorg/SConscript1
-rw-r--r--src/gallium/state_trackers/xorg/xorg_composite.c675
-rw-r--r--src/gallium/state_trackers/xorg/xorg_composite.h7
-rw-r--r--src/gallium/state_trackers/xorg/xorg_crtc.c167
-rw-r--r--src/gallium/state_trackers/xorg/xorg_dri2.c6
-rw-r--r--src/gallium/state_trackers/xorg/xorg_driver.c204
-rw-r--r--src/gallium/state_trackers/xorg/xorg_exa.c468
-rw-r--r--src/gallium/state_trackers/xorg/xorg_exa.h39
-rw-r--r--src/gallium/state_trackers/xorg/xorg_exa_tgsi.c176
-rw-r--r--src/gallium/state_trackers/xorg/xorg_exa_tgsi.h16
-rw-r--r--src/gallium/state_trackers/xorg/xorg_output.c111
-rw-r--r--src/gallium/state_trackers/xorg/xorg_renderer.c907
-rw-r--r--src/gallium/state_trackers/xorg/xorg_renderer.h60
-rw-r--r--src/gallium/state_trackers/xorg/xorg_tracker.h20
-rw-r--r--src/gallium/state_trackers/xorg/xorg_xv.c719
-rw-r--r--src/gallium/state_trackers/xorg/xvmc/Makefile16
-rw-r--r--src/gallium/state_trackers/xorg/xvmc/SConscript27
-rw-r--r--src/gallium/state_trackers/xorg/xvmc/attributes.c46
-rw-r--r--src/gallium/state_trackers/xorg/xvmc/block.c88
-rw-r--r--src/gallium/state_trackers/xorg/xvmc/context.c252
-rw-r--r--src/gallium/state_trackers/xorg/xvmc/subpicture.c195
-rw-r--r--src/gallium/state_trackers/xorg/xvmc/surface.c409
-rw-r--r--src/gallium/state_trackers/xorg/xvmc/tests/.gitignore5
-rw-r--r--src/gallium/state_trackers/xorg/xvmc/tests/Makefile28
-rw-r--r--src/gallium/state_trackers/xorg/xvmc/tests/test_blocks.c111
-rw-r--r--src/gallium/state_trackers/xorg/xvmc/tests/test_context.c119
-rw-r--r--src/gallium/state_trackers/xorg/xvmc/tests/test_rendering.c317
-rw-r--r--src/gallium/state_trackers/xorg/xvmc/tests/test_surface.c98
-rw-r--r--src/gallium/state_trackers/xorg/xvmc/tests/testlib.c146
-rw-r--r--src/gallium/state_trackers/xorg/xvmc/tests/testlib.h69
-rw-r--r--src/gallium/state_trackers/xorg/xvmc/tests/xvmc_bench.c300
-rw-r--r--src/gallium/state_trackers/xorg/xvmc/xvmc_private.h58
33 files changed, 5040 insertions, 822 deletions
diff --git a/src/gallium/state_trackers/xorg/Makefile b/src/gallium/state_trackers/xorg/Makefile
index 27a1990724..22c107370e 100644
--- a/src/gallium/state_trackers/xorg/Makefile
+++ b/src/gallium/state_trackers/xorg/Makefile
@@ -5,6 +5,8 @@ LIBNAME = xorgtracker
LIBRARY_INCLUDES = \
-DHAVE_CONFIG_H \
+ $(shell pkg-config xextproto --atleast-version=7.0.99.1 \
+ && echo "-DHAVE_XEXTPROTO_71") \
$(shell pkg-config --cflags-only-I pixman-1 xorg-server libdrm xproto) \
-I$(TOP)/src/gallium/include \
-I$(TOP)/src/gallium/auxiliary \
diff --git a/src/gallium/state_trackers/xorg/SConscript b/src/gallium/state_trackers/xorg/SConscript
index 65f55ea378..6165bae7a4 100644
--- a/src/gallium/state_trackers/xorg/SConscript
+++ b/src/gallium/state_trackers/xorg/SConscript
@@ -22,6 +22,7 @@ if 'xorg' in env['statetrackers']:
'xorg_exa.c',
'xorg_exa_tgsi.c',
'xorg_output.c',
+ 'xorg_xv.c',
]
)
Export('st_xorg')
diff --git a/src/gallium/state_trackers/xorg/xorg_composite.c b/src/gallium/state_trackers/xorg/xorg_composite.c
index c708ac3170..a8d779b8ad 100644
--- a/src/gallium/state_trackers/xorg/xorg_composite.c
+++ b/src/gallium/state_trackers/xorg/xorg_composite.c
@@ -1,97 +1,116 @@
#include "xorg_composite.h"
+#include "xorg_renderer.h"
#include "xorg_exa_tgsi.h"
#include "cso_cache/cso_context.h"
#include "util/u_draw_quad.h"
+#include "util/u_math.h"
#include "pipe/p_inlines.h"
+/*XXX also in Xrender.h but the including it here breaks compilition */
+#define XFixedToDouble(f) (((double) (f)) / 65536.)
+
struct xorg_composite_blend {
- int op:8;
+ int op : 8;
- unsigned rgb_src_factor:5; /**< PIPE_BLENDFACTOR_x */
- unsigned rgb_dst_factor:5; /**< PIPE_BLENDFACTOR_x */
+ unsigned alpha_dst : 4;
+ unsigned alpha_src : 4;
- unsigned alpha_src_factor:5; /**< PIPE_BLENDFACTOR_x */
- unsigned alpha_dst_factor:5; /**< PIPE_BLENDFACTOR_x */
+ unsigned rgb_src : 8; /**< PIPE_BLENDFACTOR_x */
+ unsigned rgb_dst : 8; /**< PIPE_BLENDFACTOR_x */
};
#define BLEND_OP_OVER 3
static const struct xorg_composite_blend xorg_blends[] = {
{ PictOpClear,
- PIPE_BLENDFACTOR_CONST_COLOR, PIPE_BLENDFACTOR_CONST_ALPHA,
- PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO },
-
+ 0, 0, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO},
{ PictOpSrc,
- PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE,
- PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO },
-
+ 0, 0, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ZERO},
{ PictOpDst,
- PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO,
- PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE },
-
+ 0, 0, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ONE},
{ PictOpOver,
- PIPE_BLENDFACTOR_SRC_ALPHA, PIPE_BLENDFACTOR_ONE,
- PIPE_BLENDFACTOR_INV_SRC_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA },
-
+ 0, 1, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_INV_SRC_ALPHA},
{ PictOpOverReverse,
- PIPE_BLENDFACTOR_SRC_ALPHA, PIPE_BLENDFACTOR_ONE,
- PIPE_BLENDFACTOR_INV_SRC_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA },
+ 1, 0, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_ONE},
+ { PictOpIn,
+ 1, 0, PIPE_BLENDFACTOR_DST_ALPHA, PIPE_BLENDFACTOR_ZERO},
+ { PictOpInReverse,
+ 0, 1, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_SRC_ALPHA},
+ { PictOpOut,
+ 1, 0, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_ZERO},
+ { PictOpOutReverse,
+ 0, 1, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_INV_SRC_ALPHA},
+ { PictOpAtop,
+ 1, 1, PIPE_BLENDFACTOR_DST_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA},
+ { PictOpAtopReverse,
+ 1, 1, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_SRC_ALPHA},
+ { PictOpXor,
+ 1, 1, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA},
+ { PictOpAdd,
+ 0, 0, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE},
};
+
static INLINE void
-pixel_to_float4(PictFormatPtr format,
- CARD32 pixel, float *color)
+pixel_to_float4(Pixel pixel, float *color)
{
CARD32 r, g, b, a;
- debug_assert(format->type == PictTypeDirect);
-
- r = (pixel >> format->direct.red) & format->direct.redMask;
- g = (pixel >> format->direct.green) & format->direct.greenMask;
- b = (pixel >> format->direct.blue) & format->direct.blueMask;
- a = (pixel >> format->direct.alpha) & format->direct.alphaMask;
- color[0] = ((float)r) / ((float)format->direct.redMask);
- color[1] = ((float)g) / ((float)format->direct.greenMask);
- color[2] = ((float)b) / ((float)format->direct.blueMask);
- color[3] = ((float)a) / ((float)format->direct.alphaMask);
+ a = (pixel >> 24) & 0xff;
+ r = (pixel >> 16) & 0xff;
+ g = (pixel >> 8) & 0xff;
+ b = (pixel >> 0) & 0xff;
+ color[0] = ((float)r) / 255.;
+ color[1] = ((float)g) / 255.;
+ color[2] = ((float)b) / 255.;
+ color[3] = ((float)a) / 255.;
}
-struct acceleration_info {
- int op : 16;
- int with_mask : 1;
- int component_alpha : 1;
-};
-static const struct acceleration_info accelerated_ops[] = {
- {PictOpClear, 1, 0},
- {PictOpSrc, 1, 0},
- {PictOpDst, 1, 0},
- {PictOpOver, 1, 0},
- {PictOpOverReverse, 1, 0},
- {PictOpIn, 1, 0},
- {PictOpInReverse, 1, 0},
- {PictOpOut, 1, 0},
- {PictOpOutReverse, 1, 0},
- {PictOpAtop, 1, 0},
- {PictOpAtopReverse, 1, 0},
- {PictOpXor, 1, 0},
- {PictOpAdd, 1, 0},
- {PictOpSaturate, 1, 0},
-};
-
-static struct xorg_composite_blend
-blend_for_op(int op)
+static boolean
+blend_for_op(struct xorg_composite_blend *blend,
+ int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+ PicturePtr pDstPicture)
{
const int num_blends =
sizeof(xorg_blends)/sizeof(struct xorg_composite_blend);
int i;
+ boolean supported = FALSE;
+
+ /* our default in case something goes wrong */
+ *blend = xorg_blends[BLEND_OP_OVER];
for (i = 0; i < num_blends; ++i) {
- if (xorg_blends[i].op == op)
- return xorg_blends[i];
+ if (xorg_blends[i].op == op) {
+ *blend = xorg_blends[i];
+ supported = TRUE;
+ }
+ }
+
+ /* If there's no dst alpha channel, adjust the blend op so that we'll treat
+ * it as always 1. */
+ if (pDstPicture &&
+ PICT_FORMAT_A(pDstPicture->format) == 0 && blend->alpha_dst) {
+ if (blend->rgb_src == PIPE_BLENDFACTOR_DST_ALPHA)
+ blend->rgb_src = PIPE_BLENDFACTOR_ONE;
+ else if (blend->rgb_src == PIPE_BLENDFACTOR_INV_DST_ALPHA)
+ blend->rgb_src = PIPE_BLENDFACTOR_ZERO;
+ }
+
+ /* If the source alpha is being used, then we should only be in a case where
+ * the source blend factor is 0, and the source blend value is the mask
+ * channels multiplied by the source picture's alpha. */
+ if (pMaskPicture && pMaskPicture->componentAlpha &&
+ PICT_FORMAT_RGB(pMaskPicture->format) && blend->alpha_src) {
+ if (blend->rgb_dst == PIPE_BLENDFACTOR_SRC_ALPHA) {
+ blend->rgb_dst = PIPE_BLENDFACTOR_SRC_COLOR;
+ } else if (blend->rgb_dst == PIPE_BLENDFACTOR_INV_SRC_ALPHA) {
+ blend->rgb_dst = PIPE_BLENDFACTOR_INV_SRC_COLOR;
+ }
}
- return xorg_blends[BLEND_OP_OVER];
+
+ return supported;
}
static INLINE int
@@ -112,150 +131,41 @@ render_repeat_to_gallium(int mode)
return PIPE_TEX_WRAP_REPEAT;
}
-
-static INLINE void
-setup_vertex0(float vertex[2][4], float x, float y,
- float color[4])
-{
- vertex[0][0] = x;
- vertex[0][1] = y;
- vertex[0][2] = 0.f; /*z*/
- vertex[0][3] = 1.f; /*w*/
-
- vertex[1][0] = color[0]; /*r*/
- vertex[1][1] = color[1]; /*g*/
- vertex[1][2] = color[2]; /*b*/
- vertex[1][3] = color[3]; /*a*/
-}
-
-static struct pipe_buffer *
-setup_vertex_data0(struct exa_context *ctx,
- int srcX, int srcY, int maskX, int maskY,
- int dstX, int dstY, int width, int height)
-{
- float vertices[4][2][4];
-
- /* 1st vertex */
- setup_vertex0(vertices[0], dstX, dstY,
- ctx->solid_color);
- /* 2nd vertex */
- setup_vertex0(vertices[1], dstX + width, dstY,
- ctx->solid_color);
- /* 3rd vertex */
- setup_vertex0(vertices[2], dstX + width, dstY + height,
- ctx->solid_color);
- /* 4th vertex */
- setup_vertex0(vertices[3], dstX, dstY + height,
- ctx->solid_color);
-
- return pipe_user_buffer_create(ctx->ctx->screen,
- vertices,
- sizeof(vertices));
-}
-
-static INLINE void
-setup_vertex1(float vertex[2][4], float x, float y, float s, float t)
+static INLINE boolean
+render_filter_to_gallium(int xrender_filter, int *out_filter)
{
- vertex[0][0] = x;
- vertex[0][1] = y;
- vertex[0][2] = 0.f; /*z*/
- vertex[0][3] = 1.f; /*w*/
-
- vertex[1][0] = s; /*s*/
- vertex[1][1] = t; /*t*/
- vertex[1][2] = 0.f; /*r*/
- vertex[1][3] = 1.f; /*q*/
-}
-
-static struct pipe_buffer *
-setup_vertex_data1(struct exa_context *ctx,
- int srcX, int srcY, int maskX, int maskY,
- int dstX, int dstY, int width, int height)
-{
- float vertices[4][2][4];
- float s0, t0, s1, t1;
- struct pipe_texture *src = ctx->bound_textures[0];
-
- s0 = srcX / src->width[0];
- s1 = srcX + width / src->width[0];
- t0 = srcY / src->height[0];
- t1 = srcY + height / src->height[0];
-
- /* 1st vertex */
- setup_vertex1(vertices[0], dstX, dstY,
- s0, t0);
- /* 2nd vertex */
- setup_vertex1(vertices[1], dstX + width, dstY,
- s1, t0);
- /* 3rd vertex */
- setup_vertex1(vertices[2], dstX + width, dstY + height,
- s1, t1);
- /* 4th vertex */
- setup_vertex1(vertices[3], dstX, dstY + height,
- s0, t1);
-
- return pipe_user_buffer_create(ctx->ctx->screen,
- vertices,
- sizeof(vertices));
-}
+ switch (xrender_filter) {
+ case PictFilterNearest:
+ *out_filter = PIPE_TEX_FILTER_NEAREST;
+ break;
+ case PictFilterBilinear:
+ *out_filter = PIPE_TEX_FILTER_LINEAR;
+ break;
+ case PictFilterFast:
+ *out_filter = PIPE_TEX_FILTER_NEAREST;
+ break;
+ case PictFilterGood:
+ *out_filter = PIPE_TEX_FILTER_LINEAR;
+ break;
+ case PictFilterBest:
+ *out_filter = PIPE_TEX_FILTER_LINEAR;
+ break;
+ default:
+ debug_printf("Unkown xrender filter");
+ *out_filter = PIPE_TEX_FILTER_NEAREST;
+ return FALSE;
+ }
-static INLINE void
-setup_vertex2(float vertex[3][4], float x, float y,
- float s0, float t0, float s1, float t1)
-{
- vertex[0][0] = x;
- vertex[0][1] = y;
- vertex[0][2] = 0.f; /*z*/
- vertex[0][3] = 1.f; /*w*/
-
- vertex[1][0] = s0; /*s*/
- vertex[1][1] = t0; /*t*/
- vertex[1][2] = 0.f; /*r*/
- vertex[1][3] = 1.f; /*q*/
-
- vertex[2][0] = s1; /*s*/
- vertex[2][1] = t1; /*t*/
- vertex[2][2] = 0.f; /*r*/
- vertex[2][3] = 1.f; /*q*/
+ return TRUE;
}
-static struct pipe_buffer *
-setup_vertex_data2(struct exa_context *ctx,
- int srcX, int srcY, int maskX, int maskY,
- int dstX, int dstY, int width, int height)
+static boolean is_filter_accelerated(PicturePtr pic)
{
- float vertices[4][3][4];
- float st0[4], st1[4];
- struct pipe_texture *src = ctx->bound_textures[0];
- struct pipe_texture *mask = ctx->bound_textures[0];
-
- st0[0] = srcX / src->width[0];
- st0[1] = srcY / src->height[0];
- st0[2] = srcX + width / src->width[0];
- st0[3] = srcY + height / src->height[0];
-
- st1[0] = maskX / mask->width[0];
- st1[1] = maskY / mask->height[0];
- st1[2] = maskX + width / mask->width[0];
- st1[3] = maskY + height / mask->height[0];
-
- /* 1st vertex */
- setup_vertex2(vertices[0], dstX, dstY,
- st0[0], st0[1], st1[0], st1[1]);
- /* 2nd vertex */
- setup_vertex2(vertices[1], dstX + width, dstY,
- st0[2], st0[1], st1[2], st1[1]);
- /* 3rd vertex */
- setup_vertex2(vertices[2], dstX + width, dstY + height,
- st0[2], st0[3], st1[2], st1[3]);
- /* 4th vertex */
- setup_vertex2(vertices[3], dstX, dstY + height,
- st0[0], st0[3], st1[0], st1[3]);
-
- return pipe_user_buffer_create(ctx->ctx->screen,
- vertices,
- sizeof(vertices));
+ int filter;
+ if (pic && !render_filter_to_gallium(pic->filter, &filter))
+ return FALSE;
+ return TRUE;
}
boolean xorg_composite_accelerated(int op,
@@ -263,125 +173,60 @@ boolean xorg_composite_accelerated(int op,
PicturePtr pMaskPicture,
PicturePtr pDstPicture)
{
- unsigned i;
- unsigned accel_ops_count =
- sizeof(accelerated_ops)/sizeof(struct acceleration_info);
-
-
- /*FIXME: currently accel is disabled */
- return FALSE;
+ ScreenPtr pScreen = pDstPicture->pDrawable->pScreen;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ modesettingPtr ms = modesettingPTR(pScrn);
+ struct xorg_composite_blend blend;
+
+ if (!is_filter_accelerated(pSrcPicture) ||
+ !is_filter_accelerated(pMaskPicture)) {
+ XORG_FALLBACK("Unsupported Xrender filter");
+ }
- if (pSrcPicture) {
- /* component alpha not supported */
- if (pSrcPicture->componentAlpha)
- return FALSE;
- /* fills not supported */
- if (pSrcPicture->pSourcePict)
- return FALSE;
+ if (pSrcPicture->pSourcePict) {
+ if (pSrcPicture->pSourcePict->type != SourcePictTypeSolidFill)
+ XORG_FALLBACK("Gradients not enabled (haven't been well tested)");
}
- for (i = 0; i < accel_ops_count; ++i) {
- if (op == accelerated_ops[i].op) {
- if (pMaskPicture && !accelerated_ops[i].with_mask)
- return FALSE;
- return TRUE;
+ if (blend_for_op(&blend, op,
+ pSrcPicture, pMaskPicture, pDstPicture)) {
+ /* Check for component alpha */
+ if (pMaskPicture && pMaskPicture->componentAlpha &&
+ PICT_FORMAT_RGB(pMaskPicture->format)) {
+ if (blend.alpha_src && blend.rgb_src != PIPE_BLENDFACTOR_ZERO) {
+ XORG_FALLBACK("Component alpha not supported with source "
+ "alpha and source value blending. (op=%d)",
+ op);
+ }
}
+ return TRUE;
}
- return FALSE;
-}
-
-static void
-bind_framebuffer_state(struct exa_context *exa, PicturePtr pDstPicture,
- struct exa_pixmap_priv *pDst)
-{
- unsigned i;
- struct pipe_framebuffer_state state;
- struct pipe_surface *surface = exa_gpu_surface(exa, pDst);
- memset(&state, 0, sizeof(struct pipe_framebuffer_state));
-
- state.width = pDstPicture->pDrawable->width;
- state.height = pDstPicture->pDrawable->height;
-
- state.nr_cbufs = 1;
- state.cbufs[0] = surface;
- for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i)
- state.cbufs[i] = 0;
-
- /* currently we don't use depth/stencil */
- state.zsbuf = 0;
-
- cso_set_framebuffer(exa->cso, &state);
-}
-
-enum AxisOrientation {
- Y0_BOTTOM,
- Y0_TOP
-};
-
-static void
-set_viewport(struct exa_context *exa, int width, int height,
- enum AxisOrientation orientation)
-{
- struct pipe_viewport_state viewport;
- float y_scale = (orientation == Y0_BOTTOM) ? -2.f : 2.f;
-
- viewport.scale[0] = width / 2.f;
- viewport.scale[1] = height / y_scale;
- viewport.scale[2] = 1.0;
- viewport.scale[3] = 1.0;
- viewport.translate[0] = width / 2.f;
- viewport.translate[1] = height / 2.f;
- viewport.translate[2] = 0.0;
- viewport.translate[3] = 0.0;
-
- cso_set_viewport(exa->cso, &viewport);
-}
-
-static void
-bind_viewport_state(struct exa_context *exa, PicturePtr pDstPicture)
-{
- int width = pDstPicture->pDrawable->width;
- int height = pDstPicture->pDrawable->height;
-
- set_viewport(exa, width, height, Y0_TOP);
+ XORG_FALLBACK("Unsupported composition operation = %d", op);
}
static void
bind_blend_state(struct exa_context *exa, int op,
- PicturePtr pSrcPicture, PicturePtr pMaskPicture)
+ PicturePtr pSrcPicture,
+ PicturePtr pMaskPicture,
+ PicturePtr pDstPicture)
{
- boolean component_alpha = pSrcPicture->componentAlpha;
struct xorg_composite_blend blend_opt;
struct pipe_blend_state blend;
- if (component_alpha) {
- op = PictOpOver;
- }
- blend_opt = blend_for_op(op);
+ blend_for_op(&blend_opt, op, pSrcPicture, pMaskPicture, pDstPicture);
memset(&blend, 0, sizeof(struct pipe_blend_state));
blend.blend_enable = 1;
- blend.colormask |= PIPE_MASK_R;
- blend.colormask |= PIPE_MASK_G;
- blend.colormask |= PIPE_MASK_B;
- blend.colormask |= PIPE_MASK_A;
+ blend.colormask |= PIPE_MASK_RGBA;
- blend.rgb_src_factor = blend_opt.rgb_src_factor;
- blend.alpha_src_factor = blend_opt.alpha_src_factor;
- blend.rgb_dst_factor = blend_opt.rgb_dst_factor;
- blend.alpha_dst_factor = blend_opt.alpha_dst_factor;
+ blend.rgb_src_factor = blend_opt.rgb_src;
+ blend.alpha_src_factor = blend_opt.rgb_src;
+ blend.rgb_dst_factor = blend_opt.rgb_dst;
+ blend.alpha_dst_factor = blend_opt.rgb_dst;
- cso_set_blend(exa->cso, &blend);
+ cso_set_blend(exa->renderer->cso, &blend);
}
-static void
-bind_rasterizer_state(struct exa_context *exa)
-{
- struct pipe_rasterizer_state raster;
- memset(&raster, 0, sizeof(struct pipe_rasterizer_state));
- raster.gl_rasterization_rules = 1;
- cso_set_rasterizer(exa->cso, &raster);
-}
static void
bind_shaders(struct exa_context *exa, int op,
@@ -390,14 +235,17 @@ bind_shaders(struct exa_context *exa, int op,
unsigned vs_traits = 0, fs_traits = 0;
struct xorg_shader shader;
+ exa->has_solid_color = FALSE;
+
if (pSrcPicture) {
if (pSrcPicture->pSourcePict) {
if (pSrcPicture->pSourcePict->type == SourcePictTypeSolidFill) {
fs_traits |= FS_SOLID_FILL;
vs_traits |= VS_SOLID_FILL;
- pixel_to_float4(pSrcPicture->pFormat,
- pSrcPicture->pSourcePict->solidFill.color,
+ debug_assert(pSrcPicture->format == PICT_a8r8g8b8);
+ pixel_to_float4(pSrcPicture->pSourcePict->solidFill.color,
exa->solid_color);
+ exa->has_solid_color = TRUE;
} else {
debug_assert("!gradients not supported");
}
@@ -410,14 +258,22 @@ bind_shaders(struct exa_context *exa, int op,
if (pMaskPicture) {
vs_traits |= VS_MASK;
fs_traits |= FS_MASK;
+ if (pMaskPicture->componentAlpha) {
+ struct xorg_composite_blend blend;
+ blend_for_op(&blend, op,
+ pSrcPicture, pMaskPicture, NULL);
+ if (blend.alpha_src) {
+ fs_traits |= FS_CA_SRCALPHA;
+ } else
+ fs_traits |= FS_CA_FULL;
+ }
}
- shader = xorg_shaders_get(exa->shaders, vs_traits, fs_traits);
- cso_set_vertex_shader_handle(exa->cso, shader.vs);
- cso_set_fragment_shader_handle(exa->cso, shader.fs);
+ shader = xorg_shaders_get(exa->renderer->shaders, vs_traits, fs_traits);
+ cso_set_vertex_shader_handle(exa->renderer->cso, shader.vs);
+ cso_set_fragment_shader_handle(exa->renderer->cso, shader.fs);
}
-
static void
bind_samplers(struct exa_context *exa, int op,
PicturePtr pSrcPicture, PicturePtr pMaskPicture,
@@ -435,34 +291,50 @@ bind_samplers(struct exa_context *exa, int op,
memset(&mask_sampler, 0, sizeof(struct pipe_sampler_state));
if (pSrcPicture && pSrc) {
- unsigned src_wrap = render_repeat_to_gallium(
- pSrcPicture->repeatType);
- src_sampler.wrap_s = src_wrap;
- src_sampler.wrap_t = src_wrap;
- src_sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
- src_sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
- src_sampler.normalized_coords = 1;
- samplers[0] = &src_sampler;
- exa->bound_textures[0] = pSrc->tex;
- ++exa->num_bound_samplers;
+ if (exa->has_solid_color) {
+ debug_assert(!"solid color with textures");
+ samplers[0] = NULL;
+ exa->bound_textures[0] = NULL;
+ } else {
+ unsigned src_wrap = render_repeat_to_gallium(
+ pSrcPicture->repeatType);
+ int filter;
+
+ render_filter_to_gallium(pSrcPicture->filter, &filter);
+
+ src_sampler.wrap_s = src_wrap;
+ src_sampler.wrap_t = src_wrap;
+ src_sampler.min_img_filter = filter;
+ src_sampler.mag_img_filter = filter;
+ src_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST;
+ src_sampler.normalized_coords = 1;
+ samplers[0] = &src_sampler;
+ exa->bound_textures[0] = pSrc->tex;
+ exa->num_bound_samplers = 1;
+ }
}
if (pMaskPicture && pMask) {
unsigned mask_wrap = render_repeat_to_gallium(
pMaskPicture->repeatType);
+ int filter;
+
+ render_filter_to_gallium(pMaskPicture->filter, &filter);
+
mask_sampler.wrap_s = mask_wrap;
mask_sampler.wrap_t = mask_wrap;
- mask_sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
- mask_sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
+ mask_sampler.min_img_filter = filter;
+ mask_sampler.mag_img_filter = filter;
+ src_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST;
mask_sampler.normalized_coords = 1;
samplers[1] = &mask_sampler;
exa->bound_textures[1] = pMask->tex;
- ++exa->num_bound_samplers;
+ exa->num_bound_samplers = 2;
}
- cso_set_samplers(exa->cso, exa->num_bound_samplers,
+ cso_set_samplers(exa->renderer->cso, exa->num_bound_samplers,
(const struct pipe_sampler_state **)samplers);
- cso_set_sampler_textures(exa->cso, exa->num_bound_samplers,
+ cso_set_sampler_textures(exa->renderer->cso, exa->num_bound_samplers,
exa->bound_textures);
}
@@ -475,18 +347,8 @@ setup_vs_constant_buffer(struct exa_context *exa,
2.f/width, 2.f/height, 1, 1,
-1, -1, 0, 0
};
- struct pipe_constant_buffer *cbuf = &exa->vs_const_buffer;
-
- pipe_buffer_reference(&cbuf->buffer, NULL);
- cbuf->buffer = pipe_buffer_create(exa->ctx->screen, 16,
- PIPE_BUFFER_USAGE_CONSTANT,
- param_bytes);
-
- if (cbuf->buffer) {
- pipe_buffer_write(exa->ctx->screen, cbuf->buffer,
- 0, param_bytes, vs_consts);
- }
- exa->ctx->set_constant_buffer(exa->ctx, PIPE_SHADER_VERTEX, 0, cbuf);
+ renderer_set_constants(exa->renderer, PIPE_SHADER_VERTEX,
+ vs_consts, param_bytes);
}
@@ -494,33 +356,61 @@ static void
setup_fs_constant_buffer(struct exa_context *exa)
{
const int param_bytes = 4 * sizeof(float);
- float fs_consts[8] = {
+ const float fs_consts[8] = {
0, 0, 0, 1,
};
- struct pipe_constant_buffer *cbuf = &exa->fs_const_buffer;
-
- pipe_buffer_reference(&cbuf->buffer, NULL);
- cbuf->buffer = pipe_buffer_create(exa->ctx->screen, 16,
- PIPE_BUFFER_USAGE_CONSTANT,
- param_bytes);
-
- if (cbuf->buffer) {
- pipe_buffer_write(exa->ctx->screen, cbuf->buffer,
- 0, param_bytes, fs_consts);
- }
- exa->ctx->set_constant_buffer(exa->ctx, PIPE_SHADER_FRAGMENT, 0, cbuf);
+ renderer_set_constants(exa->renderer, PIPE_SHADER_FRAGMENT,
+ fs_consts, param_bytes);
}
static void
-setup_constant_buffers(struct exa_context *exa, PicturePtr pDstPicture)
+setup_constant_buffers(struct exa_context *exa, struct exa_pixmap_priv *pDst)
{
- int width = pDstPicture->pDrawable->width;
- int height = pDstPicture->pDrawable->height;
+ int width = pDst->tex->width[0];
+ int height = pDst->tex->height[0];
setup_vs_constant_buffer(exa, width, height);
setup_fs_constant_buffer(exa);
}
+static INLINE boolean matrix_from_pict_transform(PictTransform *trans, float *matrix)
+{
+ if (!trans)
+ return FALSE;
+
+ matrix[0] = XFixedToDouble(trans->matrix[0][0]);
+ matrix[3] = XFixedToDouble(trans->matrix[0][1]);
+ matrix[6] = XFixedToDouble(trans->matrix[0][2]);
+
+ matrix[1] = XFixedToDouble(trans->matrix[1][0]);
+ matrix[4] = XFixedToDouble(trans->matrix[1][1]);
+ matrix[7] = XFixedToDouble(trans->matrix[1][2]);
+
+ matrix[2] = XFixedToDouble(trans->matrix[2][0]);
+ matrix[5] = XFixedToDouble(trans->matrix[2][1]);
+ matrix[8] = XFixedToDouble(trans->matrix[2][2]);
+
+ return TRUE;
+}
+
+static void
+setup_transforms(struct exa_context *exa,
+ PicturePtr pSrcPicture, PicturePtr pMaskPicture)
+{
+ PictTransform *src_t = NULL;
+ PictTransform *mask_t = NULL;
+
+ if (pSrcPicture)
+ src_t = pSrcPicture->transform;
+ if (pMaskPicture)
+ mask_t = pMaskPicture->transform;
+
+ exa->transform.has_src =
+ matrix_from_pict_transform(src_t, exa->transform.src);
+ exa->transform.has_mask =
+ matrix_from_pict_transform(mask_t, exa->transform.mask);
+}
+
boolean xorg_composite_bind_state(struct exa_context *exa,
int op,
PicturePtr pSrcPicture,
@@ -530,17 +420,18 @@ boolean xorg_composite_bind_state(struct exa_context *exa,
struct exa_pixmap_priv *pMask,
struct exa_pixmap_priv *pDst)
{
- bind_framebuffer_state(exa, pDstPicture, pDst);
- bind_viewport_state(exa, pDstPicture);
- bind_blend_state(exa, op, pSrcPicture, pMaskPicture);
- bind_rasterizer_state(exa);
+ renderer_bind_framebuffer(exa->renderer, pDst);
+ renderer_bind_viewport(exa->renderer, pDst);
+ bind_blend_state(exa, op, pSrcPicture, pMaskPicture, pDstPicture);
+ renderer_bind_rasterizer(exa->renderer);
bind_shaders(exa, op, pSrcPicture, pMaskPicture);
bind_samplers(exa, op, pSrcPicture, pMaskPicture,
pDstPicture, pSrc, pMask, pDst);
+ setup_constant_buffers(exa, pDst);
- setup_constant_buffers(exa, pDstPicture);
+ setup_transforms(exa, pSrcPicture, pMaskPicture);
- return FALSE;
+ return TRUE;
}
void xorg_composite(struct exa_context *exa,
@@ -548,37 +439,67 @@ void xorg_composite(struct exa_context *exa,
int srcX, int srcY, int maskX, int maskY,
int dstX, int dstY, int width, int height)
{
- struct pipe_context *pipe = exa->ctx;
- struct pipe_buffer *buf = 0;
-
if (exa->num_bound_samplers == 0 ) { /* solid fill */
- buf = setup_vertex_data0(exa,
- srcX, srcY, maskX, maskY,
- dstX, dstY, width, height);
- } else if (exa->num_bound_samplers == 1 ) /* src */
- buf = setup_vertex_data1(exa,
- srcX, srcY, maskX, maskY,
- dstX, dstY, width, height);
- else if (exa->num_bound_samplers == 2) /* src + mask */
- buf = setup_vertex_data2(exa,
- srcX, srcY, maskX, maskY,
- dstX, dstY, width, height);
- else if (exa->num_bound_samplers == 3) { /* src + mask + dst */
- debug_assert(!"src/mask/dst not handled right now");
+ renderer_draw_solid_rect(exa->renderer,
+ dstX, dstY, dstX + width, dstY + height,
+ exa->solid_color);
+ } else {
+ int pos[6] = {srcX, srcY, maskX, maskY, dstX, dstY};
+ float *src_matrix = NULL;
+ float *mask_matrix = NULL;
+
+ if (exa->transform.has_src)
+ src_matrix = exa->transform.src;
+ if (exa->transform.has_mask)
+ mask_matrix = exa->transform.mask;
+
+ renderer_draw_textures(exa->renderer,
+ pos, width, height,
+ exa->bound_textures,
+ exa->num_bound_samplers,
+ src_matrix, mask_matrix);
+ }
+}
+
+boolean xorg_solid_bind_state(struct exa_context *exa,
+ struct exa_pixmap_priv *pixmap,
+ Pixel fg)
+{
+ unsigned vs_traits, fs_traits;
+ struct xorg_shader shader;
+
+ pixel_to_float4(fg, exa->solid_color);
+ exa->has_solid_color = TRUE;
+
#if 0
- buf = setup_vertex_data2(exa,
- srcX, srcY, maskX, maskY,
- dstX, dstY, width, height);
+ debug_printf("Color Pixel=(%d, %d, %d, %d), RGBA=(%f, %f, %f, %f)\n",
+ (fg >> 24) & 0xff, (fg >> 16) & 0xff,
+ (fg >> 8) & 0xff, (fg >> 0) & 0xff,
+ exa->solid_color[0], exa->solid_color[1],
+ exa->solid_color[2], exa->solid_color[3]);
#endif
- }
- if (buf) {
- util_draw_vertex_buffer(pipe, buf, 0,
- PIPE_PRIM_TRIANGLE_FAN,
- 4, /* verts */
- 1 + exa->num_bound_samplers); /* attribs/vert */
+ vs_traits = VS_SOLID_FILL;
+ fs_traits = FS_SOLID_FILL;
- pipe_buffer_reference(&buf, NULL);
- }
+ renderer_bind_framebuffer(exa->renderer, pixmap);
+ renderer_bind_viewport(exa->renderer, pixmap);
+ renderer_bind_rasterizer(exa->renderer);
+ bind_blend_state(exa, PictOpSrc, NULL, NULL, NULL);
+ setup_constant_buffers(exa, pixmap);
+
+ shader = xorg_shaders_get(exa->renderer->shaders, vs_traits, fs_traits);
+ cso_set_vertex_shader_handle(exa->renderer->cso, shader.vs);
+ cso_set_fragment_shader_handle(exa->renderer->cso, shader.fs);
+
+ return TRUE;
+}
+
+void xorg_solid(struct exa_context *exa,
+ struct exa_pixmap_priv *pixmap,
+ int x0, int y0, int x1, int y1)
+{
+ renderer_draw_solid_rect(exa->renderer,
+ x0, y0, x1, y1, exa->solid_color);
}
diff --git a/src/gallium/state_trackers/xorg/xorg_composite.h b/src/gallium/state_trackers/xorg/xorg_composite.h
index 17dfcb199e..236addf1ce 100644
--- a/src/gallium/state_trackers/xorg/xorg_composite.h
+++ b/src/gallium/state_trackers/xorg/xorg_composite.h
@@ -22,4 +22,11 @@ void xorg_composite(struct exa_context *exa,
int srcX, int srcY, int maskX, int maskY,
int dstX, int dstY, int width, int height);
+boolean xorg_solid_bind_state(struct exa_context *exa,
+ struct exa_pixmap_priv *pixmap,
+ Pixel fg);
+void xorg_solid(struct exa_context *exa,
+ struct exa_pixmap_priv *pixmap,
+ int x0, int y0, int x1, int y1);
+
#endif
diff --git a/src/gallium/state_trackers/xorg/xorg_crtc.c b/src/gallium/state_trackers/xorg/xorg_crtc.c
index fe08bde9ef..85b9162d4c 100644
--- a/src/gallium/state_trackers/xorg/xorg_crtc.c
+++ b/src/gallium/state_trackers/xorg/xorg_crtc.c
@@ -42,8 +42,12 @@
#include "xorg_tracker.h"
#include "xf86Modes.h"
+#ifdef HAVE_XEXTPROTO_71
+#include <X11/extensions/dpmsconst.h>
+#else
#define DPMS_SERVER
#include <X11/extensions/dpms.h>
+#endif
#include "pipe/p_inlines.h"
#include "util/u_rect.h"
@@ -60,8 +64,6 @@ struct crtc_private
static void
crtc_dpms(xf86CrtcPtr crtc, int mode)
{
- //ScrnInfoPtr pScrn = crtc->scrn;
-
switch (mode) {
case DPMSModeOn:
case DPMSModeStandby:
@@ -73,44 +75,29 @@ crtc_dpms(xf86CrtcPtr crtc, int mode)
}
static Bool
-crtc_lock(xf86CrtcPtr crtc)
-{
- return FALSE;
-}
-
-static void
-crtc_unlock(xf86CrtcPtr crtc)
-{
-}
-
-static void
-crtc_prepare(xf86CrtcPtr crtc)
-{
-}
-
-static void
-crtc_commit(xf86CrtcPtr crtc)
-{
-}
-
-static Bool
-crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode,
- DisplayModePtr adjusted_mode)
-{
- return TRUE;
-}
-
-static void
-crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
- DisplayModePtr adjusted_mode, int x, int y)
+crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
+ Rotation rotation, int x, int y)
{
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
modesettingPtr ms = modesettingPTR(crtc->scrn);
- xf86OutputPtr output = config->output[config->compat_output];
- drmModeConnectorPtr drm_connector = output->driver_private;
+ xf86OutputPtr output = NULL;
+ drmModeConnectorPtr drm_connector;
struct crtc_private *crtcp = crtc->driver_private;
drmModeCrtcPtr drm_crtc = crtcp->drm_crtc;
drmModeModeInfo drm_mode;
+ int i, ret;
+
+ for (i = 0; i < config->num_output; output = NULL, i++) {
+ output = config->output[i];
+
+ if (output->crtc == crtc)
+ break;
+ }
+
+ if (!output)
+ return FALSE;
+
+ drm_connector = output->driver_private;
drm_mode.clock = mode->Clock;
drm_mode.hdisplay = mode->HDisplay;
@@ -129,17 +116,19 @@ crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
xf86SetModeDefaultName(mode);
strncpy(drm_mode.name, mode->name, DRM_DISPLAY_MODE_LEN);
- drmModeSetCrtc(ms->fd, drm_crtc->crtc_id, ms->fb_id, x, y,
- &drm_connector->connector_id, 1, &drm_mode);
-}
+ ret = drmModeSetCrtc(ms->fd, drm_crtc->crtc_id, ms->fb_id, x, y,
+ &drm_connector->connector_id, 1, &drm_mode);
-#if 0
-static void
-crtc_load_lut(xf86CrtcPtr crtc)
-{
- //ScrnInfoPtr pScrn = crtc->scrn;
+ if (ret)
+ return FALSE;
+
+ crtc->x = x;
+ crtc->y = y;
+ crtc->mode = *mode;
+ crtc->rotation = rotation;
+
+ return TRUE;
}
-#endif
static void
crtc_gamma_set(xf86CrtcPtr crtc, CARD16 * red, CARD16 * green, CARD16 * blue,
@@ -150,37 +139,37 @@ crtc_gamma_set(xf86CrtcPtr crtc, CARD16 * red, CARD16 * green, CARD16 * blue,
static void *
crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height)
{
- //ScrnInfoPtr pScrn = crtc->scrn;
-
return NULL;
}
static PixmapPtr
crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
{
- //ScrnInfoPtr pScrn = crtc->scrn;
-
return NULL;
}
static void
crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
{
- //ScrnInfoPtr pScrn = crtc->scrn;
}
+/*
+ * Cursor functions
+ */
+
static void
-crtc_destroy(xf86CrtcPtr crtc)
+crtc_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg)
{
- struct crtc_private *crtcp = crtc->driver_private;
+}
- if (crtcp->cursor_tex)
- pipe_texture_reference(&crtcp->cursor_tex, NULL);
+static void
+crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y)
+{
+ modesettingPtr ms = modesettingPTR(crtc->scrn);
+ struct crtc_private *crtcp = crtc->driver_private;
- drmModeFreeCrtc(crtcp->drm_crtc);
- xfree(crtcp);
+ drmModeMoveCursor(ms->fd, crtcp->drm_crtc->crtc_id, x, y);
}
-
static void
crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 * image)
{
@@ -226,15 +215,6 @@ crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 * image)
}
static void
-crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y)
-{
- modesettingPtr ms = modesettingPTR(crtc->scrn);
- struct crtc_private *crtcp = crtc->driver_private;
-
- drmModeMoveCursor(ms->fd, crtcp->drm_crtc->crtc_id, x, y);
-}
-
-static void
crtc_show_cursor(xf86CrtcPtr crtc)
{
modesettingPtr ms = modesettingPTR(crtc->scrn);
@@ -254,29 +234,6 @@ crtc_hide_cursor(xf86CrtcPtr crtc)
drmModeSetCursor(ms->fd, crtcp->drm_crtc->crtc_id, 0, 0, 0);
}
-static const xf86CrtcFuncsRec crtc_funcs = {
- .dpms = crtc_dpms,
- .save = NULL,
- .restore = NULL,
- .lock = crtc_lock,
- .unlock = crtc_unlock,
- .mode_fixup = crtc_mode_fixup,
- .prepare = crtc_prepare,
- .mode_set = crtc_mode_set,
- .commit = crtc_commit,
- .gamma_set = crtc_gamma_set,
- .shadow_create = crtc_shadow_create,
- .shadow_allocate = crtc_shadow_allocate,
- .shadow_destroy = crtc_shadow_destroy,
- .set_cursor_position = crtc_set_cursor_position,
- .show_cursor = crtc_show_cursor,
- .hide_cursor = crtc_hide_cursor,
- .load_cursor_image = NULL, /* lets convert to argb only */
- .set_cursor_colors = NULL, /* using argb only */
- .load_cursor_argb = crtc_load_cursor_argb,
- .destroy = crtc_destroy,
-};
-
void
crtc_cursor_destroy(xf86CrtcPtr crtc)
{
@@ -287,6 +244,40 @@ crtc_cursor_destroy(xf86CrtcPtr crtc)
}
}
+/*
+ * Misc functions
+ */
+
+static void
+crtc_destroy(xf86CrtcPtr crtc)
+{
+ struct crtc_private *crtcp = crtc->driver_private;
+
+ if (crtcp->cursor_tex)
+ pipe_texture_reference(&crtcp->cursor_tex, NULL);
+
+ drmModeFreeCrtc(crtcp->drm_crtc);
+ xfree(crtcp);
+}
+
+static const xf86CrtcFuncsRec crtc_funcs = {
+ .dpms = crtc_dpms,
+ .set_mode_major = crtc_set_mode_major,
+
+ .set_cursor_colors = crtc_set_cursor_colors,
+ .set_cursor_position = crtc_set_cursor_position,
+ .show_cursor = crtc_show_cursor,
+ .hide_cursor = crtc_hide_cursor,
+ .load_cursor_argb = crtc_load_cursor_argb,
+
+ .shadow_create = crtc_shadow_create,
+ .shadow_allocate = crtc_shadow_allocate,
+ .shadow_destroy = crtc_shadow_destroy,
+
+ .gamma_set = crtc_gamma_set,
+ .destroy = crtc_destroy,
+};
+
void
crtc_init(ScrnInfoPtr pScrn)
{
@@ -305,6 +296,7 @@ crtc_init(ScrnInfoPtr pScrn)
for (c = 0; c < res->count_crtcs; c++) {
drm_crtc = drmModeGetCrtc(ms->fd, res->crtcs[c]);
+
if (!drm_crtc)
continue;
@@ -321,7 +313,6 @@ crtc_init(ScrnInfoPtr pScrn)
crtcp->drm_crtc = drm_crtc;
crtc->driver_private = crtcp;
-
}
out:
diff --git a/src/gallium/state_trackers/xorg/xorg_dri2.c b/src/gallium/state_trackers/xorg/xorg_dri2.c
index 6431a0fe25..c41a7cd639 100644
--- a/src/gallium/state_trackers/xorg/xorg_dri2.c
+++ b/src/gallium/state_trackers/xorg/xorg_dri2.c
@@ -81,11 +81,14 @@ driDoCreateBuffer(DrawablePtr pDraw, DRI2BufferPtr buffer, unsigned int format)
case DRI2BufferStencil:
#if defined(DRI2INFOREC_VERSION) && DRI2INFOREC_VERSION > 2
case DRI2BufferDepthStencil:
+#else
+ /* Works on old X servers because sanity checking is for the weak */
+ case 9:
+#endif
if (exa_priv->depth_stencil_tex &&
!pf_is_depth_stencil(exa_priv->depth_stencil_tex->format))
exa_priv->depth_stencil_tex = NULL;
/* Fall through */
-#endif
case DRI2BufferDepth:
if (exa_priv->depth_stencil_tex)
pipe_texture_reference(&tex, exa_priv->depth_stencil_tex);
@@ -118,6 +121,7 @@ driDoCreateBuffer(DrawablePtr pDraw, DRI2BufferPtr buffer, unsigned int format)
}
if (!tex) {
+ exaMoveInPixmap(private->pPixmap);
xorg_exa_set_shared_usage(private->pPixmap);
pScreen->ModifyPixmapHeader(private->pPixmap, 0, 0, 0, 0, 0, NULL);
tex = xorg_exa_get_texture(private->pPixmap);
diff --git a/src/gallium/state_trackers/xorg/xorg_driver.c b/src/gallium/state_trackers/xorg/xorg_driver.c
index 643b6b3b9e..26cf2dd772 100644
--- a/src/gallium/state_trackers/xorg/xorg_driver.c
+++ b/src/gallium/state_trackers/xorg/xorg_driver.c
@@ -144,20 +144,22 @@ static Bool
CreateFrontBuffer(ScrnInfoPtr pScrn)
{
modesettingPtr ms = modesettingPTR(pScrn);
- ScreenPtr pScreen = pScrn->pScreen;
- PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
unsigned handle, stride;
+ struct pipe_texture *tex;
ms->noEvict = TRUE;
- xorg_exa_set_displayed_usage(rootPixmap);
- pScreen->ModifyPixmapHeader(rootPixmap,
- pScrn->virtualX, pScrn->virtualY,
- pScrn->depth, pScrn->bitsPerPixel,
- pScrn->displayWidth * pScrn->bitsPerPixel / 8,
- NULL);
- ms->noEvict = FALSE;
- handle = xorg_exa_get_pixmap_handle(rootPixmap, &stride);
+ tex = xorg_exa_create_root_texture(pScrn, pScrn->virtualX, pScrn->virtualY,
+ pScrn->depth, pScrn->bitsPerPixel);
+
+ if (!tex)
+ return FALSE;
+
+ if (!ms->api->local_handle_from_texture(ms->api, ms->screen,
+ tex,
+ &stride,
+ &handle))
+ return FALSE;
drmModeAddFB(ms->fd,
pScrn->virtualX,
@@ -166,12 +168,39 @@ CreateFrontBuffer(ScrnInfoPtr pScrn)
pScrn->bitsPerPixel,
stride,
handle,
- &ms->fb_id);
+ &ms->fb_id);
pScrn->frameX0 = 0;
pScrn->frameY0 = 0;
AdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
+ pipe_texture_reference(&ms->root_texture, tex);
+ pipe_texture_reference(&tex, NULL);
+ return TRUE;
+}
+
+static Bool
+BindTextureToRoot(ScrnInfoPtr pScrn)
+{
+ modesettingPtr ms = modesettingPTR(pScrn);
+ ScreenPtr pScreen = pScrn->pScreen;
+ struct pipe_texture *check;
+ PixmapPtr rootPixmap;
+
+ rootPixmap = pScreen->GetScreenPixmap(pScreen);
+
+ xorg_exa_set_displayed_usage(rootPixmap);
+ xorg_exa_set_shared_usage(rootPixmap);
+ xorg_exa_set_texture(rootPixmap, ms->root_texture);
+ if (!pScreen->ModifyPixmapHeader(rootPixmap, -1, -1, -1, -1, -1, NULL))
+ FatalError("Couldn't adjust screen pixmap\n");
+
+ check = xorg_exa_get_texture(rootPixmap);
+ if (ms->root_texture != check)
+ FatalError("Created new root texture\n");
+
+ pipe_texture_reference(&check, NULL);
+
return TRUE;
}
@@ -179,10 +208,9 @@ static Bool
crtc_resize(ScrnInfoPtr pScrn, int width, int height)
{
modesettingPtr ms = modesettingPTR(pScrn);
- //ScreenPtr pScreen = pScrn->pScreen;
- //PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
- //Bool fbAccessDisabled;
- //CARD8 *fbstart;
+ unsigned handle, stride;
+ PixmapPtr rootPixmap;
+ ScreenPtr pScreen = pScrn->pScreen;
if (width == pScrn->virtualX && height == pScrn->virtualY)
return TRUE;
@@ -192,13 +220,40 @@ crtc_resize(ScrnInfoPtr pScrn, int width, int height)
pScrn->virtualX = width;
pScrn->virtualY = height;
+ /*
+ * Remove the old framebuffer & texture.
+ */
+ drmModeRmFB(ms->fd, ms->fb_id);
+ pipe_texture_reference(&ms->root_texture, NULL);
+
+
+ rootPixmap = pScreen->GetScreenPixmap(pScreen);
+ if (!pScreen->ModifyPixmapHeader(rootPixmap, width, height, -1, -1, -1, NULL))
+ return FALSE;
+
+ /* takes one ref */
+ ms->root_texture = xorg_exa_get_texture(rootPixmap);
+
+ if (!ms->api->local_handle_from_texture(ms->api, ms->screen,
+ ms->root_texture,
+ &stride,
+ &handle))
+ FatalError("Could not get handle and stride from texture\n");
+
+ drmModeAddFB(ms->fd,
+ pScrn->virtualX,
+ pScrn->virtualY,
+ pScrn->depth,
+ pScrn->bitsPerPixel,
+ stride,
+ handle,
+ &ms->fb_id);
+
/* HW dependent - FIXME */
pScrn->displayWidth = pScrn->virtualX;
- drmModeRmFB(ms->fd, ms->fb_id);
-
/* now create new frontbuffer */
- return CreateFrontBuffer(pScrn);
+ return CreateFrontBuffer(pScrn) && BindTextureToRoot(pScrn);
}
static const xf86CrtcConfigFuncsRec crtc_config_funcs = {
@@ -206,6 +261,37 @@ static const xf86CrtcConfigFuncsRec crtc_config_funcs = {
};
static Bool
+InitDRM(ScrnInfoPtr pScrn)
+{
+ modesettingPtr ms = modesettingPTR(pScrn);
+
+ /* deal with server regeneration */
+ if (ms->fd < 0) {
+ char *BusID;
+
+ BusID = xalloc(64);
+ sprintf(BusID, "PCI:%d:%d:%d",
+ ((ms->PciInfo->domain << 8) | ms->PciInfo->bus),
+ ms->PciInfo->dev, ms->PciInfo->func
+ );
+
+ ms->fd = drmOpen(NULL, BusID);
+
+ if (ms->fd < 0)
+ return FALSE;
+ }
+
+ if (!ms->api) {
+ ms->api = drm_api_create();
+
+ if (!ms->api)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static Bool
PreInit(ScrnInfoPtr pScrn, int flags)
{
xf86CrtcConfigPtr xf86_config;
@@ -213,7 +299,6 @@ PreInit(ScrnInfoPtr pScrn, int flags)
rgb defaultWeight = { 0, 0, 0 };
EntityInfoPtr pEnt;
EntPtr msEnt = NULL;
- char *BusID;
int max_width, max_height;
if (pScrn->numEntities != 1)
@@ -262,16 +347,9 @@ PreInit(ScrnInfoPtr pScrn, int flags)
}
}
- BusID = xalloc(64);
- sprintf(BusID, "PCI:%d:%d:%d",
- ((ms->PciInfo->domain << 8) | ms->PciInfo->bus),
- ms->PciInfo->dev, ms->PciInfo->func
- );
-
- ms->api = drm_api_create();
- ms->fd = drmOpen(NULL, BusID);
-
- if (ms->fd < 0)
+ ms->fd = -1;
+ ms->api = NULL;
+ if (!InitDRM(pScrn))
return FALSE;
pScrn->monitor = pScrn->confScreen->monitor;
@@ -406,11 +484,12 @@ static void xorgBlockHandler(int i, pointer blockData, pointer pTimeout,
BoxPtr rect = REGION_RECTS(dirty);
int i;
+ /* XXX no need for copy? */
for (i = 0; i < num_cliprects; i++, rect++) {
- clip[i].x = rect->x1;
- clip[i].y = rect->y1;
- clip[i].width = rect->x2 - rect->x1;
- clip[i].height = rect->y2 - rect->y1;
+ clip[i].x1 = rect->x1;
+ clip[i].y1 = rect->y1;
+ clip[i].x2 = rect->x2;
+ clip[i].y2 = rect->y2;
}
/* TODO query connector property to see if this is needed */
@@ -429,7 +508,6 @@ CreateScreenResources(ScreenPtr pScreen)
modesettingPtr ms = modesettingPTR(pScrn);
PixmapPtr rootPixmap;
Bool ret;
- unsigned handle, stride;
ms->noEvict = TRUE;
@@ -437,29 +515,14 @@ CreateScreenResources(ScreenPtr pScreen)
ret = pScreen->CreateScreenResources(pScreen);
pScreen->CreateScreenResources = CreateScreenResources;
- rootPixmap = pScreen->GetScreenPixmap(pScreen);
-
- xorg_exa_set_displayed_usage(rootPixmap);
- xorg_exa_set_shared_usage(rootPixmap);
- if (!pScreen->ModifyPixmapHeader(rootPixmap, -1, -1, -1, -1, -1, NULL))
- FatalError("Couldn't adjust screen pixmap\n");
+ BindTextureToRoot(pScrn);
ms->noEvict = FALSE;
- handle = xorg_exa_get_pixmap_handle(rootPixmap, &stride);
-
- drmModeAddFB(ms->fd,
- pScrn->virtualX,
- pScrn->virtualY,
- pScrn->depth,
- pScrn->bitsPerPixel,
- stride,
- handle,
- &ms->fb_id);
-
AdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
#ifdef DRM_MODE_FEATURE_DIRTYFB
+ rootPixmap = pScreen->GetScreenPixmap(pScreen);
ms->damage = DamageCreate(NULL, NULL, DamageReportNone, TRUE,
pScreen, rootPixmap);
@@ -472,6 +535,8 @@ CreateScreenResources(ScreenPtr pScreen)
"Failed to create screen damage record\n");
return FALSE;
}
+#else
+ (void)rootPixmap;
#endif
return ret;
@@ -484,21 +549,8 @@ ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
modesettingPtr ms = modesettingPTR(pScrn);
VisualPtr visual;
- /* deal with server regeneration */
- if (ms->fd < 0) {
- char *BusID;
-
- BusID = xalloc(64);
- sprintf(BusID, "PCI:%d:%d:%d",
- ((ms->PciInfo->domain << 8) | ms->PciInfo->bus),
- ms->PciInfo->dev, ms->PciInfo->func
- );
-
- ms->fd = drmOpen(NULL, BusID);
-
- if (ms->fd < 0)
- return FALSE;
- }
+ if (!InitDRM(pScrn))
+ return FALSE;
if (!ms->screen) {
ms->screen = ms->api->create_screen(ms->api, ms->fd, NULL);
@@ -558,6 +610,9 @@ ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
xf86SetBlackWhitePixels(pScreen);
ms->exa = xorg_exa_init(pScrn);
+ ms->debug_fallback = debug_get_bool_option("XORG_DEBUG_FALLBACK", TRUE);
+
+ xorg_init_video(pScreen);
miInitializeBackingStore(pScreen);
xf86SetBackingStore(pScreen);
@@ -607,8 +662,8 @@ AdjustFrame(int scrnIndex, int x, int y, int flags)
xf86CrtcPtr crtc = output->crtc;
if (crtc && crtc->enabled) {
- crtc->funcs->mode_set(crtc, pScrn->currentMode, pScrn->currentMode, x,
- y);
+ crtc->funcs->set_mode_major(crtc, pScrn->currentMode,
+ RR_Rotate_0, x, y);
crtc->x = output->initial_x + x;
crtc->y = output->initial_y + y;
}
@@ -681,8 +736,11 @@ EnterVT(int scrnIndex, int flags)
SaveHWState(pScrn);
}
- if (!flags) /* signals startup as we'll do this in CreateScreenResources */
- CreateFrontBuffer(pScrn);
+ if (!CreateFrontBuffer(pScrn))
+ return FALSE;
+
+ if (!flags && !BindTextureToRoot(pScrn))
+ return FALSE;
if (!xf86SetDesiredModes(pScrn))
return FALSE;
@@ -722,11 +780,15 @@ CloseScreen(int scrnIndex, ScreenPtr pScreen)
}
#endif
+ pipe_texture_reference(&ms->root_texture, NULL);
+
if (ms->exa)
xorg_exa_close(pScrn);
+ if (ms->api && ms->api->destroy)
ms->api->destroy(ms->api);
- ms->api = NULL;
+ ms->api = NULL;
+
drmClose(ms->fd);
ms->fd = -1;
diff --git a/src/gallium/state_trackers/xorg/xorg_exa.c b/src/gallium/state_trackers/xorg/xorg_exa.c
index a17a71f23a..bd97baae2b 100644
--- a/src/gallium/state_trackers/xorg/xorg_exa.c
+++ b/src/gallium/state_trackers/xorg/xorg_exa.c
@@ -43,10 +43,12 @@
#include "pipe/p_state.h"
#include "pipe/p_inlines.h"
-#include "cso_cache/cso_context.h"
-
#include "util/u_rect.h"
+#define DEBUG_PRINT 0
+#define DEBUG_SOLID 0
+#define ACCEL_ENABLED TRUE
+
/*
* Helper functions
*/
@@ -72,6 +74,9 @@ exa_get_pipe_format(int depth, enum pipe_format *format, int *bbp)
assert(*bbp == 16);
break;
case 8:
+ *format = PIPE_FORMAT_L8_UNORM;
+ assert(*bbp == 8);
+ break;
case 4:
case 1:
*format = PIPE_FORMAT_A8R8G8B8_UNORM; /* bad bad bad */
@@ -82,6 +87,17 @@ exa_get_pipe_format(int depth, enum pipe_format *format, int *bbp)
}
}
+static void
+xorg_exa_common_done(struct exa_context *exa)
+{
+ exa->copy.src = NULL;
+ exa->copy.dst = NULL;
+ exa->transform.has_src = FALSE;
+ exa->transform.has_mask = FALSE;
+ exa->has_solid_color = FALSE;
+ exa->num_bound_samplers = 0;
+}
+
/*
* Static exported EXA functions
*/
@@ -89,12 +105,21 @@ exa_get_pipe_format(int depth, enum pipe_format *format, int *bbp)
static void
ExaWaitMarker(ScreenPtr pScreen, int marker)
{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ modesettingPtr ms = modesettingPTR(pScrn);
+ struct exa_context *exa = ms->exa;
+
+#if 0
+ xorg_exa_flush(exa, PIPE_FLUSH_RENDER_CACHE, NULL);
+#else
+ xorg_exa_finish(exa);
+#endif
}
static int
ExaMarkSync(ScreenPtr pScreen)
{
- return 1;
+ return 1;
}
static Bool
@@ -111,15 +136,20 @@ ExaDownloadFromScreen(PixmapPtr pPix, int x, int y, int w, int h, char *dst,
if (!priv || !priv->tex)
return FALSE;
- if (exa->ctx->is_texture_referenced(exa->ctx, priv->tex, 0, 0) &
+ if (exa->pipe->is_texture_referenced(exa->pipe, priv->tex, 0, 0) &
PIPE_REFERENCED_FOR_WRITE)
- exa->ctx->flush(exa->ctx, 0, NULL);
+ exa->pipe->flush(exa->pipe, 0, NULL);
transfer = exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
PIPE_TRANSFER_READ, x, y, w, h);
if (!transfer)
return FALSE;
+#if DEBUG_PRINT
+ debug_printf("------ ExaDownloadFromScreen(%d, %d, %d, %d, %d)\n",
+ x, y, w, h, dst_pitch);
+#endif
+
util_copy_rect((unsigned char*)dst, &priv->tex->block, dst_pitch, 0, 0,
w, h, exa->scrn->transfer_map(exa->scrn, transfer),
transfer->stride, 0, 0);
@@ -149,6 +179,11 @@ ExaUploadToScreen(PixmapPtr pPix, int x, int y, int w, int h, char *src,
if (!transfer)
return FALSE;
+#if DEBUG_PRINT
+ debug_printf("++++++ ExaUploadToScreen(%d, %d, %d, %d, %d)\n",
+ x, y, w, h, src_pitch);
+#endif
+
util_copy_rect(exa->scrn->transfer_map(exa->scrn, transfer),
&priv->tex->block, transfer->stride, 0, 0, w, h,
(unsigned char*)src, src_pitch, 0, 0);
@@ -176,22 +211,33 @@ ExaPrepareAccess(PixmapPtr pPix, int index)
if (!priv->tex)
return FALSE;
- if (priv->map_count++ == 0)
+ if (priv->map_count == 0)
{
- if (exa->ctx->is_texture_referenced(exa->ctx, priv->tex, 0, 0) &
+ if (exa->pipe->is_texture_referenced(exa->pipe, priv->tex, 0, 0) &
PIPE_REFERENCED_FOR_WRITE)
- exa->ctx->flush(exa->ctx, 0, NULL);
+ exa->pipe->flush(exa->pipe, 0, NULL);
priv->map_transfer =
exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
+#ifdef EXA_MIXED_PIXMAPS
+ PIPE_TRANSFER_MAP_DIRECTLY |
+#endif
PIPE_TRANSFER_READ_WRITE,
0, 0, priv->tex->width[0], priv->tex->height[0]);
+ if (!priv->map_transfer)
+#ifdef EXA_MIXED_PIXMAPS
+ return FALSE;
+#else
+ FatalError("failed to create transfer\n");
+#endif
pPix->devPrivate.ptr =
exa->scrn->transfer_map(exa->scrn, priv->map_transfer);
pPix->devKind = priv->map_transfer->stride;
}
+ priv->map_count++;
+
return TRUE;
}
@@ -231,15 +277,17 @@ ExaDone(PixmapPtr pPixmap)
if (!priv)
return;
- if (priv->src_surf)
- exa->scrn->tex_surface_destroy(priv->src_surf);
- priv->src_surf = NULL;
+ xorg_exa_common_done(exa);
}
static void
ExaDoneComposite(PixmapPtr pPixmap)
{
+ ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
+ modesettingPtr ms = modesettingPTR(pScrn);
+ struct exa_context *exa = ms->exa;
+ xorg_exa_common_done(exa);
}
static Bool
@@ -250,24 +298,32 @@ ExaPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planeMask, Pixel fg)
struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
struct exa_context *exa = ms->exa;
- if (pPixmap->drawable.depth < 15)
- return FALSE;
-
- if (!EXA_PM_IS_SOLID(&pPixmap->drawable, planeMask))
- return FALSE;
+#if DEBUG_PRINT
+ debug_printf("ExaPrepareSolid(0x%x)\n", fg);
+#endif
+ if (!exa->pipe)
+ XORG_FALLBACK("accle not enabled");
if (!priv || !priv->tex)
- return FALSE;
+ XORG_FALLBACK("%s", !priv ? "!priv" : "!priv->tex");
+
+ if (!EXA_PM_IS_SOLID(&pPixmap->drawable, planeMask))
+ XORG_FALLBACK("planeMask is not solid");
if (alu != GXcopy)
- return FALSE;
+ XORG_FALLBACK("not GXcopy");
- if (!exa->ctx || !exa->ctx->surface_fill)
- return FALSE;
+ if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
+ priv->tex->target,
+ PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) {
+ XORG_FALLBACK("format %s", pf_name(priv->tex->format));
+ }
- priv->color = fg;
+#if DEBUG_SOLID
+ fg = 0xffff0000;
+#endif
- return TRUE;
+ return ACCEL_ENABLED && xorg_solid_bind_state(exa, priv, fg);
}
static void
@@ -277,12 +333,51 @@ ExaSolid(PixmapPtr pPixmap, int x0, int y0, int x1, int y1)
modesettingPtr ms = modesettingPTR(pScrn);
struct exa_context *exa = ms->exa;
struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
- struct pipe_surface *surf = exa_gpu_surface(exa, priv);
- exa->ctx->surface_fill(exa->ctx, surf, x0, y0, x1 - x0, y1 - y0,
- priv->color);
+#if DEBUG_PRINT
+ debug_printf("\tExaSolid(%d, %d, %d, %d)\n", x0, y0, x1, y1);
+#endif
+
+#if 0
+ if (x0 == 0 && y0 == 0 &&
+ x1 == priv->tex->width[0] &&
+ y1 == priv->tex->height[0]) {
+ exa->ctx->clear(exa->pipe, PIPE_CLEAR_COLOR,
+ exa->solid_color, 1., 0);
+ } else
+#endif
- exa->scrn->tex_surface_destroy(surf);
+#if DEBUG_SOLID
+ exa->solid_color[0] = 0.f;
+ exa->solid_color[1] = 1.f;
+ exa->solid_color[2] = 0.f;
+ exa->solid_color[3] = 1.f;
+ xorg_solid(exa, priv, 0, 0, 1024, 768);
+ exa->solid_color[0] = 1.f;
+ exa->solid_color[1] = 0.f;
+ exa->solid_color[2] = 0.f;
+ exa->solid_color[3] = 1.f;
+ xorg_solid(exa, priv, 0, 0, 300, 300);
+ xorg_solid(exa, priv, 300, 300, 350, 350);
+ xorg_solid(exa, priv, 350, 350, 500, 500);
+
+ xorg_solid(exa, priv,
+ priv->tex->width[0] - 10,
+ priv->tex->height[0] - 10,
+ priv->tex->width[0],
+ priv->tex->height[0]);
+
+ exa->solid_color[0] = 0.f;
+ exa->solid_color[1] = 0.f;
+ exa->solid_color[2] = 1.f;
+ exa->solid_color[3] = 1.f;
+
+ exa->has_solid_color = FALSE;
+ ExaPrepareCopy(pPixmap, pPixmap, 0, 0, GXcopy, 0xffffffff);
+ ExaCopy(pPixmap, 0, 0, 50, 50, 500, 500);
+#else
+ xorg_solid(exa, priv, x0, y0, x1, y1) ;
+#endif
}
static Bool
@@ -295,42 +390,59 @@ ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
struct exa_pixmap_priv *src_priv = exaGetPixmapDriverPrivate(pSrcPixmap);
- if (alu != GXcopy)
- return FALSE;
+#if DEBUG_PRINT
+ debug_printf("ExaPrepareCopy\n");
+#endif
+ if (!exa->pipe)
+ XORG_FALLBACK("accle not enabled");
- if (pSrcPixmap->drawable.depth < 15 || pDstPixmap->drawable.depth < 15)
- return FALSE;
+ if (!priv || !priv->tex)
+ XORG_FALLBACK("pDst %s", !priv ? "!priv" : "!priv->tex");
+
+ if (!src_priv || !src_priv->tex)
+ XORG_FALLBACK("pSrc %s", !src_priv ? "!priv" : "!priv->tex");
if (!EXA_PM_IS_SOLID(&pSrcPixmap->drawable, planeMask))
- return FALSE;
+ XORG_FALLBACK("planeMask is not solid");
- if (!priv || !src_priv)
- return FALSE;
+ if (alu != GXcopy)
+ XORG_FALLBACK("alu not GXcopy");
- if (!priv->tex || !src_priv->tex)
- return FALSE;
+ if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
+ priv->tex->target,
+ PIPE_TEXTURE_USAGE_RENDER_TARGET, 0))
+ XORG_FALLBACK("pDst format %s", pf_name(priv->tex->format));
- if (!exa->ctx || !exa->ctx->surface_copy)
- return FALSE;
+ if (!exa->scrn->is_format_supported(exa->scrn, src_priv->tex->format,
+ src_priv->tex->target,
+ PIPE_TEXTURE_USAGE_SAMPLER, 0))
+ XORG_FALLBACK("pSrc format %s", pf_name(src_priv->tex->format));
- priv->src_surf = exa_gpu_surface(exa, src_priv);
+ exa->copy.src = src_priv;
+ exa->copy.dst = priv;
- return TRUE;
+ return ACCEL_ENABLED;
}
static void
ExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
int width, int height)
{
- ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
- modesettingPtr ms = modesettingPTR(pScrn);
- struct exa_context *exa = ms->exa;
- struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
- struct pipe_surface *surf = exa_gpu_surface(exa, priv);
+ ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
+ modesettingPtr ms = modesettingPTR(pScrn);
+ struct exa_context *exa = ms->exa;
+ struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
+
+#if DEBUG_PRINT
+ debug_printf("\tExaCopy(srcx=%d, srcy=%d, dstX=%d, dstY=%d, w=%d, h=%d)\n",
+ srcX, srcY, dstX, dstY, width, height);
+#endif
+
+ debug_assert(priv == exa->copy.dst);
- exa->ctx->surface_copy(exa->ctx, surf, dstX, dstY, priv->src_surf,
- srcX, srcY, width, height);
- exa->scrn->tex_surface_destroy(surf);
+ renderer_copy_pixmap(exa->renderer, exa->copy.dst, dstX, dstY,
+ exa->copy.src, srcX, srcY,
+ width, height);
}
static Bool
@@ -341,11 +453,51 @@ ExaPrepareComposite(int op, PicturePtr pSrcPicture,
ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
modesettingPtr ms = modesettingPTR(pScrn);
struct exa_context *exa = ms->exa;
+ struct exa_pixmap_priv *priv;
+
+#if DEBUG_PRINT
+ debug_printf("ExaPrepareComposite(%d, src=0x%p, mask=0x%p, dst=0x%p)\n",
+ op, pSrcPicture, pMaskPicture, pDstPicture);
+#endif
+ if (!exa->pipe)
+ XORG_FALLBACK("accle not enabled");
+
+ priv = exaGetPixmapDriverPrivate(pDst);
+ if (!priv || !priv->tex)
+ XORG_FALLBACK("pDst %s", !priv ? "!priv" : "!priv->tex");
+
+ if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
+ priv->tex->target,
+ PIPE_TEXTURE_USAGE_RENDER_TARGET, 0))
+ XORG_FALLBACK("pDst format: %s", pf_name(priv->tex->format));
+
+ if (pSrc) {
+ priv = exaGetPixmapDriverPrivate(pSrc);
+ if (!priv || !priv->tex)
+ XORG_FALLBACK("pSrc %s", !priv ? "!priv" : "!priv->tex");
+
+ if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
+ priv->tex->target,
+ PIPE_TEXTURE_USAGE_SAMPLER, 0))
+ XORG_FALLBACK("pSrc format: %s", pf_name(priv->tex->format));
+ }
- return xorg_composite_bind_state(exa, op, pSrcPicture, pMaskPicture,
+ if (pMask) {
+ priv = exaGetPixmapDriverPrivate(pMask);
+ if (!priv || !priv->tex)
+ XORG_FALLBACK("pMask %s", !priv ? "!priv" : "!priv->tex");
+
+ if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
+ priv->tex->target,
+ PIPE_TEXTURE_USAGE_SAMPLER, 0))
+ XORG_FALLBACK("pMask format: %s", pf_name(priv->tex->format));
+ }
+
+ return ACCEL_ENABLED &&
+ xorg_composite_bind_state(exa, op, pSrcPicture, pMaskPicture,
pDstPicture,
- exaGetPixmapDriverPrivate(pSrc),
- exaGetPixmapDriverPrivate(pMask),
+ pSrc ? exaGetPixmapDriverPrivate(pSrc) : NULL,
+ pMask ? exaGetPixmapDriverPrivate(pMask) : NULL,
exaGetPixmapDriverPrivate(pDst));
}
@@ -358,6 +510,13 @@ ExaComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
struct exa_context *exa = ms->exa;
struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDst);
+#if DEBUG_PRINT
+ debug_printf("\tExaComposite(src[%d,%d], mask=[%d, %d], dst=[%d, %d], dim=[%d, %d])\n",
+ srcX, srcY, maskX, maskY, dstX, dstY, width, height);
+ debug_printf("\t Num bound samplers = %d\n",
+ exa->num_bound_samplers);
+#endif
+
xorg_composite(exa, priv, srcX, srcY, maskX, maskY,
dstX, dstY, width, height);
}
@@ -367,10 +526,15 @@ ExaCheckComposite(int op,
PicturePtr pSrcPicture, PicturePtr pMaskPicture,
PicturePtr pDstPicture)
{
- return xorg_composite_accelerated(op,
- pSrcPicture,
- pMaskPicture,
- pDstPicture);
+ boolean accelerated = xorg_composite_accelerated(op,
+ pSrcPicture,
+ pMaskPicture,
+ pDstPicture);
+#if DEBUG_PRINT
+ debug_printf("ExaCheckComposite(%d, %p, %p, %p) = %d\n",
+ op, pSrcPicture, pMaskPicture, pDstPicture, accelerated);
+#endif
+ return ACCEL_ENABLED && accelerated;
}
static void *
@@ -389,14 +553,11 @@ static void
ExaDestroyPixmap(ScreenPtr pScreen, void *dPriv)
{
struct exa_pixmap_priv *priv = (struct exa_pixmap_priv *)dPriv;
- ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
- modesettingPtr ms = modesettingPTR(pScrn);
if (!priv)
return;
- if (priv->tex)
- ms->screen->texture_destroy(priv->tex);
+ pipe_texture_reference(&priv->tex, NULL);
xfree(priv);
}
@@ -516,64 +677,43 @@ ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
priv->tex->height[0] != height ||
priv->tex_flags != priv->flags)) {
struct pipe_texture *texture = NULL;
-
-#ifdef DRM_MODE_FEATURE_DIRTYFB
- if (priv->flags)
-#endif
- {
- struct pipe_texture template;
-
- memset(&template, 0, sizeof(template));
- template.target = PIPE_TEXTURE_2D;
- exa_get_pipe_format(depth, &template.format, &bitsPerPixel);
- pf_get_block(template.format, &template.block);
- template.width[0] = width;
- template.height[0] = height;
- template.depth[0] = 1;
- template.last_level = 0;
- template.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET | priv->flags;
- priv->tex_flags = priv->flags;
- texture = exa->scrn->texture_create(exa->scrn, &template);
-
- if (priv->tex) {
- struct pipe_surface *dst_surf;
-
- dst_surf = exa->scrn->get_tex_surface(exa->scrn, texture, 0, 0, 0,
- PIPE_BUFFER_USAGE_GPU_WRITE);
- priv->src_surf = exa_gpu_surface(exa, priv);
- exa->ctx->surface_copy(exa->ctx, dst_surf, 0, 0, priv->src_surf,
- 0, 0, min(width, texture->width[0]),
- min(height, texture->height[0]));
- exa->scrn->tex_surface_destroy(dst_surf);
- exa->scrn->tex_surface_destroy(priv->src_surf);
- priv->src_surf = NULL;
- } else if (pPixmap->devPrivate.ptr) {
- struct pipe_transfer *transfer;
-
- if (priv->map_count != 0)
- FatalError("doing ExaModifyPixmapHeader on mapped buffer\n");
-
- transfer =
- exa->scrn->get_tex_transfer(exa->scrn, texture, 0, 0, 0,
- PIPE_TRANSFER_WRITE,
- 0, 0, width, height);
- util_copy_rect(exa->scrn->transfer_map(exa->scrn, transfer),
- &texture->block, transfer->stride, 0, 0,
- width, height, pPixmap->devPrivate.ptr,
- pPixmap->devKind, 0, 0);
- exa->scrn->transfer_unmap(exa->scrn, transfer);
- exa->scrn->tex_transfer_destroy(transfer);
- }
+ struct pipe_texture template;
+
+ memset(&template, 0, sizeof(template));
+ template.target = PIPE_TEXTURE_2D;
+ exa_get_pipe_format(depth, &template.format, &bitsPerPixel);
+ pf_get_block(template.format, &template.block);
+ template.width[0] = width;
+ template.height[0] = height;
+ template.depth[0] = 1;
+ template.last_level = 0;
+ template.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET | priv->flags;
+ priv->tex_flags = priv->flags;
+ texture = exa->scrn->texture_create(exa->scrn, &template);
+
+ if (priv->tex) {
+ struct pipe_surface *dst_surf;
+ struct pipe_surface *src_surf;
+
+ dst_surf = exa->scrn->get_tex_surface(
+ exa->scrn, texture, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE);
+ src_surf = xorg_gpu_surface(exa->pipe->screen, priv);
+ if (exa->pipe->surface_copy) {
+ exa->pipe->surface_copy(exa->pipe, dst_surf, 0, 0, src_surf,
+ 0, 0, min(width, texture->width[0]),
+ min(height, texture->height[0]));
+ } else {
+ util_surface_copy(exa->pipe, FALSE, dst_surf, 0, 0, src_surf,
+ 0, 0, min(width, texture->width[0]),
+ min(height, texture->height[0]));
+ }
+ exa->scrn->tex_surface_destroy(dst_surf);
+ exa->scrn->tex_surface_destroy(src_surf);
}
-#ifdef DRM_MODE_FEATURE_DIRTYFB
- else {
- xfree(pPixmap->devPrivate.ptr);
- pPixmap->devPrivate.ptr = xalloc(pPixmap->drawable.height *
- pPixmap->devKind);
- }
-#endif
pipe_texture_reference(&priv->tex, texture);
+ /* the texture we create has one reference */
+ pipe_texture_reference(&texture, NULL);
}
return TRUE;
@@ -588,31 +728,60 @@ xorg_exa_get_texture(PixmapPtr pPixmap)
return tex;
}
+Bool
+xorg_exa_set_texture(PixmapPtr pPixmap, struct pipe_texture *tex)
+{
+ struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
+
+ int mask = PIPE_TEXTURE_USAGE_PRIMARY | PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
+
+ if (!priv)
+ return FALSE;
+
+ if (pPixmap->drawable.width != tex->width[0] ||
+ pPixmap->drawable.height != tex->height[0])
+ return FALSE;
+
+ pipe_texture_reference(&priv->tex, tex);
+ priv->tex_flags = tex->tex_usage & mask;
+
+ return TRUE;
+}
+
+struct pipe_texture *
+xorg_exa_create_root_texture(ScrnInfoPtr pScrn,
+ int width, int height,
+ int depth, int bitsPerPixel)
+{
+ modesettingPtr ms = modesettingPTR(pScrn);
+ struct exa_context *exa = ms->exa;
+ struct pipe_texture template;
+
+ memset(&template, 0, sizeof(template));
+ template.target = PIPE_TEXTURE_2D;
+ exa_get_pipe_format(depth, &template.format, &bitsPerPixel);
+ pf_get_block(template.format, &template.block);
+ template.width[0] = width;
+ template.height[0] = height;
+ template.depth[0] = 1;
+ template.last_level = 0;
+ template.tex_usage |= PIPE_TEXTURE_USAGE_RENDER_TARGET;
+ template.tex_usage |= PIPE_TEXTURE_USAGE_PRIMARY;
+ template.tex_usage |= PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
+
+ return exa->scrn->texture_create(exa->scrn, &template);
+}
+
void
xorg_exa_close(ScrnInfoPtr pScrn)
{
modesettingPtr ms = modesettingPTR(pScrn);
struct exa_context *exa = ms->exa;
- struct pipe_constant_buffer *vsbuf = &exa->vs_const_buffer;
- struct pipe_constant_buffer *fsbuf = &exa->fs_const_buffer;
-
- if (exa->shaders) {
- xorg_shaders_destroy(exa->shaders);
- }
- if (vsbuf && vsbuf->buffer)
- pipe_buffer_reference(&vsbuf->buffer, NULL);
+ renderer_destroy(exa->renderer);
- if (fsbuf && fsbuf->buffer)
- pipe_buffer_reference(&fsbuf->buffer, NULL);
-
- if (exa->cso) {
- cso_release_all(exa->cso);
- cso_destroy_context(exa->cso);
- }
-
- if (exa->ctx)
- exa->ctx->destroy(exa->ctx);
+ if (exa->pipe)
+ exa->pipe->destroy(exa->pipe);
exaDriverFini(pScrn->pScreen);
xfree(exa);
@@ -645,6 +814,12 @@ xorg_exa_init(ScrnInfoPtr pScrn)
pExa->pixmapOffsetAlign = 0;
pExa->pixmapPitchAlign = 1;
pExa->flags = EXA_OFFSCREEN_PIXMAPS | EXA_HANDLES_PIXMAPS;
+#ifdef EXA_SUPPORTS_PREPARE_AUX
+ pExa->flags |= EXA_SUPPORTS_PREPARE_AUX;
+#endif
+#ifdef EXA_MIXED_PIXMAPS
+ pExa->flags |= EXA_MIXED_PIXMAPS;
+#endif
pExa->maxX = 8191; /* FIXME */
pExa->maxY = 8191; /* FIXME */
@@ -674,12 +849,11 @@ xorg_exa_init(ScrnInfoPtr pScrn)
}
exa->scrn = ms->screen;
- exa->ctx = ms->api->create_context(ms->api, exa->scrn);
+ exa->pipe = ms->api->create_context(ms->api, exa->scrn);
/* Share context with DRI */
- ms->ctx = exa->ctx;
+ ms->ctx = exa->pipe;
- exa->cso = cso_create_context(exa->ctx);
- exa->shaders = xorg_shaders_create(exa);
+ exa->renderer = renderer_create(exa->pipe);
return (void *)exa;
@@ -690,11 +864,27 @@ out_err:
}
struct pipe_surface *
-exa_gpu_surface(struct exa_context *exa, struct exa_pixmap_priv *priv)
+xorg_gpu_surface(struct pipe_screen *scrn, struct exa_pixmap_priv *priv)
{
- return exa->scrn->get_tex_surface(exa->scrn, priv->tex, 0, 0, 0,
- PIPE_BUFFER_USAGE_GPU_READ |
- PIPE_BUFFER_USAGE_GPU_WRITE);
+ return scrn->get_tex_surface(scrn, priv->tex, 0, 0, 0,
+ PIPE_BUFFER_USAGE_GPU_READ |
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+
+}
+
+void xorg_exa_flush(struct exa_context *exa, uint pipeFlushFlags,
+ struct pipe_fence_handle **fence)
+{
+ exa->pipe->flush(exa->pipe, pipeFlushFlags, fence);
+}
+
+void xorg_exa_finish(struct exa_context *exa)
+{
+ struct pipe_fence_handle *fence = NULL;
+
+ xorg_exa_flush(exa, PIPE_FLUSH_RENDER_CACHE, &fence);
+ exa->pipe->screen->fence_finish(exa->pipe->screen, fence, 0);
+ exa->pipe->screen->fence_reference(exa->pipe->screen, &fence, NULL);
}
diff --git a/src/gallium/state_trackers/xorg/xorg_exa.h b/src/gallium/state_trackers/xorg/xorg_exa.h
index 5b515be139..45f88d9404 100644
--- a/src/gallium/state_trackers/xorg/xorg_exa.h
+++ b/src/gallium/state_trackers/xorg/xorg_exa.h
@@ -14,20 +14,29 @@ struct xorg_shaders;
struct exa_context
{
ExaDriverPtr pExa;
- struct pipe_context *ctx;
+ struct pipe_context *pipe;
struct pipe_screen *scrn;
- struct cso_context *cso;
- struct xorg_shaders *shaders;
-
- struct pipe_constant_buffer vs_const_buffer;
- struct pipe_constant_buffer fs_const_buffer;
+ struct xorg_renderer *renderer;
struct pipe_texture *bound_textures[MAX_EXA_SAMPLERS];
int num_bound_samplers;
float solid_color[4];
-};
+ boolean has_solid_color;
+ /* float[9] projective matrix bound to pictures */
+ struct {
+ float src[9];
+ float mask[9];
+ boolean has_src;
+ boolean has_mask;
+ } transform;
+
+ struct {
+ struct exa_pixmap_priv *src;
+ struct exa_pixmap_priv *dst;
+ } copy;
+};
struct exa_pixmap_priv
{
@@ -36,15 +45,25 @@ struct exa_pixmap_priv
struct pipe_texture *tex;
struct pipe_texture *depth_stencil_tex;
- unsigned int color;
- struct pipe_surface *src_surf; /* for copies */
struct pipe_transfer *map_transfer;
unsigned map_count;
};
+#define XORG_FALLBACK(s, arg...) \
+do { \
+ if (ms->debug_fallback) { \
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, \
+ "%s fallback " s "\n", __FUNCTION__, ##arg); \
+ } \
+ return FALSE; \
+} while(0)
+
struct pipe_surface *
-exa_gpu_surface(struct exa_context *exa, struct exa_pixmap_priv *priv);
+xorg_gpu_surface(struct pipe_screen *scrn, struct exa_pixmap_priv *priv);
+void xorg_exa_flush(struct exa_context *exa, uint pipeFlushFlags,
+ struct pipe_fence_handle **fence);
+void xorg_exa_finish(struct exa_context *exa);
#endif
diff --git a/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c b/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c
index cfee10c3b3..83cc12fea9 100644
--- a/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c
+++ b/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c
@@ -44,33 +44,29 @@
*/
struct xorg_shaders {
- struct exa_context *exa;
+ struct xorg_renderer *r;
struct cso_hash *vs_hash;
struct cso_hash *fs_hash;
};
-static const char over_op[] =
- "SUB TEMP[3], CONST[0].wwww, TEMP[1].wwww\n"
- "MUL TEMP[3], TEMP[0], TEMP[3]\n"
- "ADD TEMP[0], TEMP[3], TEMP[0]\n";
-
-
-static INLINE void
-create_preamble(struct ureg_program *ureg)
-{
-}
-
-
static INLINE void
src_in_mask(struct ureg_program *ureg,
struct ureg_dst dst,
struct ureg_src src,
- struct ureg_src mask)
+ struct ureg_src mask,
+ int component_alpha)
{
- /* MUL dst, src, mask.wwww */
- ureg_MUL(ureg, dst, src,
- ureg_scalar(mask, TGSI_SWIZZLE_W));
+ if (component_alpha == FS_CA_FULL) {
+ ureg_MUL(ureg, dst, src, mask);
+ } else if (component_alpha == FS_CA_SRCALPHA) {
+ ureg_MUL(ureg, dst,
+ ureg_scalar(src, TGSI_SWIZZLE_W), mask);
+ }
+ else {
+ ureg_MUL(ureg, dst, src,
+ ureg_scalar(mask, TGSI_SWIZZLE_X));
+ }
}
static struct ureg_src
@@ -79,8 +75,7 @@ vs_normalize_coords(struct ureg_program *ureg, struct ureg_src coords,
{
struct ureg_dst tmp = ureg_DECL_temporary(ureg);
struct ureg_src ret;
- ureg_MUL(ureg, tmp, coords, const0);
- ureg_ADD(ureg, tmp, ureg_src(tmp), const1);
+ ureg_MAD(ureg, tmp, coords, const0, const1);
ret = ureg_src(tmp);
ureg_release_temporary(ureg, tmp);
return ret;
@@ -241,42 +236,46 @@ create_vs(struct pipe_context *pipe,
boolean is_fill = vs_traits & VS_FILL;
boolean is_composite = vs_traits & VS_COMPOSITE;
boolean has_mask = vs_traits & VS_MASK;
+ boolean is_yuv = vs_traits & VS_YUV;
+ unsigned input_slot = 0;
ureg = ureg_create(TGSI_PROCESSOR_VERTEX);
if (ureg == NULL)
return 0;
- const0 = ureg_DECL_constant(ureg);
- const1 = ureg_DECL_constant(ureg);
+ const0 = ureg_DECL_constant(ureg, 0);
+ const1 = ureg_DECL_constant(ureg, 1);
/* it has to be either a fill or a composite op */
- debug_assert(is_fill ^ is_composite);
+ debug_assert((is_fill ^ is_composite) ^ is_yuv);
- src = ureg_DECL_vs_input(ureg,
- TGSI_SEMANTIC_POSITION, 0);
+ 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) {
- src = ureg_DECL_vs_input(ureg,
- TGSI_SEMANTIC_GENERIC, 1);
- dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 1);
+ src = ureg_DECL_vs_input(ureg, input_slot++);
+ dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 0);
ureg_MOV(ureg, dst, src);
}
+
if (is_fill) {
- src = ureg_DECL_vs_input(ureg,
- TGSI_SEMANTIC_COLOR, 1);
- dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 1);
+ src = ureg_DECL_vs_input(ureg, input_slot++);
+ dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
ureg_MOV(ureg, dst, src);
}
if (has_mask) {
- src = ureg_DECL_vs_input(ureg,
- TGSI_SEMANTIC_GENERIC, 2);
- dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 2);
+ src = ureg_DECL_vs_input(ureg, input_slot++);
+ dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 1);
ureg_MOV(ureg, dst, src);
}
@@ -286,6 +285,75 @@ create_vs(struct pipe_context *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;
+ 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);
+
+ matrow0 = ureg_DECL_constant(ureg, 0);
+ matrow1 = ureg_DECL_constant(ureg, 1);
+ matrow2 = ureg_DECL_constant(ureg, 2);
+
+ 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_SUB(ureg, u, ureg_src(u),
+ ureg_scalar(matrow0, TGSI_SWIZZLE_W));
+ ureg_SUB(ureg, v, ureg_src(v),
+ ureg_scalar(matrow0, TGSI_SWIZZLE_W));
+
+ ureg_MUL(ureg, rgb,
+ ureg_scalar(ureg_src(y), TGSI_SWIZZLE_X),
+ matrow0);
+ 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));
+
+ /* rgb.a = 1; */
+ ureg_MOV(ureg, ureg_writemask(rgb, TGSI_WRITEMASK_W),
+ ureg_scalar(matrow0, TGSI_SWIZZLE_X));
+
+ 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 void *
create_fs(struct pipe_context *pipe,
unsigned fs_traits)
{
@@ -300,13 +368,15 @@ create_fs(struct pipe_context *pipe,
boolean is_solid = fs_traits & FS_SOLID_FILL;
boolean is_lingrad = fs_traits & FS_LINGRAD_FILL;
boolean is_radgrad = fs_traits & FS_RADGRAD_FILL;
+ unsigned comp_alpha = fs_traits & FS_COMPONENT_ALPHA;
+ boolean is_yuv = fs_traits & FS_YUV;
ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
if (ureg == NULL)
return 0;
- /* it has to be either a fill or a composite op */
- debug_assert(is_fill ^ is_composite);
+ /* it has to be either a fill, a composite op or a yuv conversion */
+ debug_assert((is_fill ^ is_composite) ^ is_yuv);
out = ureg_DECL_output(ureg,
TGSI_SEMANTIC_COLOR,
@@ -315,11 +385,10 @@ create_fs(struct pipe_context *pipe,
if (is_composite) {
src_sampler = ureg_DECL_sampler(ureg, 0);
src_input = ureg_DECL_fs_input(ureg,
- TGSI_SEMANTIC_POSITION,
+ TGSI_SEMANTIC_GENERIC,
0,
TGSI_INTERPOLATE_PERSPECTIVE);
- }
- if (is_fill) {
+ } else if (is_fill) {
if (is_solid)
src_input = ureg_DECL_fs_input(ureg,
TGSI_SEMANTIC_COLOR,
@@ -330,12 +399,15 @@ create_fs(struct pipe_context *pipe,
TGSI_SEMANTIC_POSITION,
0,
TGSI_INTERPOLATE_PERSPECTIVE);
+ } else {
+ debug_assert(is_yuv);
+ return create_yuv_shader(pipe, ureg);
}
if (has_mask) {
mask_sampler = ureg_DECL_sampler(ureg, 1);
mask_pos = ureg_DECL_fs_input(ureg,
- TGSI_SEMANTIC_POSITION,
+ TGSI_SEMANTIC_GENERIC,
1,
TGSI_INTERPOLATE_PERSPECTIVE);
}
@@ -370,11 +442,11 @@ create_fs(struct pipe_context *pipe,
else
src = out;
- coords = ureg_DECL_constant(ureg);
- const0124 = ureg_DECL_constant(ureg);
- matrow0 = ureg_DECL_constant(ureg);
- matrow1 = ureg_DECL_constant(ureg);
- matrow2 = ureg_DECL_constant(ureg);
+ coords = ureg_DECL_constant(ureg, 0);
+ const0124 = ureg_DECL_constant(ureg, 1);
+ matrow0 = ureg_DECL_constant(ureg, 2);
+ matrow1 = ureg_DECL_constant(ureg, 3);
+ matrow2 = ureg_DECL_constant(ureg, 4);
if (is_lingrad) {
linear_gradient(ureg, src,
@@ -396,7 +468,7 @@ create_fs(struct pipe_context *pipe,
ureg_TEX(ureg, mask,
TGSI_TEXTURE_2D, mask_pos, mask_sampler);
/* src IN mask */
- src_in_mask(ureg, out, ureg_src(src), ureg_src(mask));
+ src_in_mask(ureg, out, ureg_src(src), ureg_src(mask), comp_alpha);
ureg_release_temporary(ureg, mask);
}
@@ -405,11 +477,11 @@ create_fs(struct pipe_context *pipe,
return ureg_create_shader_and_destroy(ureg, pipe);
}
-struct xorg_shaders * xorg_shaders_create(struct exa_context *exa)
+struct xorg_shaders * xorg_shaders_create(struct xorg_renderer *r)
{
struct xorg_shaders *sc = CALLOC_STRUCT(xorg_shaders);
- sc->exa = exa;
+ sc->r = r;
sc->vs_hash = cso_hash_create();
sc->fs_hash = cso_hash_create();
@@ -436,9 +508,9 @@ cache_destroy(struct cso_context *cso,
void xorg_shaders_destroy(struct xorg_shaders *sc)
{
- cache_destroy(sc->exa->cso, sc->vs_hash,
+ cache_destroy(sc->r->cso, sc->vs_hash,
PIPE_SHADER_VERTEX);
- cache_destroy(sc->exa->cso, sc->fs_hash,
+ cache_destroy(sc->r->cso, sc->fs_hash,
PIPE_SHADER_FRAGMENT);
free(sc);
@@ -470,12 +542,12 @@ struct xorg_shader xorg_shaders_get(struct xorg_shaders *sc,
unsigned vs_traits,
unsigned fs_traits)
{
- struct xorg_shader shader = {0};
+ struct xorg_shader shader = { NULL, NULL };
void *vs, *fs;
- vs = shader_from_cache(sc->exa->ctx, PIPE_SHADER_VERTEX,
+ vs = shader_from_cache(sc->r->pipe, PIPE_SHADER_VERTEX,
sc->vs_hash, vs_traits);
- fs = shader_from_cache(sc->exa->ctx, PIPE_SHADER_FRAGMENT,
+ fs = shader_from_cache(sc->r->pipe, PIPE_SHADER_FRAGMENT,
sc->fs_hash, fs_traits);
debug_assert(vs && fs);
diff --git a/src/gallium/state_trackers/xorg/xorg_exa_tgsi.h b/src/gallium/state_trackers/xorg/xorg_exa_tgsi.h
index 1535a0c8c3..d3bfa304c2 100644
--- a/src/gallium/state_trackers/xorg/xorg_exa_tgsi.h
+++ b/src/gallium/state_trackers/xorg/xorg_exa_tgsi.h
@@ -1,7 +1,7 @@
#ifndef XORG_EXA_TGSI_H
#define XORG_EXA_TGSI_H
-#include "xorg_exa.h"
+#include "xorg_renderer.h"
enum xorg_vs_traits {
VS_COMPOSITE = 1 << 0,
@@ -9,10 +9,12 @@ enum xorg_vs_traits {
VS_SOLID_FILL = 1 << 2,
VS_LINGRAD_FILL = 1 << 3,
VS_RADGRAD_FILL = 1 << 4,
+ VS_YUV = 1 << 5,
+
+
VS_FILL = (VS_SOLID_FILL |
VS_LINGRAD_FILL |
VS_RADGRAD_FILL)
- /*VS_TRANSFORM = 1 << 5*/
};
enum xorg_fs_traits {
@@ -21,9 +23,15 @@ enum xorg_fs_traits {
FS_SOLID_FILL = 1 << 2,
FS_LINGRAD_FILL = 1 << 3,
FS_RADGRAD_FILL = 1 << 4,
+ FS_CA_FULL = 1 << 5, /* src.rgba * mask.rgba */
+ FS_CA_SRCALPHA = 1 << 6, /* src.aaaa * mask.rgba */
+ FS_YUV = 1<< 7,
+
FS_FILL = (FS_SOLID_FILL |
FS_LINGRAD_FILL |
- FS_RADGRAD_FILL)
+ FS_RADGRAD_FILL),
+ FS_COMPONENT_ALPHA = (FS_CA_FULL |
+ FS_CA_SRCALPHA)
};
struct xorg_shader {
@@ -33,7 +41,7 @@ struct xorg_shader {
struct xorg_shaders;
-struct xorg_shaders *xorg_shaders_create(struct exa_context *exa);
+struct xorg_shaders *xorg_shaders_create(struct xorg_renderer *renderer);
void xorg_shaders_destroy(struct xorg_shaders *shaders);
struct xorg_shader xorg_shaders_get(struct xorg_shaders *shaders,
diff --git a/src/gallium/state_trackers/xorg/xorg_output.c b/src/gallium/state_trackers/xorg/xorg_output.c
index 950af942f5..bfeddc5e11 100644
--- a/src/gallium/state_trackers/xorg/xorg_output.c
+++ b/src/gallium/state_trackers/xorg/xorg_output.c
@@ -42,8 +42,12 @@
#include <sys/stat.h>
#include <sys/types.h>
+#ifdef HAVE_XEXTPROTO_71
+#include <X11/extensions/dpmsconst.h>
+#else
#define DPMS_SERVER
#include <X11/extensions/dpms.h>
+#endif
#include "X11/Xatom.h"
@@ -52,66 +56,29 @@
static char *connector_enum_list[] = {
"Unknown",
"VGA",
- "DVI-I",
- "DVI-D",
- "DVI-A",
+ "DVI",
+ "DVI",
+ "DVI",
"Composite",
"SVIDEO",
"LVDS",
- "Component",
- "9-pin DIN",
- "DisplayPort",
- "HDMI Type A",
- "HDMI Type B",
+ "CTV",
+ "DIN",
+ "DP",
+ "HDMI",
+ "HDMI",
};
static void
-dpms(xf86OutputPtr output, int mode)
-{
-}
-
-static void
-save(xf86OutputPtr output)
-{
-}
-
-static void
-restore(xf86OutputPtr output)
-{
-}
-
-static int
-mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
-{
- return MODE_OK;
-}
-
-static Bool
-mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
- DisplayModePtr adjusted_mode)
-{
- return TRUE;
-}
-
-static void
-prepare(xf86OutputPtr output)
-{
- dpms(output, DPMSModeOff);
-}
-
-static void
-mode_set(xf86OutputPtr output, DisplayModePtr mode,
- DisplayModePtr adjusted_mode)
+create_resources(xf86OutputPtr output)
{
+#ifdef RANDR_12_INTERFACE
+#endif /* RANDR_12_INTERFACE */
}
static void
-commit(xf86OutputPtr output)
+dpms(xf86OutputPtr output, int mode)
{
- dpms(output, DPMSModeOn);
-
- if (output->scrn->pScreen != NULL)
- xf86_reload_cursors(output->scrn->pScreen);
}
static xf86OutputStatus
@@ -167,17 +134,10 @@ get_modes(xf86OutputPtr output)
return modes;
}
-static void
-destroy(xf86OutputPtr output)
-{
- drmModeFreeConnector(output->driver_private);
-}
-
-static void
-create_resources(xf86OutputPtr output)
+static int
+mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
{
-#ifdef RANDR_12_INTERFACE
-#endif /* RANDR_12_INTERFACE */
+ return MODE_OK;
}
#ifdef RANDR_12_INTERFACE
@@ -196,36 +156,26 @@ get_property(xf86OutputPtr output, Atom property)
}
#endif /* RANDR_13_INTERFACE */
-#ifdef RANDR_GET_CRTC_INTERFACE
-static xf86CrtcPtr
-get_crtc(xf86OutputPtr output)
+static void
+destroy(xf86OutputPtr output)
{
- return NULL;
+ drmModeFreeConnector(output->driver_private);
}
-#endif
static const xf86OutputFuncsRec output_funcs = {
.create_resources = create_resources,
- .dpms = dpms,
- .save = save,
- .restore = restore,
- .mode_valid = mode_valid,
- .mode_fixup = mode_fixup,
- .prepare = prepare,
- .mode_set = mode_set,
- .commit = commit,
- .detect = detect,
- .get_modes = get_modes,
#ifdef RANDR_12_INTERFACE
.set_property = set_property,
#endif
#ifdef RANDR_13_INTERFACE
.get_property = get_property,
#endif
+ .dpms = dpms,
+ .detect = detect,
+
+ .get_modes = get_modes,
+ .mode_valid = mode_valid,
.destroy = destroy,
-#ifdef RANDR_GET_CRTC_INTERFACE
- .get_crtc = get_crtc,
-#endif
};
void
@@ -236,7 +186,7 @@ output_init(ScrnInfoPtr pScrn)
drmModeResPtr res;
drmModeConnectorPtr drm_connector = NULL;
drmModeEncoderPtr drm_encoder = NULL;
- char *name;
+ char name[32];
int c, v, p;
res = drmModeGetResources(ms->fd);
@@ -269,7 +219,10 @@ output_init(ScrnInfoPtr pScrn)
(void)v;
#endif
- name = connector_enum_list[drm_connector->connector_type];
+ snprintf(name, 32, "%s%d",
+ connector_enum_list[drm_connector->connector_type],
+ drm_connector->connector_type_id);
+
output = xf86OutputCreate(pScrn, &output_funcs, name);
if (!output)
diff --git a/src/gallium/state_trackers/xorg/xorg_renderer.c b/src/gallium/state_trackers/xorg/xorg_renderer.c
new file mode 100644
index 0000000000..ac2c4935a5
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xorg_renderer.c
@@ -0,0 +1,907 @@
+#include "xorg_exa.h"
+#include "xorg_renderer.h"
+
+#include "xorg_exa_tgsi.h"
+
+#include "cso_cache/cso_context.h"
+#include "util/u_draw_quad.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "util/u_rect.h"
+
+#include "pipe/p_inlines.h"
+
+#include <math.h>
+
+enum AxisOrientation {
+ Y0_BOTTOM,
+ Y0_TOP
+};
+
+#define floatsEqual(x, y) (fabs(x - y) <= 0.00001f * MIN2(fabs(x), fabs(y)))
+#define floatIsZero(x) (floatsEqual((x) + 1, 1))
+
+static INLINE boolean is_affine(float *matrix)
+{
+ return floatIsZero(matrix[2]) && floatIsZero(matrix[5])
+ && floatsEqual(matrix[8], 1);
+}
+static INLINE void map_point(float *mat, float x, float y,
+ float *out_x, float *out_y)
+{
+ if (!mat) {
+ *out_x = x;
+ *out_y = y;
+ return;
+ }
+
+ *out_x = mat[0]*x + mat[3]*y + mat[6];
+ *out_y = mat[1]*x + mat[4]*y + mat[7];
+ if (!is_affine(mat)) {
+ float w = 1/(mat[2]*x + mat[5]*y + mat[8]);
+ *out_x *= w;
+ *out_y *= w;
+ }
+}
+
+static void
+renderer_init_state(struct xorg_renderer *r)
+{
+ struct pipe_depth_stencil_alpha_state dsa;
+
+ /* set common initial clip state */
+ memset(&dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
+ cso_set_depth_stencil_alpha(r->cso, &dsa);
+}
+
+
+static INLINE void
+setup_vertex0(float vertex[2][4], float x, float y,
+ float color[4])
+{
+ vertex[0][0] = x;
+ vertex[0][1] = y;
+ vertex[0][2] = 0.f; /*z*/
+ vertex[0][3] = 1.f; /*w*/
+
+ vertex[1][0] = color[0]; /*r*/
+ vertex[1][1] = color[1]; /*g*/
+ vertex[1][2] = color[2]; /*b*/
+ vertex[1][3] = color[3]; /*a*/
+}
+
+static INLINE void
+setup_vertex1(float vertex[2][4], float x, float y, float s, float t)
+{
+ vertex[0][0] = x;
+ vertex[0][1] = y;
+ vertex[0][2] = 0.f; /*z*/
+ vertex[0][3] = 1.f; /*w*/
+
+ vertex[1][0] = s; /*s*/
+ vertex[1][1] = t; /*t*/
+ vertex[1][2] = 0.f; /*r*/
+ vertex[1][3] = 1.f; /*q*/
+}
+
+static struct pipe_buffer *
+setup_vertex_data1(struct xorg_renderer *r,
+ float srcX, float srcY, float dstX, float dstY,
+ float width, float height,
+ struct pipe_texture *src, float *src_matrix)
+{
+ float s0, t0, s1, t1;
+ float pt0[2], pt1[2];
+
+ pt0[0] = srcX;
+ pt0[1] = srcY;
+ pt1[0] = (srcX + width);
+ pt1[1] = (srcY + height);
+
+ if (src_matrix) {
+ map_point(src_matrix, pt0[0], pt0[1], &pt0[0], &pt0[1]);
+ map_point(src_matrix, pt1[0], pt1[1], &pt1[0], &pt1[1]);
+ }
+
+ s0 = pt0[0] / src->width[0];
+ s1 = pt1[0] / src->width[0];
+ t0 = pt0[1] / src->height[0];
+ t1 = pt1[1] / src->height[0];
+
+ /* 1st vertex */
+ setup_vertex1(r->vertices2[0], dstX, dstY, s0, t0);
+ /* 2nd vertex */
+ setup_vertex1(r->vertices2[1], dstX + width, dstY, s1, t0);
+ /* 3rd vertex */
+ setup_vertex1(r->vertices2[2], dstX + width, dstY + height, s1, t1);
+ /* 4th vertex */
+ setup_vertex1(r->vertices2[3], dstX, dstY + height, s0, t1);
+
+ return pipe_user_buffer_create(r->pipe->screen,
+ r->vertices2,
+ sizeof(r->vertices2));
+}
+
+static struct pipe_buffer *
+setup_vertex_data_tex(struct xorg_renderer *r,
+ float x0, float y0, float x1, float y1,
+ float s0, float t0, float s1, float t1,
+ float z)
+{
+ /* 1st vertex */
+ setup_vertex1(r->vertices2[0], x0, y0, s0, t0);
+ /* 2nd vertex */
+ setup_vertex1(r->vertices2[1], x1, y0, s1, t0);
+ /* 3rd vertex */
+ setup_vertex1(r->vertices2[2], x1, y1, s1, t1);
+ /* 4th vertex */
+ setup_vertex1(r->vertices2[3], x0, y1, s0, t1);
+
+ return pipe_user_buffer_create(r->pipe->screen,
+ r->vertices2,
+ sizeof(r->vertices2));
+}
+
+static INLINE void
+setup_vertex2(float vertex[3][4], float x, float y,
+ float s0, float t0, float s1, float t1)
+{
+ vertex[0][0] = x;
+ vertex[0][1] = y;
+ vertex[0][2] = 0.f; /*z*/
+ vertex[0][3] = 1.f; /*w*/
+
+ vertex[1][0] = s0; /*s*/
+ vertex[1][1] = t0; /*t*/
+ vertex[1][2] = 0.f; /*r*/
+ vertex[1][3] = 1.f; /*q*/
+
+ vertex[2][0] = s1; /*s*/
+ vertex[2][1] = t1; /*t*/
+ vertex[2][2] = 0.f; /*r*/
+ vertex[2][3] = 1.f; /*q*/
+}
+
+static struct pipe_buffer *
+setup_vertex_data2(struct xorg_renderer *r,
+ float srcX, float srcY, float maskX, float maskY,
+ float dstX, float dstY, float width, float height,
+ struct pipe_texture *src,
+ struct pipe_texture *mask,
+ float *src_matrix, float *mask_matrix)
+{
+ float src_s0, src_t0, src_s1, src_t1;
+ float mask_s0, mask_t0, mask_s1, mask_t1;
+ float spt0[2], spt1[2];
+ float mpt0[2], mpt1[2];
+
+ spt0[0] = srcX;
+ spt0[1] = srcY;
+ spt1[0] = srcX + width;
+ spt1[1] = srcY + height;
+
+ mpt0[0] = maskX;
+ mpt0[1] = maskY;
+ mpt1[0] = maskX + width;
+ mpt1[1] = maskY + height;
+
+ if (src_matrix) {
+ map_point(src_matrix, spt0[0], spt0[1], &spt0[0], &spt0[1]);
+ map_point(src_matrix, spt1[0], spt1[1], &spt1[0], &spt1[1]);
+ }
+
+ if (mask_matrix) {
+ map_point(mask_matrix, mpt0[0], mpt0[1], &mpt0[0], &mpt0[1]);
+ map_point(mask_matrix, mpt1[0], mpt1[1], &mpt1[0], &mpt1[1]);
+ }
+
+ src_s0 = spt0[0] / src->width[0];
+ src_t0 = spt0[1] / src->height[0];
+ src_s1 = spt1[0] / src->width[0];
+ src_t1 = spt1[1] / src->height[0];
+
+ mask_s0 = mpt0[0] / mask->width[0];
+ mask_t0 = mpt0[1] / mask->height[0];
+ mask_s1 = mpt1[0] / mask->width[0];
+ mask_t1 = mpt1[1] / mask->height[0];
+
+ /* 1st vertex */
+ setup_vertex2(r->vertices3[0], dstX, dstY,
+ src_s0, src_t0, mask_s0, mask_t0);
+ /* 2nd vertex */
+ setup_vertex2(r->vertices3[1], dstX + width, dstY,
+ src_s1, src_t0, mask_s1, mask_t0);
+ /* 3rd vertex */
+ setup_vertex2(r->vertices3[2], dstX + width, dstY + height,
+ src_s1, src_t1, mask_s1, mask_t1);
+ /* 4th vertex */
+ setup_vertex2(r->vertices3[3], dstX, dstY + height,
+ src_s0, src_t1, mask_s0, mask_t1);
+
+
+ return pipe_user_buffer_create(r->pipe->screen,
+ r->vertices3,
+ sizeof(r->vertices3));
+}
+
+static struct pipe_buffer *
+setup_vertex_data_yuv(struct xorg_renderer *r,
+ float srcX, float srcY, float srcW, float srcH,
+ float dstX, float dstY, float dstW, float dstH,
+ struct pipe_texture **tex)
+{
+ float s0, t0, s1, t1;
+ float spt0[2], spt1[2];
+
+ spt0[0] = srcX;
+ spt0[1] = srcY;
+ spt1[0] = srcX + srcW;
+ spt1[1] = srcY + srcH;
+
+ s0 = spt0[0] / tex[0]->width[0];
+ t0 = spt0[1] / tex[0]->height[0];
+ s1 = spt1[0] / tex[0]->width[0];
+ t1 = spt1[1] / tex[0]->height[0];
+
+ /* 1st vertex */
+ setup_vertex1(r->vertices2[0], dstX, dstY, s0, t0);
+ /* 2nd vertex */
+ setup_vertex1(r->vertices2[1], dstX + dstW, dstY,
+ s1, t0);
+ /* 3rd vertex */
+ setup_vertex1(r->vertices2[2], dstX + dstW, dstY + dstH,
+ s1, t1);
+ /* 4th vertex */
+ setup_vertex1(r->vertices2[3], dstX, dstY + dstH,
+ s0, t1);
+
+
+ return pipe_user_buffer_create(r->pipe->screen,
+ r->vertices2,
+ sizeof(r->vertices2));
+}
+
+
+
+static void
+set_viewport(struct xorg_renderer *r, int width, int height,
+ enum AxisOrientation orientation)
+{
+ struct pipe_viewport_state viewport;
+ float y_scale = (orientation == Y0_BOTTOM) ? -2.f : 2.f;
+
+ viewport.scale[0] = width / 2.f;
+ viewport.scale[1] = height / y_scale;
+ viewport.scale[2] = 1.0;
+ viewport.scale[3] = 1.0;
+ viewport.translate[0] = width / 2.f;
+ viewport.translate[1] = height / 2.f;
+ viewport.translate[2] = 0.0;
+ viewport.translate[3] = 0.0;
+
+ cso_set_viewport(r->cso, &viewport);
+}
+
+
+
+struct xorg_renderer * renderer_create(struct pipe_context *pipe)
+{
+ struct xorg_renderer *renderer = CALLOC_STRUCT(xorg_renderer);
+
+ renderer->pipe = pipe;
+ renderer->cso = cso_create_context(pipe);
+ renderer->shaders = xorg_shaders_create(renderer);
+
+ renderer_init_state(renderer);
+
+ return renderer;
+}
+
+void renderer_destroy(struct xorg_renderer *r)
+{
+ struct pipe_constant_buffer *vsbuf = &r->vs_const_buffer;
+ struct pipe_constant_buffer *fsbuf = &r->fs_const_buffer;
+
+ if (vsbuf && vsbuf->buffer)
+ pipe_buffer_reference(&vsbuf->buffer, NULL);
+
+ if (fsbuf && fsbuf->buffer)
+ pipe_buffer_reference(&fsbuf->buffer, NULL);
+
+ if (r->shaders) {
+ xorg_shaders_destroy(r->shaders);
+ r->shaders = NULL;
+ }
+
+ if (r->cso) {
+ cso_release_all(r->cso);
+ cso_destroy_context(r->cso);
+ r->cso = NULL;
+ }
+}
+
+void renderer_bind_framebuffer(struct xorg_renderer *r,
+ struct exa_pixmap_priv *priv)
+{
+ unsigned i;
+ struct pipe_framebuffer_state state;
+ struct pipe_surface *surface = xorg_gpu_surface(r->pipe->screen, priv);
+ memset(&state, 0, sizeof(struct pipe_framebuffer_state));
+
+ state.width = priv->tex->width[0];
+ state.height = priv->tex->height[0];
+
+ state.nr_cbufs = 1;
+ state.cbufs[0] = surface;
+ for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i)
+ state.cbufs[i] = 0;
+
+ /* currently we don't use depth/stencil */
+ state.zsbuf = 0;
+
+ cso_set_framebuffer(r->cso, &state);
+
+ /* we do fire and forget for the framebuffer, this is the forget part */
+ pipe_surface_reference(&surface, NULL);
+}
+
+void renderer_bind_viewport(struct xorg_renderer *r,
+ struct exa_pixmap_priv *dst)
+{
+ int width = dst->tex->width[0];
+ int height = dst->tex->height[0];
+
+ /*debug_printf("Bind viewport (%d, %d)\n", width, height);*/
+
+ set_viewport(r, width, height, Y0_TOP);
+}
+
+void renderer_bind_rasterizer(struct xorg_renderer *r)
+{
+ struct pipe_rasterizer_state raster;
+
+ /* XXX: move to renderer_init_state? */
+ memset(&raster, 0, sizeof(struct pipe_rasterizer_state));
+ raster.gl_rasterization_rules = 1;
+ cso_set_rasterizer(r->cso, &raster);
+}
+
+void renderer_set_constants(struct xorg_renderer *r,
+ int shader_type,
+ const float *params,
+ int param_bytes)
+{
+ struct pipe_constant_buffer *cbuf =
+ (shader_type == PIPE_SHADER_VERTEX) ? &r->vs_const_buffer :
+ &r->fs_const_buffer;
+
+ pipe_buffer_reference(&cbuf->buffer, NULL);
+ cbuf->buffer = pipe_buffer_create(r->pipe->screen, 16,
+ PIPE_BUFFER_USAGE_CONSTANT,
+ param_bytes);
+
+ if (cbuf->buffer) {
+ pipe_buffer_write(r->pipe->screen, cbuf->buffer,
+ 0, param_bytes, params);
+ }
+ r->pipe->set_constant_buffer(r->pipe, shader_type, 0, cbuf);
+}
+
+static void
+setup_vs_constant_buffer(struct xorg_renderer *r,
+ int width, int height)
+{
+ const int param_bytes = 8 * sizeof(float);
+ float vs_consts[8] = {
+ 2.f/width, 2.f/height, 1, 1,
+ -1, -1, 0, 0
+ };
+ renderer_set_constants(r, PIPE_SHADER_VERTEX,
+ vs_consts, param_bytes);
+}
+
+static void
+setup_fs_constant_buffer(struct xorg_renderer *r)
+{
+ const int param_bytes = 4 * sizeof(float);
+ const float fs_consts[8] = {
+ 0, 0, 0, 1,
+ };
+ renderer_set_constants(r, PIPE_SHADER_FRAGMENT,
+ fs_consts, param_bytes);
+}
+
+static INLINE void shift_rectx(float coords[4],
+ const float *bounds,
+ const float shift)
+{
+ coords[0] += shift;
+ coords[2] -= shift;
+ if (bounds) {
+ coords[2] = MIN2(coords[2], bounds[2]);
+ /* bound x/y + width/height */
+ if ((coords[0] + coords[2]) > (bounds[0] + bounds[2])) {
+ coords[2] = (bounds[0] + bounds[2]) - coords[0];
+ }
+ }
+}
+
+static INLINE void shift_recty(float coords[4],
+ const float *bounds,
+ const float shift)
+{
+ coords[1] += shift;
+ coords[3] -= shift;
+ if (bounds) {
+ coords[3] = MIN2(coords[3], bounds[3]);
+ if ((coords[1] + coords[3]) > (bounds[1] + bounds[3])) {
+ coords[3] = (bounds[1] + bounds[3]) - coords[1];
+ }
+ }
+}
+
+static INLINE void bound_rect(float coords[4],
+ const float bounds[4],
+ float shift[4])
+{
+ /* if outside the bounds */
+ if (coords[0] > (bounds[0] + bounds[2]) ||
+ coords[1] > (bounds[1] + bounds[3]) ||
+ (coords[0] + coords[2]) < bounds[0] ||
+ (coords[1] + coords[3]) < bounds[1]) {
+ coords[0] = 0.f;
+ coords[1] = 0.f;
+ coords[2] = 0.f;
+ coords[3] = 0.f;
+ shift[0] = 0.f;
+ shift[1] = 0.f;
+ return;
+ }
+
+ /* bound x */
+ if (coords[0] < bounds[0]) {
+ shift[0] = bounds[0] - coords[0];
+ coords[2] -= shift[0];
+ coords[0] = bounds[0];
+ } else
+ shift[0] = 0.f;
+
+ /* bound y */
+ if (coords[1] < bounds[1]) {
+ shift[1] = bounds[1] - coords[1];
+ coords[3] -= shift[1];
+ coords[1] = bounds[1];
+ } else
+ shift[1] = 0.f;
+
+ shift[2] = bounds[2] - coords[2];
+ shift[3] = bounds[3] - coords[3];
+ /* bound width/height */
+ coords[2] = MIN2(coords[2], bounds[2]);
+ coords[3] = MIN2(coords[3], bounds[3]);
+
+ /* bound x/y + width/height */
+ if ((coords[0] + coords[2]) > (bounds[0] + bounds[2])) {
+ coords[2] = (bounds[0] + bounds[2]) - coords[0];
+ }
+ if ((coords[1] + coords[3]) > (bounds[1] + bounds[3])) {
+ coords[3] = (bounds[1] + bounds[3]) - coords[1];
+ }
+
+ /* if outside the bounds */
+ if ((coords[0] + coords[2]) < bounds[0] ||
+ (coords[1] + coords[3]) < bounds[1]) {
+ coords[0] = 0.f;
+ coords[1] = 0.f;
+ coords[2] = 0.f;
+ coords[3] = 0.f;
+ return;
+ }
+}
+
+static INLINE void sync_size(float *src_loc, float *dst_loc)
+{
+ src_loc[2] = MIN2(src_loc[2], dst_loc[2]);
+ src_loc[3] = MIN2(src_loc[3], dst_loc[3]);
+ dst_loc[2] = src_loc[2];
+ dst_loc[3] = src_loc[3];
+}
+
+static void renderer_copy_texture(struct xorg_renderer *r,
+ struct pipe_texture *src,
+ float sx1, float sy1,
+ float sx2, float sy2,
+ struct pipe_texture *dst,
+ float dx1, float dy1,
+ float dx2, float dy2)
+{
+ struct pipe_context *pipe = r->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_buffer *buf;
+ struct pipe_surface *dst_surf = screen->get_tex_surface(
+ screen, dst, 0, 0, 0,
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+ struct pipe_framebuffer_state fb;
+ float s0, t0, s1, t1;
+ struct xorg_shader shader;
+
+ assert(src->width[0] != 0);
+ assert(src->height[0] != 0);
+ assert(dst->width[0] != 0);
+ assert(dst->height[0] != 0);
+
+#if 1
+ s0 = sx1 / src->width[0];
+ s1 = sx2 / src->width[0];
+ t0 = sy1 / src->height[0];
+ t1 = sy2 / src->height[0];
+#else
+ s0 = 0;
+ s1 = 1;
+ t0 = 0;
+ t1 = 1;
+#endif
+
+#if 0
+ debug_printf("copy texture src=[%f, %f, %f, %f], dst=[%f, %f, %f, %f], tex=[%f, %f, %f, %f]\n",
+ sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2,
+ s0, t0, s1, t1);
+#endif
+
+ assert(screen->is_format_supported(screen, dst_surf->format,
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_RENDER_TARGET,
+ 0));
+
+ /* save state (restored below) */
+ cso_save_blend(r->cso);
+ cso_save_samplers(r->cso);
+ cso_save_sampler_textures(r->cso);
+ cso_save_framebuffer(r->cso);
+ cso_save_fragment_shader(r->cso);
+ cso_save_vertex_shader(r->cso);
+
+ cso_save_viewport(r->cso);
+
+
+ /* set misc state we care about */
+ {
+ struct pipe_blend_state blend;
+ memset(&blend, 0, sizeof(blend));
+ blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ blend.colormask = PIPE_MASK_RGBA;
+ cso_set_blend(r->cso, &blend);
+ }
+
+ /* sampler */
+ {
+ struct pipe_sampler_state sampler;
+ memset(&sampler, 0, sizeof(sampler));
+ sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
+ sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
+ sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
+ sampler.normalized_coords = 1;
+ cso_single_sampler(r->cso, 0, &sampler);
+ cso_single_sampler_done(r->cso);
+ }
+
+ set_viewport(r, dst_surf->width, dst_surf->height, Y0_TOP);
+
+ /* texture */
+ cso_set_sampler_textures(r->cso, 1, &src);
+
+ renderer_bind_rasterizer(r);
+
+ /* shaders */
+ shader = xorg_shaders_get(r->shaders,
+ VS_COMPOSITE,
+ FS_COMPOSITE);
+ cso_set_vertex_shader_handle(r->cso, shader.vs);
+ cso_set_fragment_shader_handle(r->cso, shader.fs);
+
+ /* drawing dest */
+ memset(&fb, 0, sizeof(fb));
+ fb.width = dst_surf->width;
+ fb.height = dst_surf->height;
+ fb.nr_cbufs = 1;
+ fb.cbufs[0] = dst_surf;
+ {
+ int i;
+ for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i)
+ fb.cbufs[i] = 0;
+ }
+ cso_set_framebuffer(r->cso, &fb);
+ setup_vs_constant_buffer(r, fb.width, fb.height);
+ setup_fs_constant_buffer(r);
+
+ /* draw quad */
+ buf = setup_vertex_data_tex(r,
+ dx1, dy1,
+ dx2, dy2,
+ s0, t0, s1, t1,
+ 0.0f);
+
+ if (buf) {
+ util_draw_vertex_buffer(r->pipe, buf, 0,
+ PIPE_PRIM_TRIANGLE_FAN,
+ 4, /* verts */
+ 2); /* attribs/vert */
+
+ pipe_buffer_reference(&buf, NULL);
+ }
+
+ /* restore state we changed */
+ cso_restore_blend(r->cso);
+ cso_restore_samplers(r->cso);
+ cso_restore_sampler_textures(r->cso);
+ cso_restore_framebuffer(r->cso);
+ cso_restore_vertex_shader(r->cso);
+ cso_restore_fragment_shader(r->cso);
+ cso_restore_viewport(r->cso);
+
+ pipe_surface_reference(&dst_surf, NULL);
+}
+
+static struct pipe_texture *
+create_sampler_texture(struct xorg_renderer *r,
+ struct pipe_texture *src)
+{
+ enum pipe_format format;
+ struct pipe_context *pipe = r->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_texture *pt;
+ struct pipe_texture templ;
+
+ pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
+
+ /* the coming in texture should already have that invariance */
+ debug_assert(screen->is_format_supported(screen, src->format,
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_SAMPLER, 0));
+
+ format = src->format;
+
+ memset(&templ, 0, sizeof(templ));
+ templ.target = PIPE_TEXTURE_2D;
+ templ.format = format;
+ templ.last_level = 0;
+ templ.width[0] = src->width[0];
+ templ.height[0] = src->height[0];
+ templ.depth[0] = 1;
+ pf_get_block(format, &templ.block);
+ templ.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER;
+
+ pt = screen->texture_create(screen, &templ);
+
+ debug_assert(!pt || pipe_is_referenced(&pt->reference));
+
+ if (!pt)
+ return NULL;
+
+ {
+ /* copy source framebuffer surface into texture */
+ struct pipe_surface *ps_read = screen->get_tex_surface(
+ screen, src, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ);
+ struct pipe_surface *ps_tex = screen->get_tex_surface(
+ screen, pt, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE );
+ if (pipe->surface_copy) {
+ pipe->surface_copy(pipe,
+ ps_tex, /* dest */
+ 0, 0, /* destx/y */
+ ps_read,
+ 0, 0, src->width[0], src->height[0]);
+ } else {
+ util_surface_copy(pipe, FALSE,
+ ps_tex, /* dest */
+ 0, 0, /* destx/y */
+ ps_read,
+ 0, 0, src->width[0], src->height[0]);
+ }
+ pipe_surface_reference(&ps_read, NULL);
+ pipe_surface_reference(&ps_tex, NULL);
+ }
+
+ return pt;
+}
+
+
+void renderer_copy_pixmap(struct xorg_renderer *r,
+ struct exa_pixmap_priv *dst_priv, int dx, int dy,
+ struct exa_pixmap_priv *src_priv, int sx, int sy,
+ int width, int height)
+{
+ float dst_loc[4], src_loc[4];
+ float dst_bounds[4], src_bounds[4];
+ float src_shift[4], dst_shift[4], shift[4];
+ struct pipe_texture *dst = dst_priv->tex;
+ struct pipe_texture *src = src_priv->tex;
+
+ if (r->pipe->is_texture_referenced(r->pipe, src, 0, 0) &
+ PIPE_REFERENCED_FOR_WRITE)
+ r->pipe->flush(r->pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
+
+ dst_loc[0] = dx;
+ dst_loc[1] = dy;
+ dst_loc[2] = width;
+ dst_loc[3] = height;
+ dst_bounds[0] = 0.f;
+ dst_bounds[1] = 0.f;
+ dst_bounds[2] = dst->width[0];
+ dst_bounds[3] = dst->height[0];
+
+ src_loc[0] = sx;
+ src_loc[1] = sy;
+ src_loc[2] = width;
+ src_loc[3] = height;
+ src_bounds[0] = 0.f;
+ src_bounds[1] = 0.f;
+ src_bounds[2] = src->width[0];
+ src_bounds[3] = src->height[0];
+
+ bound_rect(src_loc, src_bounds, src_shift);
+ bound_rect(dst_loc, dst_bounds, dst_shift);
+ shift[0] = src_shift[0] - dst_shift[0];
+ shift[1] = src_shift[1] - dst_shift[1];
+
+ if (shift[0] < 0)
+ shift_rectx(src_loc, src_bounds, -shift[0]);
+ else
+ shift_rectx(dst_loc, dst_bounds, shift[0]);
+
+ if (shift[1] < 0)
+ shift_recty(src_loc, src_bounds, -shift[1]);
+ else
+ shift_recty(dst_loc, dst_bounds, shift[1]);
+
+ sync_size(src_loc, dst_loc);
+
+ if (src_loc[2] >= 0 && src_loc[3] >= 0 &&
+ dst_loc[2] >= 0 && dst_loc[3] >= 0) {
+ struct pipe_texture *temp_src = src;
+
+ if (src == dst)
+ temp_src = create_sampler_texture(r, src);
+
+ renderer_copy_texture(r,
+ temp_src,
+ src_loc[0],
+ src_loc[1],
+ src_loc[0] + src_loc[2],
+ src_loc[1] + src_loc[3],
+ dst,
+ dst_loc[0],
+ dst_loc[1],
+ dst_loc[0] + dst_loc[2],
+ dst_loc[1] + dst_loc[3]);
+
+ if (src == dst)
+ pipe_texture_reference(&temp_src, NULL);
+ }
+}
+
+void renderer_draw_solid_rect(struct xorg_renderer *r,
+ int x0, int y0,
+ int x1, int y1,
+ float *color)
+{
+ struct pipe_context *pipe = r->pipe;
+ struct pipe_buffer *buf = 0;
+
+ /*
+ 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]);*/
+ /* 1st vertex */
+ setup_vertex0(r->vertices2[0], x0, y0, color);
+ /* 2nd vertex */
+ setup_vertex0(r->vertices2[1], x1, y0, color);
+ /* 3rd vertex */
+ setup_vertex0(r->vertices2[2], x1, y1, color);
+ /* 4th vertex */
+ setup_vertex0(r->vertices2[3], x0, y1, color);
+
+ buf = pipe_user_buffer_create(pipe->screen,
+ r->vertices2,
+ sizeof(r->vertices2));
+
+
+ if (buf) {
+ util_draw_vertex_buffer(pipe, buf, 0,
+ PIPE_PRIM_TRIANGLE_FAN,
+ 4, /* verts */
+ 2); /* attribs/vert */
+
+ pipe_buffer_reference(&buf, NULL);
+ }
+}
+
+void renderer_draw_textures(struct xorg_renderer *r,
+ int *pos,
+ int width, int height,
+ struct pipe_texture **textures,
+ int num_textures,
+ float *src_matrix, float *mask_matrix)
+{
+ struct pipe_context *pipe = r->pipe;
+ struct pipe_buffer *buf = 0;
+
+#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(num_textures) {
+ case 1:
+ buf = setup_vertex_data1(r,
+ pos[0], pos[1], /* src */
+ pos[4], pos[5], /* dst */
+ width, height,
+ textures[0], src_matrix);
+ break;
+ case 2:
+ buf = setup_vertex_data2(r,
+ pos[0], pos[1], /* src */
+ pos[2], pos[3], /* mask */
+ pos[4], pos[5], /* dst */
+ width, height,
+ textures[0], textures[1],
+ src_matrix, mask_matrix);
+ break;
+ case 3:
+ default:
+ debug_assert(!"Unsupported number of textures");
+ break;
+ }
+
+ if (buf) {
+ int num_attribs = 1; /*pos*/
+ num_attribs += num_textures;
+
+ util_draw_vertex_buffer(pipe, buf, 0,
+ PIPE_PRIM_TRIANGLE_FAN,
+ 4, /* verts */
+ num_attribs); /* attribs/vert */
+
+ pipe_buffer_reference(&buf, NULL);
+ }
+}
+
+void renderer_draw_yuv(struct xorg_renderer *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 pipe_texture **textures)
+{
+ struct pipe_context *pipe = r->pipe;
+ struct pipe_buffer *buf = 0;
+
+ buf = setup_vertex_data_yuv(r,
+ src_x, src_y, src_w, src_h,
+ dst_x, dst_y, dst_w, dst_h,
+ textures);
+
+ if (buf) {
+ const int num_attribs = 2; /*pos + tex coord*/
+
+ util_draw_vertex_buffer(pipe, buf, 0,
+ PIPE_PRIM_TRIANGLE_FAN,
+ 4, /* verts */
+ num_attribs); /* attribs/vert */
+
+ pipe_buffer_reference(&buf, NULL);
+ }
+}
diff --git a/src/gallium/state_trackers/xorg/xorg_renderer.h b/src/gallium/state_trackers/xorg/xorg_renderer.h
new file mode 100644
index 0000000000..34c9ee4541
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xorg_renderer.h
@@ -0,0 +1,60 @@
+#ifndef XORG_RENDERER_H
+#define XORG_RENDERER_H
+
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+
+struct xorg_shaders;
+struct exa_pixmap_priv;
+
+struct xorg_renderer {
+ struct pipe_context *pipe;
+
+ struct cso_context *cso;
+ struct xorg_shaders *shaders;
+
+ struct pipe_constant_buffer vs_const_buffer;
+ struct pipe_constant_buffer fs_const_buffer;
+
+ /* we should combine these three */
+ float vertices2[4][2][4];
+ float vertices3[4][3][4];
+};
+
+struct xorg_renderer *renderer_create(struct pipe_context *pipe);
+void renderer_destroy(struct xorg_renderer *renderer);
+
+void renderer_bind_framebuffer(struct xorg_renderer *r,
+ struct exa_pixmap_priv *priv);
+void renderer_bind_viewport(struct xorg_renderer *r,
+ struct exa_pixmap_priv *dst);
+void renderer_bind_rasterizer(struct xorg_renderer *r);
+void renderer_set_constants(struct xorg_renderer *r,
+ int shader_type,
+ const float *buffer,
+ int size);
+void renderer_copy_pixmap(struct xorg_renderer *r,
+ struct exa_pixmap_priv *dst_priv, int dx, int dy,
+ struct exa_pixmap_priv *src_priv, int sx, int sy,
+ int width, int height);
+
+void renderer_draw_solid_rect(struct xorg_renderer *r,
+ int x0, int y0,
+ int x1, int y1,
+ float *color);
+
+void renderer_draw_textures(struct xorg_renderer *r,
+ int *pos,
+ int width, int height,
+ struct pipe_texture **textures,
+ int num_textures,
+ float *src_matrix,
+ float *mask_matrix);
+
+void renderer_draw_yuv(struct xorg_renderer *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 pipe_texture **textures);
+
+
+#endif
diff --git a/src/gallium/state_trackers/xorg/xorg_tracker.h b/src/gallium/state_trackers/xorg/xorg_tracker.h
index b1ab783a15..6130cf6621 100644
--- a/src/gallium/state_trackers/xorg/xorg_tracker.h
+++ b/src/gallium/state_trackers/xorg/xorg_tracker.h
@@ -51,6 +51,8 @@
#define DRV_ERROR(msg) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, msg);
+struct exa_context;
+
typedef struct
{
int lastInstance;
@@ -90,10 +92,12 @@ typedef struct _modesettingRec
struct pipe_context *ctx;
boolean d_depth_bits_last;
boolean ds_depth_bits_last;
+ struct pipe_texture *root_texture;
/* exa */
- void *exa;
+ struct exa_context *exa;
Bool noEvict;
+ Bool debug_fallback;
#ifdef DRM_MODE_FEATURE_DIRTYFB
DamagePtr damage;
@@ -118,6 +122,14 @@ xorg_exa_set_displayed_usage(PixmapPtr pPixmap);
int
xorg_exa_set_shared_usage(PixmapPtr pPixmap);
+Bool
+xorg_exa_set_texture(PixmapPtr pPixmap, struct pipe_texture *tex);
+
+struct pipe_texture *
+xorg_exa_create_root_texture(ScrnInfoPtr pScrn,
+ int width, int height,
+ int depth, int bpp);
+
void *
xorg_exa_init(ScrnInfoPtr pScrn);
@@ -151,5 +163,11 @@ crtc_cursor_destroy(xf86CrtcPtr crtc);
void
output_init(ScrnInfoPtr pScrn);
+/***********************************************************************
+ * xorg_xv.c
+ */
+void
+xorg_init_video(ScreenPtr pScreen);
+
#endif /* _XORG_TRACKER_H_ */
diff --git a/src/gallium/state_trackers/xorg/xorg_xv.c b/src/gallium/state_trackers/xorg/xorg_xv.c
new file mode 100644
index 0000000000..2b935c0f73
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xorg_xv.c
@@ -0,0 +1,719 @@
+#include "xorg_tracker.h"
+
+#include <xf86xv.h>
+#include <X11/extensions/Xv.h>
+#include <fourcc.h>
+
+#include "xorg_exa.h"
+#include "xorg_renderer.h"
+#include "xorg_exa_tgsi.h"
+
+#include "cso_cache/cso_context.h"
+
+#include "pipe/p_screen.h"
+#include "pipe/p_inlines.h"
+
+/*XXX get these from pipe's texture limits */
+#define IMAGE_MAX_WIDTH 2048
+#define IMAGE_MAX_HEIGHT 2048
+
+#define RES_720P_X 1280
+#define RES_720P_Y 720
+
+
+/* The ITU-R BT.601 conversion matrix for SDTV. */
+/* original, matrix, but we transpose it to
+ * make the shader easier
+static const float bt_601[] = {
+ 1.0, 0.0, 1.4075, ,
+ 1.0, -0.3455, -0.7169, 0,
+ 1.0, 1.7790, 0., 0,
+};*/
+static const float bt_601[] = {
+ 1.0, 1.0, 1.0, 0.5,
+ 0.0, -0.3455, 1.7790, 0,
+ 1.4075, -0.7169, 0., 0,
+};
+
+/* The ITU-R BT.709 conversion matrix for HDTV. */
+/* original, but we transpose to make the conversion
+ * in the shader easier
+static const float bt_709[] = {
+ 1.0, 0.0, 1.581, 0,
+ 1.0, -0.1881, -0.47, 0,
+ 1.0, 1.8629, 0., 0,
+};*/
+static const float bt_709[] = {
+ 1.0, 1.0, 1.0, 0.5,
+ 0.0, -0.1881, 1.8629, 0,
+ 1.581,-0.47 , 0.0, 0,
+};
+
+#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
+
+static Atom xvBrightness, xvContrast;
+
+#define NUM_TEXTURED_ATTRIBUTES 2
+static XF86AttributeRec TexturedAttributes[NUM_TEXTURED_ATTRIBUTES] = {
+ {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"},
+ {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"}
+};
+
+#define NUM_FORMATS 3
+static XF86VideoFormatRec Formats[NUM_FORMATS] = {
+ {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
+};
+
+static XF86VideoEncodingRec DummyEncoding[1] = {
+ {
+ 0,
+ "XV_IMAGE",
+ IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT,
+ {1, 1}
+ }
+};
+
+#define NUM_IMAGES 2
+static XF86ImageRec Images[NUM_IMAGES] = {
+ XVIMAGE_UYVY,
+ XVIMAGE_YUY2,
+};
+
+struct xorg_xv_port_priv {
+ struct xorg_renderer *r;
+
+ RegionRec clip;
+
+ int brightness;
+ int contrast;
+
+ int current_set;
+ /* juggle two sets of seperate Y, U and V
+ * textures */
+ struct pipe_texture *yuv[2][3];
+};
+
+
+static void
+stop_video(ScrnInfoPtr pScrn, pointer data, Bool shutdown)
+{
+ struct xorg_xv_port_priv *priv = (struct xorg_xv_port_priv *)data;
+
+ REGION_EMPTY(pScrn->pScreen, &priv->clip);
+}
+
+static int
+set_port_attribute(ScrnInfoPtr pScrn,
+ Atom attribute, INT32 value, pointer data)
+{
+ struct xorg_xv_port_priv *priv = (struct xorg_xv_port_priv *)data;
+
+ if (attribute == xvBrightness) {
+ if ((value < -128) || (value > 127))
+ return BadValue;
+ priv->brightness = value;
+ } else if (attribute == xvContrast) {
+ if ((value < 0) || (value > 255))
+ return BadValue;
+ priv->contrast = value;
+ } else
+ return BadMatch;
+
+ return Success;
+}
+
+static int
+get_port_attribute(ScrnInfoPtr pScrn,
+ Atom attribute, INT32 * value, pointer data)
+{
+ struct xorg_xv_port_priv *priv = (struct xorg_xv_port_priv *)data;
+
+ if (attribute == xvBrightness)
+ *value = priv->brightness;
+ else if (attribute == xvContrast)
+ *value = priv->contrast;
+ else
+ return BadMatch;
+
+ return Success;
+}
+
+static void
+query_best_size(ScrnInfoPtr pScrn,
+ Bool motion,
+ short vid_w, short vid_h,
+ short drw_w, short drw_h,
+ unsigned int *p_w, unsigned int *p_h, pointer data)
+{
+ if (vid_w > (drw_w << 1))
+ drw_w = vid_w >> 1;
+ if (vid_h > (drw_h << 1))
+ drw_h = vid_h >> 1;
+
+ *p_w = drw_w;
+ *p_h = drw_h;
+}
+
+static INLINE struct pipe_texture *
+create_component_texture(struct pipe_context *pipe,
+ int width, int height)
+{
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_texture *tex = 0;
+ struct pipe_texture templ;
+
+ memset(&templ, 0, sizeof(templ));
+ templ.target = PIPE_TEXTURE_2D;
+ templ.format = PIPE_FORMAT_L8_UNORM;
+ templ.last_level = 0;
+ templ.width[0] = width;
+ templ.height[0] = height;
+ templ.depth[0] = 1;
+ pf_get_block(PIPE_FORMAT_L8_UNORM, &templ.block);
+ templ.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER;
+
+ tex = screen->texture_create(screen, &templ);
+
+ return tex;
+}
+
+static int
+check_yuv_textures(struct xorg_xv_port_priv *priv, int width, int height)
+{
+ struct pipe_texture **dst = priv->yuv[priv->current_set];
+ if (!dst[0] ||
+ dst[0]->width[0] != width ||
+ dst[0]->height[0] != height) {
+ pipe_texture_reference(&dst[0], NULL);
+ }
+ if (!dst[1] ||
+ dst[1]->width[0] != width ||
+ dst[1]->height[0] != height) {
+ pipe_texture_reference(&dst[1], NULL);
+ }
+ if (!dst[2] ||
+ dst[2]->width[0] != width ||
+ dst[2]->height[0] != height) {
+ pipe_texture_reference(&dst[2], NULL);
+ }
+
+ if (!dst[0])
+ dst[0] = create_component_texture(priv->r->pipe, width, height);
+
+ if (!dst[1])
+ dst[1] = create_component_texture(priv->r->pipe, width, height);
+
+ if (!dst[2])
+ dst[2] = create_component_texture(priv->r->pipe, width, height);
+
+ if (!dst[0] || !dst[1] || !dst[2])
+ return BadAlloc;
+
+ return Success;
+}
+
+static void
+copy_packed_data(ScrnInfoPtr pScrn,
+ struct xorg_xv_port_priv *port,
+ int id,
+ unsigned char *buf,
+ int srcPitch,
+ int left,
+ int top,
+ int w, int h)
+{
+ unsigned char *src;
+ int i, j;
+ struct pipe_texture **dst = port->yuv[port->current_set];
+ struct pipe_transfer *ytrans, *utrans, *vtrans;
+ struct pipe_screen *screen = port->r->pipe->screen;
+ char *ymap, *vmap, *umap;
+ unsigned char y1, y2, u, v;
+ int yidx, uidx, vidx;
+ int y_array_size = w * h;
+
+ src = buf + (top * srcPitch) + (left << 1);
+
+ ytrans = screen->get_tex_transfer(screen, dst[0],
+ 0, 0, 0,
+ PIPE_TRANSFER_WRITE,
+ left, top, w, h);
+ utrans = screen->get_tex_transfer(screen, dst[1],
+ 0, 0, 0,
+ PIPE_TRANSFER_WRITE,
+ left, top, w, h);
+ vtrans = screen->get_tex_transfer(screen, dst[2],
+ 0, 0, 0,
+ PIPE_TRANSFER_WRITE,
+ left, top, w, h);
+
+ ymap = (char*)screen->transfer_map(screen, ytrans);
+ umap = (char*)screen->transfer_map(screen, utrans);
+ vmap = (char*)screen->transfer_map(screen, vtrans);
+
+ yidx = uidx = vidx = 0;
+
+ switch (id) {
+ case FOURCC_YV12: {
+ for (i = 0; i < w; ++i) {
+ for (j = 0; i < h; ++j) {
+ /*XXX use src? */
+ y1 = buf[j*w + i];
+ u = buf[(j/2) * (w/2) + i/2 + y_array_size];
+ v = buf[(j/2) * (w/2) + i/2 + y_array_size + y_array_size/4];
+ ymap[yidx++] = y1;
+ umap[uidx++] = u;
+ vmap[vidx++] = v;
+ }
+ }
+ }
+ break;
+ case FOURCC_UYVY:
+ for (i = 0; i < y_array_size; i +=2 ) {
+ /* extracting two pixels */
+ u = buf[0];
+ y1 = buf[1];
+ v = buf[2];
+ y2 = buf[3];
+ buf += 4;
+
+ ymap[yidx++] = y1;
+ ymap[yidx++] = y2;
+ umap[uidx++] = u;
+ umap[uidx++] = u;
+ vmap[vidx++] = v;
+ vmap[vidx++] = v;
+ }
+ break;
+ case FOURCC_YUY2:
+ for (i = 0; i < y_array_size; i +=2 ) {
+ /* extracting two pixels */
+ y1 = buf[0];
+ u = buf[1];
+ y2 = buf[2];
+ v = buf[3];
+
+ buf += 4;
+
+ ymap[yidx++] = y1;
+ ymap[yidx++] = y2;
+ umap[uidx++] = u;
+ umap[uidx++] = u;
+ vmap[vidx++] = v;
+ vmap[vidx++] = v;
+ }
+ break;
+ default:
+ debug_assert(!"Unsupported yuv format!");
+ break;
+ }
+
+ screen->transfer_unmap(screen, ytrans);
+ screen->transfer_unmap(screen, utrans);
+ screen->transfer_unmap(screen, vtrans);
+ screen->tex_transfer_destroy(ytrans);
+ screen->tex_transfer_destroy(utrans);
+ screen->tex_transfer_destroy(vtrans);
+}
+
+
+static void
+setup_vs_video_constants(struct xorg_renderer *r, struct exa_pixmap_priv *dst)
+{
+ int width = dst->tex->width[0];
+ int height = dst->tex->height[0];
+ const int param_bytes = 8 * sizeof(float);
+ float vs_consts[8] = {
+ 2.f/width, 2.f/height, 1, 1,
+ -1, -1, 0, 0
+ };
+
+ renderer_set_constants(r, PIPE_SHADER_VERTEX,
+ vs_consts, param_bytes);
+}
+
+static void
+setup_fs_video_constants(struct xorg_renderer *r, boolean hdtv)
+{
+ const int param_bytes = 12 * sizeof(float);
+ const float *video_constants = (hdtv) ? bt_709 : bt_601;
+
+ renderer_set_constants(r, PIPE_SHADER_FRAGMENT,
+ video_constants, param_bytes);
+}
+
+static void
+draw_yuv(struct xorg_xv_port_priv *port,
+ 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 pipe_texture **textures = port->yuv[port->current_set];
+
+ renderer_draw_yuv(port->r,
+ src_x, src_y, src_w, src_h,
+ dst_x, dst_y, dst_w, dst_h,
+ textures);
+}
+
+static void
+bind_blend_state(struct xorg_xv_port_priv *port)
+{
+ struct pipe_blend_state blend;
+
+ memset(&blend, 0, sizeof(struct pipe_blend_state));
+ blend.blend_enable = 1;
+ blend.colormask |= PIPE_MASK_RGBA;
+
+ /* porter&duff src */
+ blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
+
+ cso_set_blend(port->r->cso, &blend);
+}
+
+
+static void
+bind_shaders(struct xorg_xv_port_priv *port)
+{
+ unsigned vs_traits = 0, fs_traits = 0;
+ struct xorg_shader shader;
+
+ vs_traits |= VS_YUV;
+ fs_traits |= FS_YUV;
+
+ shader = xorg_shaders_get(port->r->shaders, vs_traits, fs_traits);
+ cso_set_vertex_shader_handle(port->r->cso, shader.vs);
+ cso_set_fragment_shader_handle(port->r->cso, shader.fs);
+}
+
+static INLINE void
+conditional_flush(struct pipe_context *pipe, struct pipe_texture **tex,
+ int num)
+{
+ int i;
+ for (i = 0; i < num; ++i) {
+ if (tex[i] && pipe->is_texture_referenced(pipe, tex[i], 0, 0) &
+ PIPE_REFERENCED_FOR_WRITE) {
+ pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
+ return;
+ }
+ }
+}
+
+static void
+bind_samplers(struct xorg_xv_port_priv *port)
+{
+ struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
+ struct pipe_sampler_state sampler;
+ struct pipe_texture **dst = port->yuv[port->current_set];
+
+ memset(&sampler, 0, sizeof(struct pipe_sampler_state));
+
+ conditional_flush(port->r->pipe, dst, 3);
+
+ 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;
+
+ samplers[0] = &sampler;
+ samplers[1] = &sampler;
+ samplers[2] = &sampler;
+
+
+ cso_set_samplers(port->r->cso, 3,
+ (const struct pipe_sampler_state **)samplers);
+ cso_set_sampler_textures(port->r->cso, 3,
+ dst);
+}
+
+static int
+display_video(ScrnInfoPtr pScrn, struct xorg_xv_port_priv *pPriv, int id,
+ RegionPtr dstRegion,
+ int src_x, int src_y, int src_w, int src_h,
+ int dstX, int dstY, int dst_w, int dst_h,
+ PixmapPtr pPixmap)
+{
+ modesettingPtr ms = modesettingPTR(pScrn);
+ BoxPtr pbox;
+ int nbox;
+ int dxo, dyo;
+ Bool hdtv;
+ int x, y, w, h;
+ struct exa_pixmap_priv *dst = exaGetPixmapDriverPrivate(pPixmap);
+
+ if (!dst || !dst->tex)
+ XORG_FALLBACK("Xv destination %s", !dst ? "!dst" : "!dst->tex");
+
+ hdtv = ((src_w >= RES_720P_X) && (src_h >= RES_720P_Y));
+
+ REGION_TRANSLATE(pScrn->pScreen, dstRegion, -pPixmap->screen_x,
+ -pPixmap->screen_y);
+
+ dxo = dstRegion->extents.x1;
+ dyo = dstRegion->extents.y1;
+
+ pbox = REGION_RECTS(dstRegion);
+ nbox = REGION_NUM_RECTS(dstRegion);
+
+ renderer_bind_framebuffer(pPriv->r, dst);
+ renderer_bind_viewport(pPriv->r, dst);
+ bind_blend_state(pPriv);
+ renderer_bind_rasterizer(pPriv->r);
+ bind_shaders(pPriv);
+ bind_samplers(pPriv);
+ setup_vs_video_constants(pPriv->r, dst);
+ setup_fs_video_constants(pPriv->r, hdtv);
+
+ while (nbox--) {
+ int box_x1 = pbox->x1;
+ int box_y1 = pbox->y1;
+ int box_x2 = pbox->x2;
+ int box_y2 = pbox->y2;
+ float diff_x = (float)src_w / (float)dst_w;
+ float diff_y = (float)src_h / (float)dst_h;
+ int offset_x = box_x1 - dstX;
+ int offset_y = box_y1 - dstY;
+ int offset_w;
+ int offset_h;
+
+ x = box_x1;
+ y = box_y1;
+ w = box_x2 - box_x1;
+ h = box_y2 - box_y1;
+
+ offset_w = dst_w - w;
+ offset_h = dst_h - h;
+
+ draw_yuv(pPriv, src_x + offset_x*diff_x, src_y + offset_y*diff_y,
+ src_w - offset_w*diff_x, src_h - offset_h*diff_x,
+ x, y, w, h);
+
+ pbox++;
+ }
+ DamageDamageRegion(&pPixmap->drawable, dstRegion);
+
+ return TRUE;
+}
+
+static int
+put_image(ScrnInfoPtr pScrn,
+ short src_x, short src_y,
+ short drw_x, short drw_y,
+ short src_w, short src_h,
+ short drw_w, short drw_h,
+ int id, unsigned char *buf,
+ short width, short height,
+ Bool sync, RegionPtr clipBoxes, pointer data,
+ DrawablePtr pDraw)
+{
+ struct xorg_xv_port_priv *pPriv = (struct xorg_xv_port_priv *) data;
+ ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
+ PixmapPtr pPixmap;
+ INT32 x1, x2, y1, y2;
+ int srcPitch;
+ BoxRec dstBox;
+ int ret;
+
+ /* Clip */
+ x1 = src_x;
+ x2 = src_x + src_w;
+ y1 = src_y;
+ y2 = src_y + src_h;
+
+ dstBox.x1 = drw_x;
+ dstBox.x2 = drw_x + drw_w;
+ dstBox.y1 = drw_y;
+ dstBox.y2 = drw_y + drw_h;
+
+ if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes,
+ width, height))
+ return Success;
+
+ switch (id) {
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ srcPitch = width << 1;
+ break;
+ }
+
+ ret = check_yuv_textures(pPriv, width, height);
+
+ if (ret)
+ return ret;
+
+ copy_packed_data(pScrn, pPriv, id, buf, srcPitch,
+ src_x, src_y, width, height);
+
+ if (pDraw->type == DRAWABLE_WINDOW) {
+ pPixmap = (*pScreen->GetWindowPixmap)((WindowPtr)pDraw);
+ } else {
+ pPixmap = (PixmapPtr)pDraw;
+ }
+
+ display_video(pScrn, pPriv, id, clipBoxes,
+ src_x, src_y, src_w, src_h,
+ drw_x, drw_y,
+ drw_w, drw_h, pPixmap);
+
+ pPriv->current_set = (pPriv->current_set + 1) & 1;
+ return Success;
+}
+
+static int
+query_image_attributes(ScrnInfoPtr pScrn,
+ int id,
+ unsigned short *w, unsigned short *h,
+ int *pitches, int *offsets)
+{
+ int size;
+
+ if (*w > IMAGE_MAX_WIDTH)
+ *w = IMAGE_MAX_WIDTH;
+ if (*h > IMAGE_MAX_HEIGHT)
+ *h = IMAGE_MAX_HEIGHT;
+
+ *w = (*w + 1) & ~1;
+ if (offsets)
+ offsets[0] = 0;
+
+ switch (id) {
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ size = *w << 1;
+ if (pitches)
+ pitches[0] = size;
+ size *= *h;
+ break;
+ }
+
+ return size;
+}
+
+static struct xorg_xv_port_priv *
+port_priv_create(struct xorg_renderer *r)
+{
+ struct xorg_xv_port_priv *priv = NULL;
+
+ priv = calloc(1, sizeof(struct xorg_xv_port_priv));
+
+ if (!priv)
+ return NULL;
+
+ priv->r = r;
+
+ REGION_NULL(pScreen, &priv->clip);
+
+ debug_assert(priv && priv->r);
+
+ return priv;
+}
+
+static XF86VideoAdaptorPtr
+xorg_setup_textured_adapter(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ modesettingPtr ms = modesettingPTR(pScrn);
+ XF86VideoAdaptorPtr adapt;
+ XF86AttributePtr attrs;
+ DevUnion *dev_unions;
+ int nports = 16, i;
+ int nattributes;
+
+ nattributes = NUM_TEXTURED_ATTRIBUTES;
+
+ debug_assert(ms->exa);
+ debug_assert(ms->exa->renderer);
+
+ adapt = calloc(1, sizeof(XF86VideoAdaptorRec));
+ dev_unions = calloc(nports, sizeof(DevUnion));
+ attrs = calloc(nattributes, sizeof(XF86AttributeRec));
+ if (adapt == NULL || dev_unions == NULL || attrs == NULL) {
+ free(adapt);
+ free(dev_unions);
+ free(attrs);
+ return NULL;
+ }
+
+ adapt->type = XvWindowMask | XvInputMask | XvImageMask;
+ adapt->flags = 0;
+ adapt->name = "Gallium3D Textured Video";
+ adapt->nEncodings = 1;
+ adapt->pEncodings = DummyEncoding;
+ adapt->nFormats = NUM_FORMATS;
+ adapt->pFormats = Formats;
+ adapt->nPorts = 0;
+ adapt->pPortPrivates = dev_unions;
+ adapt->nAttributes = nattributes;
+ adapt->pAttributes = attrs;
+ memcpy(attrs, TexturedAttributes, nattributes * sizeof(XF86AttributeRec));
+ adapt->nImages = NUM_IMAGES;
+ adapt->pImages = Images;
+ adapt->PutVideo = NULL;
+ adapt->PutStill = NULL;
+ adapt->GetVideo = NULL;
+ adapt->GetStill = NULL;
+ adapt->StopVideo = stop_video;
+ adapt->SetPortAttribute = set_port_attribute;
+ adapt->GetPortAttribute = get_port_attribute;
+ adapt->QueryBestSize = query_best_size;
+ adapt->PutImage = put_image;
+ adapt->QueryImageAttributes = query_image_attributes;
+
+ for (i = 0; i < nports; i++) {
+ struct xorg_xv_port_priv *priv =
+ port_priv_create(ms->exa->renderer);
+
+ adapt->pPortPrivates[i].ptr = (pointer) (priv);
+ adapt->nPorts++;
+ }
+
+ return adapt;
+}
+
+void
+xorg_init_video(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ /*modesettingPtr ms = modesettingPTR(pScrn);*/
+ XF86VideoAdaptorPtr *adaptors, *new_adaptors = NULL;
+ XF86VideoAdaptorPtr textured_adapter;
+ int num_adaptors;
+
+ num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
+ new_adaptors = malloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr *));
+ if (new_adaptors == NULL)
+ return;
+
+ memcpy(new_adaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr));
+ adaptors = new_adaptors;
+
+ /* Add the adaptors supported by our hardware. First, set up the atoms
+ * that will be used by both output adaptors.
+ */
+ xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
+ xvContrast = MAKE_ATOM("XV_CONTRAST");
+
+ textured_adapter = xorg_setup_textured_adapter(pScreen);
+
+ debug_assert(textured_adapter);
+
+ if (textured_adapter) {
+ adaptors[num_adaptors++] = textured_adapter;
+ }
+
+ if (num_adaptors) {
+ xf86XVScreenInit(pScreen, adaptors, num_adaptors);
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Disabling Xv because no adaptors could be initialized.\n");
+ }
+
+ free(adaptors);
+}
diff --git a/src/gallium/state_trackers/xorg/xvmc/Makefile b/src/gallium/state_trackers/xorg/xvmc/Makefile
new file mode 100644
index 0000000000..126dc6d58f
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xvmc/Makefile
@@ -0,0 +1,16 @@
+TOP = ../../../../..
+include $(TOP)/configs/current
+
+LIBNAME = xvmctracker
+
+LIBRARY_INCLUDES = \
+ $(shell pkg-config --cflags-only-I xvmc) \
+ -I$(TOP)/src/gallium/winsys/g3dvl
+
+C_SOURCES = block.c \
+ surface.c \
+ context.c \
+ subpicture.c \
+ attributes.c
+
+include ../../../Makefile.template
diff --git a/src/gallium/state_trackers/xorg/xvmc/SConscript b/src/gallium/state_trackers/xorg/xvmc/SConscript
new file mode 100644
index 0000000000..cb25d68bd8
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xvmc/SConscript
@@ -0,0 +1,27 @@
+#######################################################################
+# SConscript for xvmc state_tracker
+
+Import('*')
+
+if 'xorg/xvmc' in env['statetrackers']:
+
+ env = env.Clone()
+
+ env.Append(CPPPATH = [
+ '#/src/gallium/include',
+ '#/src/gallium/auxiliary',
+ '#/src/gallium/winsys/g3dvl',
+ ])
+
+ env.ParseConfig('pkg-config --cflags --libs xvmc')
+
+ st_xvmc = env.ConvenienceLibrary(
+ target = 'st_xvmc',
+ source = [ 'block.c',
+ 'surface.c',
+ 'context.c',
+ 'subpicture.c',
+ 'attributes.c',
+ ]
+ )
+ Export('st_xvmc')
diff --git a/src/gallium/state_trackers/xorg/xvmc/attributes.c b/src/gallium/state_trackers/xorg/xvmc/attributes.c
new file mode 100644
index 0000000000..79a67838e6
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xvmc/attributes.c
@@ -0,0 +1,46 @@
+/**************************************************************************
+ *
+ * Copyright 2009 Younes Manton.
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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.
+ *
+ **************************************************************************/
+
+#include <assert.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/Xvlib.h>
+#include <X11/extensions/XvMClib.h>
+
+XvAttribute* XvMCQueryAttributes(Display *dpy, XvMCContext *context, int *number)
+{
+ return NULL;
+}
+
+Status XvMCSetAttribute(Display *dpy, XvMCContext *context, Atom attribute, int value)
+{
+ return BadImplementation;
+}
+
+Status XvMCGetAttribute(Display *dpy, XvMCContext *context, Atom attribute, int *value)
+{
+ return BadImplementation;
+}
diff --git a/src/gallium/state_trackers/xorg/xvmc/block.c b/src/gallium/state_trackers/xorg/xvmc/block.c
new file mode 100644
index 0000000000..5102375fcf
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xvmc/block.c
@@ -0,0 +1,88 @@
+/**************************************************************************
+ *
+ * Copyright 2009 Younes Manton.
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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.
+ *
+ **************************************************************************/
+
+#include <assert.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/XvMClib.h>
+#include <util/u_memory.h>
+#include "xvmc_private.h"
+
+Status XvMCCreateBlocks(Display *dpy, XvMCContext *context, unsigned int num_blocks, XvMCBlockArray *blocks)
+{
+ assert(dpy);
+
+ if (!context)
+ return XvMCBadContext;
+ if (num_blocks == 0)
+ return BadValue;
+
+ assert(blocks);
+
+ blocks->context_id = context->context_id;
+ blocks->num_blocks = num_blocks;
+ blocks->blocks = MALLOC(BLOCK_SIZE_BYTES * num_blocks);
+ blocks->privData = NULL;
+
+ return Success;
+}
+
+Status XvMCDestroyBlocks(Display *dpy, XvMCBlockArray *blocks)
+{
+ assert(dpy);
+ assert(blocks);
+ FREE(blocks->blocks);
+
+ return Success;
+}
+
+Status XvMCCreateMacroBlocks(Display *dpy, XvMCContext *context, unsigned int num_blocks, XvMCMacroBlockArray *blocks)
+{
+ assert(dpy);
+
+ if (!context)
+ return XvMCBadContext;
+ if (num_blocks == 0)
+ return BadValue;
+
+ assert(blocks);
+
+ blocks->context_id = context->context_id;
+ blocks->num_blocks = num_blocks;
+ blocks->macro_blocks = MALLOC(sizeof(XvMCMacroBlock) * num_blocks);
+ blocks->privData = NULL;
+
+ return Success;
+}
+
+Status XvMCDestroyMacroBlocks(Display *dpy, XvMCMacroBlockArray *blocks)
+{
+ assert(dpy);
+ assert(blocks);
+ FREE(blocks->macro_blocks);
+
+ return Success;
+}
diff --git a/src/gallium/state_trackers/xorg/xvmc/context.c b/src/gallium/state_trackers/xorg/xvmc/context.c
new file mode 100644
index 0000000000..c8a389385a
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xvmc/context.c
@@ -0,0 +1,252 @@
+/**************************************************************************
+ *
+ * Copyright 2009 Younes Manton.
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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.
+ *
+ **************************************************************************/
+
+#include <assert.h>
+#include <X11/Xlibint.h>
+#include <X11/extensions/XvMClib.h>
+#include <pipe/p_screen.h>
+#include <pipe/p_video_context.h>
+#include <pipe/p_video_state.h>
+#include <pipe/p_state.h>
+#include <vl_winsys.h>
+#include <util/u_memory.h>
+#include <util/u_debug.h>
+#include <vl/vl_csc.h>
+#include "xvmc_private.h"
+
+static Status Validate(Display *dpy, XvPortID port, int surface_type_id,
+ unsigned int width, unsigned int height, int flags,
+ bool *found_port, int *screen, int *chroma_format,
+ int *mc_type, int *surface_flags)
+{
+ bool found_surface = false;
+ XvAdaptorInfo *adaptor_info;
+ unsigned int num_adaptors;
+ int num_types;
+ unsigned int max_width, max_height;
+ Status ret;
+
+ assert(dpy);
+ assert(found_port);
+ assert(screen);
+ assert(chroma_format);
+ assert(mc_type);
+ assert(surface_flags);
+
+ *found_port = false;
+
+ for (unsigned int i = 0; i < XScreenCount(dpy); ++i) {
+ ret = XvQueryAdaptors(dpy, XRootWindow(dpy, i), &num_adaptors, &adaptor_info);
+ if (ret != Success)
+ return ret;
+
+ for (unsigned int j = 0; j < num_adaptors && !*found_port; ++j) {
+ for (unsigned int k = 0; k < adaptor_info[j].num_ports && !*found_port; ++k) {
+ XvMCSurfaceInfo *surface_info;
+
+ if (adaptor_info[j].base_id + k != port)
+ continue;
+
+ *found_port = true;
+
+ surface_info = XvMCListSurfaceTypes(dpy, adaptor_info[j].base_id, &num_types);
+ if (!surface_info) {
+ XvFreeAdaptorInfo(adaptor_info);
+ return BadAlloc;
+ }
+
+ for (unsigned int l = 0; l < num_types && !found_surface; ++l) {
+ if (surface_info[l].surface_type_id != surface_type_id)
+ continue;
+
+ found_surface = true;
+ max_width = surface_info[l].max_width;
+ max_height = surface_info[l].max_height;
+ *chroma_format = surface_info[l].chroma_format;
+ *mc_type = surface_info[l].mc_type;
+ *surface_flags = surface_info[l].flags;
+ *screen = i;
+ }
+
+ XFree(surface_info);
+ }
+ }
+
+ XvFreeAdaptorInfo(adaptor_info);
+ }
+
+ if (!*found_port)
+ return XvBadPort;
+ if (!found_surface)
+ return BadMatch;
+ if (width > max_width || height > max_height)
+ return BadValue;
+ if (flags != XVMC_DIRECT && flags != 0)
+ return BadValue;
+
+ return Success;
+}
+
+static enum pipe_video_profile ProfileToPipe(int xvmc_profile)
+{
+ if (xvmc_profile & XVMC_MPEG_1)
+ assert(0);
+ if (xvmc_profile & XVMC_MPEG_2)
+ return PIPE_VIDEO_PROFILE_MPEG2_MAIN;
+ if (xvmc_profile & XVMC_H263)
+ assert(0);
+ if (xvmc_profile & XVMC_MPEG_4)
+ assert(0);
+
+ assert(0);
+
+ return -1;
+}
+
+static enum pipe_video_chroma_format FormatToPipe(int xvmc_format)
+{
+ switch (xvmc_format) {
+ case XVMC_CHROMA_FORMAT_420:
+ return PIPE_VIDEO_CHROMA_FORMAT_420;
+ case XVMC_CHROMA_FORMAT_422:
+ return PIPE_VIDEO_CHROMA_FORMAT_422;
+ case XVMC_CHROMA_FORMAT_444:
+ return PIPE_VIDEO_CHROMA_FORMAT_444;
+ default:
+ assert(0);
+ }
+
+ return -1;
+}
+
+Status XvMCCreateContext(Display *dpy, XvPortID port, int surface_type_id,
+ int width, int height, int flags, XvMCContext *context)
+{
+ bool found_port;
+ int scrn;
+ int chroma_format;
+ int mc_type;
+ int surface_flags;
+ Status ret;
+ struct pipe_screen *screen;
+ struct pipe_video_context *vpipe;
+ XvMCContextPrivate *context_priv;
+ float csc[16];
+
+ assert(dpy);
+
+ if (!context)
+ return XvMCBadContext;
+
+ ret = Validate(dpy, port, surface_type_id, width, height, flags,
+ &found_port, &scrn, &chroma_format, &mc_type, &surface_flags);
+
+ /* Success and XvBadPort have the same value */
+ if (ret != Success || !found_port)
+ return ret;
+
+ /* XXX: Current limits */
+ if (chroma_format != XVMC_CHROMA_FORMAT_420) {
+ debug_printf("[XvMCg3dvl] Cannot decode requested surface type. Unsupported chroma format.\n");
+ return BadImplementation;
+ }
+ if (mc_type != (XVMC_MOCOMP | XVMC_MPEG_2)) {
+ debug_printf("[XvMCg3dvl] Cannot decode requested surface type. Non-MPEG2/Mocomp acceleration unsupported.\n");
+ return BadImplementation;
+ }
+ if (!(surface_flags & XVMC_INTRA_UNSIGNED)) {
+ debug_printf("[XvMCg3dvl] Cannot decode requested surface type. Signed intra unsupported.\n");
+ return BadImplementation;
+ }
+
+ context_priv = CALLOC(1, sizeof(XvMCContextPrivate));
+ if (!context_priv)
+ return BadAlloc;
+
+ /* TODO: Reuse screen if process creates another context */
+ screen = vl_screen_create(dpy, scrn);
+
+ if (!screen) {
+ FREE(context_priv);
+ return BadAlloc;
+ }
+
+ vpipe = vl_video_create(dpy, scrn, screen, ProfileToPipe(mc_type),
+ FormatToPipe(chroma_format), width, height);
+
+ if (!vpipe) {
+ screen->destroy(screen);
+ FREE(context_priv);
+ return BadAlloc;
+ }
+
+ /* TODO: Define some Xv attribs to allow users to specify color standard, procamp */
+ vl_csc_get_matrix
+ (
+ debug_get_bool_option("G3DVL_NO_CSC", FALSE) ?
+ VL_CSC_COLOR_STANDARD_IDENTITY : VL_CSC_COLOR_STANDARD_BT_601,
+ NULL, true, csc
+ );
+ vpipe->set_csc_matrix(vpipe, csc);
+
+ context_priv->vpipe = vpipe;
+
+ context->context_id = XAllocID(dpy);
+ context->surface_type_id = surface_type_id;
+ context->width = width;
+ context->height = height;
+ context->flags = flags;
+ context->port = port;
+ context->privData = context_priv;
+
+ SyncHandle();
+
+ return Success;
+}
+
+Status XvMCDestroyContext(Display *dpy, XvMCContext *context)
+{
+ struct pipe_screen *screen;
+ struct pipe_video_context *vpipe;
+ XvMCContextPrivate *context_priv;
+
+ assert(dpy);
+
+ if (!context || !context->privData)
+ return XvMCBadContext;
+
+ context_priv = context->privData;
+ vpipe = context_priv->vpipe;
+ pipe_surface_reference(&context_priv->backbuffer, NULL);
+ screen = vpipe->screen;
+ vpipe->destroy(vpipe);
+ screen->destroy(screen);
+ FREE(context_priv);
+ context->privData = NULL;
+
+ return Success;
+}
diff --git a/src/gallium/state_trackers/xorg/xvmc/subpicture.c b/src/gallium/state_trackers/xorg/xvmc/subpicture.c
new file mode 100644
index 0000000000..69898d5fcd
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xvmc/subpicture.c
@@ -0,0 +1,195 @@
+/**************************************************************************
+ *
+ * Copyright 2009 Younes Manton.
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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.
+ *
+ **************************************************************************/
+
+#include <assert.h>
+#include <X11/Xlibint.h>
+#include <X11/extensions/XvMClib.h>
+
+Status XvMCCreateSubpicture(Display *dpy, XvMCContext *context, XvMCSubpicture *subpicture,
+ unsigned short width, unsigned short height, int xvimage_id)
+{
+ assert(dpy);
+
+ if (!context)
+ return XvMCBadContext;
+
+ assert(subpicture);
+
+ /*if (width > || height > )
+ return BadValue;*/
+
+ /*if (xvimage_id != )
+ return BadMatch;*/
+
+ subpicture->subpicture_id = XAllocID(dpy);
+ subpicture->context_id = context->context_id;
+ subpicture->xvimage_id = xvimage_id;
+ subpicture->width = width;
+ subpicture->height = height;
+ subpicture->num_palette_entries = 0;
+ subpicture->entry_bytes = 0;
+ subpicture->component_order[0] = 0;
+ subpicture->component_order[1] = 0;
+ subpicture->component_order[2] = 0;
+ subpicture->component_order[3] = 0;
+ /* TODO: subpicture->privData = ;*/
+
+ SyncHandle();
+
+ return Success;
+}
+
+Status XvMCClearSubpicture(Display *dpy, XvMCSubpicture *subpicture, short x, short y,
+ unsigned short width, unsigned short height, unsigned int color)
+{
+ assert(dpy);
+
+ if (!subpicture)
+ return XvMCBadSubpicture;
+
+ /* TODO: Assert clear rect is within bounds? Or clip? */
+
+ return Success;
+}
+
+Status XvMCCompositeSubpicture(Display *dpy, XvMCSubpicture *subpicture, XvImage *image,
+ short srcx, short srcy, unsigned short width, unsigned short height,
+ short dstx, short dsty)
+{
+ assert(dpy);
+
+ if (!subpicture)
+ return XvMCBadSubpicture;
+
+ assert(image);
+
+ if (subpicture->xvimage_id != image->id)
+ return BadMatch;
+
+ /* TODO: Assert rects are within bounds? Or clip? */
+
+ return Success;
+}
+
+Status XvMCDestroySubpicture(Display *dpy, XvMCSubpicture *subpicture)
+{
+ assert(dpy);
+
+ if (!subpicture)
+ return XvMCBadSubpicture;
+
+ return BadImplementation;
+}
+
+Status XvMCSetSubpicturePalette(Display *dpy, XvMCSubpicture *subpicture, unsigned char *palette)
+{
+ assert(dpy);
+
+ if (!subpicture)
+ return XvMCBadSubpicture;
+
+ assert(palette);
+
+ /* We don't support paletted subpictures */
+ return BadMatch;
+}
+
+Status XvMCBlendSubpicture(Display *dpy, XvMCSurface *target_surface, XvMCSubpicture *subpicture,
+ short subx, short suby, unsigned short subw, unsigned short subh,
+ short surfx, short surfy, unsigned short surfw, unsigned short surfh)
+{
+ assert(dpy);
+
+ if (!target_surface)
+ return XvMCBadSurface;
+
+ if (!subpicture)
+ return XvMCBadSubpicture;
+
+ if (target_surface->context_id != subpicture->context_id)
+ return BadMatch;
+
+ /* TODO: Assert rects are within bounds? Or clip? */
+ return Success;
+}
+
+Status XvMCBlendSubpicture2(Display *dpy, XvMCSurface *source_surface, XvMCSurface *target_surface,
+ XvMCSubpicture *subpicture, short subx, short suby, unsigned short subw, unsigned short subh,
+ short surfx, short surfy, unsigned short surfw, unsigned short surfh)
+{
+ assert(dpy);
+
+ if (!source_surface || !target_surface)
+ return XvMCBadSurface;
+
+ if (!subpicture)
+ return XvMCBadSubpicture;
+
+ if (source_surface->context_id != subpicture->context_id)
+ return BadMatch;
+
+ if (source_surface->context_id != subpicture->context_id)
+ return BadMatch;
+
+ /* TODO: Assert rects are within bounds? Or clip? */
+ return Success;
+}
+
+Status XvMCSyncSubpicture(Display *dpy, XvMCSubpicture *subpicture)
+{
+ assert(dpy);
+
+ if (!subpicture)
+ return XvMCBadSubpicture;
+
+ return Success;
+}
+
+Status XvMCFlushSubpicture(Display *dpy, XvMCSubpicture *subpicture)
+{
+ assert(dpy);
+
+ if (!subpicture)
+ return XvMCBadSubpicture;
+
+ return Success;
+}
+
+Status XvMCGetSubpictureStatus(Display *dpy, XvMCSubpicture *subpicture, int *status)
+{
+ assert(dpy);
+
+ if (!subpicture)
+ return XvMCBadSubpicture;
+
+ assert(status);
+
+ /* TODO */
+ *status = 0;
+
+ return Success;
+}
diff --git a/src/gallium/state_trackers/xorg/xvmc/surface.c b/src/gallium/state_trackers/xorg/xvmc/surface.c
new file mode 100644
index 0000000000..bf9038f356
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xvmc/surface.c
@@ -0,0 +1,409 @@
+/**************************************************************************
+ *
+ * Copyright 2009 Younes Manton.
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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.
+ *
+ **************************************************************************/
+
+#include <assert.h>
+#include <X11/Xlibint.h>
+#include <pipe/p_video_context.h>
+#include <pipe/p_video_state.h>
+#include <pipe/p_state.h>
+#include <util/u_memory.h>
+#include "xvmc_private.h"
+
+static enum pipe_mpeg12_macroblock_type TypeToPipe(int xvmc_mb_type)
+{
+ if (xvmc_mb_type & XVMC_MB_TYPE_INTRA)
+ return PIPE_MPEG12_MACROBLOCK_TYPE_INTRA;
+ if ((xvmc_mb_type & (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD)) == XVMC_MB_TYPE_MOTION_FORWARD)
+ return PIPE_MPEG12_MACROBLOCK_TYPE_FWD;
+ if ((xvmc_mb_type & (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD)) == XVMC_MB_TYPE_MOTION_BACKWARD)
+ return PIPE_MPEG12_MACROBLOCK_TYPE_BKWD;
+ if ((xvmc_mb_type & (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD)) == (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD))
+ return PIPE_MPEG12_MACROBLOCK_TYPE_BI;
+
+ assert(0);
+
+ return -1;
+}
+
+static enum pipe_mpeg12_picture_type PictureToPipe(int xvmc_pic)
+{
+ switch (xvmc_pic) {
+ case XVMC_TOP_FIELD:
+ return PIPE_MPEG12_PICTURE_TYPE_FIELD_TOP;
+ case XVMC_BOTTOM_FIELD:
+ return PIPE_MPEG12_PICTURE_TYPE_FIELD_BOTTOM;
+ case XVMC_FRAME_PICTURE:
+ return PIPE_MPEG12_PICTURE_TYPE_FRAME;
+ default:
+ assert(0);
+ }
+
+ return -1;
+}
+
+static enum pipe_mpeg12_motion_type MotionToPipe(int xvmc_motion_type, int xvmc_dct_type)
+{
+ switch (xvmc_motion_type) {
+ case XVMC_PREDICTION_FRAME:
+ return xvmc_dct_type == XVMC_DCT_TYPE_FIELD ?
+ PIPE_MPEG12_MOTION_TYPE_16x8 : PIPE_MPEG12_MOTION_TYPE_FRAME;
+ case XVMC_PREDICTION_FIELD:
+ return PIPE_MPEG12_MOTION_TYPE_FIELD;
+ case XVMC_PREDICTION_DUAL_PRIME:
+ return PIPE_MPEG12_MOTION_TYPE_DUALPRIME;
+ default:
+ assert(0);
+ }
+
+ return -1;
+}
+
+static bool
+CreateOrResizeBackBuffer(struct pipe_video_context *vpipe, unsigned int width, unsigned int height,
+ struct pipe_surface **backbuffer)
+{
+ struct pipe_texture template;
+ struct pipe_texture *tex;
+
+ assert(vpipe);
+
+ if (*backbuffer) {
+ if ((*backbuffer)->width != width || (*backbuffer)->height != height)
+ pipe_surface_reference(backbuffer, NULL);
+ else
+ return true;
+ }
+
+ memset(&template, 0, sizeof(struct pipe_texture));
+ template.target = PIPE_TEXTURE_2D;
+ /* XXX: Needs to match the drawable's format? */
+ template.format = PIPE_FORMAT_X8R8G8B8_UNORM;
+ template.last_level = 0;
+ template.width[0] = width;
+ template.height[0] = height;
+ template.depth[0] = 1;
+ pf_get_block(template.format, &template.block);
+ template.tex_usage = PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
+
+ tex = vpipe->screen->texture_create(vpipe->screen, &template);
+ if (!tex)
+ return false;
+
+ *backbuffer = vpipe->screen->get_tex_surface(vpipe->screen, tex, 0, 0, 0,
+ PIPE_BUFFER_USAGE_GPU_READ |
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+ pipe_texture_reference(&tex, NULL);
+
+ if (!*backbuffer)
+ return false;
+
+ /* Clear the backbuffer in case the video doesn't cover the whole window */
+ /* FIXME: Need to clear every time a frame moves and leaves dirty rects */
+ vpipe->clear_surface(vpipe, 0, 0, width, height, 0, *backbuffer);
+
+ return true;
+}
+
+static void
+MacroBlocksToPipe(const XvMCMacroBlockArray *xvmc_macroblocks,
+ const XvMCBlockArray *xvmc_blocks,
+ unsigned int first_macroblock,
+ unsigned int num_macroblocks,
+ struct pipe_mpeg12_macroblock *pipe_macroblocks)
+{
+ unsigned int i, j, k, l;
+ XvMCMacroBlock *xvmc_mb;
+
+ assert(xvmc_macroblocks);
+ assert(xvmc_blocks);
+ assert(pipe_macroblocks);
+ assert(num_macroblocks);
+
+ xvmc_mb = xvmc_macroblocks->macro_blocks + first_macroblock;
+
+ for (i = 0; i < num_macroblocks; ++i) {
+ pipe_macroblocks->base.codec = PIPE_VIDEO_CODEC_MPEG12;
+ pipe_macroblocks->mbx = xvmc_mb->x;
+ pipe_macroblocks->mby = xvmc_mb->y;
+ pipe_macroblocks->mb_type = TypeToPipe(xvmc_mb->macroblock_type);
+ if (pipe_macroblocks->mb_type != PIPE_MPEG12_MACROBLOCK_TYPE_INTRA)
+ pipe_macroblocks->mo_type = MotionToPipe(xvmc_mb->motion_type, xvmc_mb->dct_type);
+ /* Get rid of Valgrind 'undefined' warnings */
+ else
+ pipe_macroblocks->mo_type = -1;
+ pipe_macroblocks->dct_type = xvmc_mb->dct_type == XVMC_DCT_TYPE_FIELD ?
+ PIPE_MPEG12_DCT_TYPE_FIELD : PIPE_MPEG12_DCT_TYPE_FRAME;
+
+ for (j = 0; j < 2; ++j)
+ for (k = 0; k < 2; ++k)
+ for (l = 0; l < 2; ++l)
+ pipe_macroblocks->pmv[j][k][l] = xvmc_mb->PMV[j][k][l];
+
+ pipe_macroblocks->cbp = xvmc_mb->coded_block_pattern;
+ pipe_macroblocks->blocks = xvmc_blocks->blocks + xvmc_mb->index * BLOCK_SIZE_SAMPLES;
+
+ ++pipe_macroblocks;
+ ++xvmc_mb;
+ }
+}
+
+Status XvMCCreateSurface(Display *dpy, XvMCContext *context, XvMCSurface *surface)
+{
+ XvMCContextPrivate *context_priv;
+ struct pipe_video_context *vpipe;
+ XvMCSurfacePrivate *surface_priv;
+ struct pipe_video_surface *vsfc;
+
+ assert(dpy);
+
+ if (!context)
+ return XvMCBadContext;
+ if (!surface)
+ return XvMCBadSurface;
+
+ context_priv = context->privData;
+ vpipe = context_priv->vpipe;
+
+ surface_priv = CALLOC(1, sizeof(XvMCSurfacePrivate));
+ if (!surface_priv)
+ return BadAlloc;
+
+ vsfc = vpipe->screen->video_surface_create(vpipe->screen, vpipe->chroma_format,
+ vpipe->width, vpipe->height);
+ if (!vsfc) {
+ FREE(surface_priv);
+ return BadAlloc;
+ }
+
+ surface_priv->pipe_vsfc = vsfc;
+ surface_priv->context = context;
+
+ surface->surface_id = XAllocID(dpy);
+ surface->context_id = context->context_id;
+ surface->surface_type_id = context->surface_type_id;
+ surface->width = context->width;
+ surface->height = context->height;
+ surface->privData = surface_priv;
+
+ SyncHandle();
+
+ return Success;
+}
+
+Status XvMCRenderSurface(Display *dpy, XvMCContext *context, unsigned int picture_structure,
+ XvMCSurface *target_surface, XvMCSurface *past_surface, XvMCSurface *future_surface,
+ unsigned int flags, unsigned int num_macroblocks, unsigned int first_macroblock,
+ XvMCMacroBlockArray *macroblocks, XvMCBlockArray *blocks
+)
+{
+ struct pipe_video_context *vpipe;
+ struct pipe_surface *t_vsfc;
+ struct pipe_surface *p_vsfc;
+ struct pipe_surface *f_vsfc;
+ XvMCContextPrivate *context_priv;
+ XvMCSurfacePrivate *target_surface_priv;
+ XvMCSurfacePrivate *past_surface_priv;
+ XvMCSurfacePrivate *future_surface_priv;
+ struct pipe_mpeg12_macroblock pipe_macroblocks[num_macroblocks];
+
+ assert(dpy);
+
+ if (!context || !context->privData)
+ return XvMCBadContext;
+ if (!target_surface || !target_surface->privData)
+ return XvMCBadSurface;
+
+ if (picture_structure != XVMC_TOP_FIELD &&
+ picture_structure != XVMC_BOTTOM_FIELD &&
+ picture_structure != XVMC_FRAME_PICTURE)
+ return BadValue;
+ /* Bkwd pred equivalent to fwd (past && !future) */
+ if (future_surface && !past_surface)
+ return BadMatch;
+
+ assert(context->context_id == target_surface->context_id);
+ assert(!past_surface || context->context_id == past_surface->context_id);
+ assert(!future_surface || context->context_id == future_surface->context_id);
+
+ assert(macroblocks);
+ assert(blocks);
+
+ assert(macroblocks->context_id == context->context_id);
+ assert(blocks->context_id == context->context_id);
+
+ assert(flags == 0 || flags == XVMC_SECOND_FIELD);
+
+ target_surface_priv = target_surface->privData;
+ past_surface_priv = past_surface ? past_surface->privData : NULL;
+ future_surface_priv = future_surface ? future_surface->privData : NULL;
+
+ assert(target_surface_priv->context == context);
+ assert(!past_surface || past_surface_priv->context == context);
+ assert(!future_surface || future_surface_priv->context == context);
+
+ context_priv = context->privData;
+ vpipe = context_priv->vpipe;
+
+ t_vsfc = target_surface_priv->pipe_vsfc;
+ p_vsfc = past_surface ? past_surface_priv->pipe_vsfc : NULL;
+ f_vsfc = future_surface ? future_surface_priv->pipe_vsfc : NULL;
+
+ MacroBlocksToPipe(macroblocks, blocks, first_macroblock,
+ num_macroblocks, pipe_macroblocks);
+
+ vpipe->set_decode_target(vpipe, t_vsfc);
+ vpipe->decode_macroblocks(vpipe, p_vsfc, f_vsfc, num_macroblocks,
+ &pipe_macroblocks->base, target_surface_priv->render_fence);
+
+ return Success;
+}
+
+Status XvMCFlushSurface(Display *dpy, XvMCSurface *surface)
+{
+ assert(dpy);
+
+ if (!surface)
+ return XvMCBadSurface;
+
+ return Success;
+}
+
+Status XvMCSyncSurface(Display *dpy, XvMCSurface *surface)
+{
+ assert(dpy);
+
+ if (!surface)
+ return XvMCBadSurface;
+
+ return Success;
+}
+
+Status XvMCPutSurface(Display *dpy, XvMCSurface *surface, Drawable drawable,
+ short srcx, short srcy, unsigned short srcw, unsigned short srch,
+ short destx, short desty, unsigned short destw, unsigned short desth,
+ int flags)
+{
+ Window root;
+ int x, y;
+ unsigned int width, height;
+ unsigned int border_width;
+ unsigned int depth;
+ struct pipe_video_context *vpipe;
+ XvMCSurfacePrivate *surface_priv;
+ XvMCContextPrivate *context_priv;
+ XvMCContext *context;
+ struct pipe_video_rect src_rect = {srcx, srcy, srcw, srch};
+ struct pipe_video_rect dst_rect = {destx, desty, destw, desth};
+
+ assert(dpy);
+
+ if (!surface || !surface->privData)
+ return XvMCBadSurface;
+
+ if (XGetGeometry(dpy, drawable, &root, &x, &y, &width, &height, &border_width, &depth) == BadDrawable)
+ return BadDrawable;
+
+ assert(flags == XVMC_TOP_FIELD || flags == XVMC_BOTTOM_FIELD || flags == XVMC_FRAME_PICTURE);
+ assert(srcx + srcw - 1 < surface->width);
+ assert(srcy + srch - 1 < surface->height);
+ /*
+ * Some apps (mplayer) hit these asserts because they call
+ * this function after the window has been resized by the WM
+ * but before they've handled the corresponding XEvent and
+ * know about the new dimensions. The output should be clipped
+ * until the app updates destw and desth.
+ */
+ /*
+ assert(destx + destw - 1 < width);
+ assert(desty + desth - 1 < height);
+ */
+
+ surface_priv = surface->privData;
+ context = surface_priv->context;
+ context_priv = context->privData;
+ vpipe = context_priv->vpipe;
+
+ if (!CreateOrResizeBackBuffer(vpipe, width, height, &context_priv->backbuffer))
+ return BadAlloc;
+
+ vpipe->render_picture(vpipe, surface_priv->pipe_vsfc, PictureToPipe(flags), &src_rect,
+ context_priv->backbuffer, &dst_rect, surface_priv->disp_fence);
+
+ vl_video_bind_drawable(vpipe, drawable);
+
+ vpipe->screen->flush_frontbuffer
+ (
+ vpipe->screen,
+ context_priv->backbuffer,
+ vpipe->priv
+ );
+
+ return Success;
+}
+
+Status XvMCGetSurfaceStatus(Display *dpy, XvMCSurface *surface, int *status)
+{
+ assert(dpy);
+
+ if (!surface)
+ return XvMCBadSurface;
+
+ assert(status);
+
+ *status = 0;
+
+ return Success;
+}
+
+Status XvMCDestroySurface(Display *dpy, XvMCSurface *surface)
+{
+ XvMCSurfacePrivate *surface_priv;
+
+ assert(dpy);
+
+ if (!surface || !surface->privData)
+ return XvMCBadSurface;
+
+ surface_priv = surface->privData;
+ pipe_video_surface_reference(&surface_priv->pipe_vsfc, NULL);
+ FREE(surface_priv);
+ surface->privData = NULL;
+
+ return Success;
+}
+
+Status XvMCHideSurface(Display *dpy, XvMCSurface *surface)
+{
+ assert(dpy);
+
+ if (!surface || !surface->privData)
+ return XvMCBadSurface;
+
+ /* No op, only for overlaid rendering */
+
+ return Success;
+}
diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/.gitignore b/src/gallium/state_trackers/xorg/xvmc/tests/.gitignore
new file mode 100644
index 0000000000..e1d2f9023d
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xvmc/tests/.gitignore
@@ -0,0 +1,5 @@
+test_context
+test_surface
+test_blocks
+test_rendering
+xvmc_bench
diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/Makefile b/src/gallium/state_trackers/xorg/xvmc/tests/Makefile
new file mode 100644
index 0000000000..c875dd7605
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xvmc/tests/Makefile
@@ -0,0 +1,28 @@
+TOP = ../../../../../..
+include $(TOP)/configs/current
+
+LIBS = -lXvMCW -lXvMC -lXv -lX11
+
+#############################################
+
+.PHONY: default clean
+
+default: test_context test_surface test_blocks test_rendering xvmc_bench
+
+test_context: test_context.o testlib.o
+ $(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
+
+test_surface: test_surface.o testlib.o
+ $(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
+
+test_blocks: test_blocks.o testlib.o
+ $(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
+
+test_rendering: test_rendering.o testlib.o
+ $(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
+
+xvmc_bench: xvmc_bench.o testlib.o
+ $(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
+
+clean:
+ $(RM) -rf *.o test_context test_surface test_blocks test_rendering xvmc_bench
diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/test_blocks.c b/src/gallium/state_trackers/xorg/xvmc/tests/test_blocks.c
new file mode 100644
index 0000000000..994e3ca4d1
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xvmc/tests/test_blocks.c
@@ -0,0 +1,111 @@
+/**************************************************************************
+ *
+ * Copyright 2009 Younes Manton.
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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.
+ *
+ **************************************************************************/
+
+#include <assert.h>
+#include <error.h>
+#include "testlib.h"
+
+int main(int argc, char **argv)
+{
+ const unsigned int width = 16, height = 16;
+ const unsigned int min_required_blocks = 1, min_required_macroblocks = 1;
+ const unsigned int mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2};
+
+ Display *display;
+ XvPortID port_num;
+ int surface_type_id;
+ unsigned int is_overlay, intra_unsigned;
+ int colorkey;
+ XvMCContext context;
+ XvMCSurface surface;
+ XvMCBlockArray blocks = {0};
+ XvMCMacroBlockArray macroblocks = {0};
+
+ display = XOpenDisplay(NULL);
+
+ if (!GetPort
+ (
+ display,
+ width,
+ height,
+ XVMC_CHROMA_FORMAT_420,
+ mc_types,
+ 2,
+ &port_num,
+ &surface_type_id,
+ &is_overlay,
+ &intra_unsigned
+ ))
+ {
+ XCloseDisplay(display);
+ error(1, 0, "Error, unable to find a good port.\n");
+ }
+
+ if (is_overlay)
+ {
+ Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0);
+ XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey);
+ }
+
+ assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success);
+ assert(XvMCCreateSurface(display, &context, &surface) == Success);
+
+ /* Test NULL context */
+ assert(XvMCCreateBlocks(display, NULL, 1, &blocks) == XvMCBadContext);
+ /* Test 0 blocks */
+ assert(XvMCCreateBlocks(display, &context, 0, &blocks) == BadValue);
+ /* Test valid params */
+ assert(XvMCCreateBlocks(display, &context, min_required_blocks, &blocks) == Success);
+ /* Test context id assigned and correct */
+ assert(blocks.context_id == context.context_id);
+ /* Test number of blocks assigned and correct */
+ assert(blocks.num_blocks == min_required_blocks);
+ /* Test block pointer valid */
+ assert(blocks.blocks != NULL);
+ /* Test NULL context */
+ assert(XvMCCreateMacroBlocks(display, NULL, 1, &macroblocks) == XvMCBadContext);
+ /* Test 0 macroblocks */
+ assert(XvMCCreateMacroBlocks(display, &context, 0, &macroblocks) == BadValue);
+ /* Test valid params */
+ assert(XvMCCreateMacroBlocks(display, &context, min_required_macroblocks, &macroblocks) == Success);
+ /* Test context id assigned and correct */
+ assert(macroblocks.context_id == context.context_id);
+ /* Test macroblock pointer valid */
+ assert(macroblocks.macro_blocks != NULL);
+ /* Test valid params */
+ assert(XvMCDestroyMacroBlocks(display, &macroblocks) == Success);
+ /* Test valid params */
+ assert(XvMCDestroyBlocks(display, &blocks) == Success);
+
+ assert(XvMCDestroySurface(display, &surface) == Success);
+ assert(XvMCDestroyContext(display, &context) == Success);
+
+ XvUngrabPort(display, port_num, CurrentTime);
+ XCloseDisplay(display);
+
+ return 0;
+}
diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/test_context.c b/src/gallium/state_trackers/xorg/xvmc/tests/test_context.c
new file mode 100644
index 0000000000..3da957c933
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xvmc/tests/test_context.c
@@ -0,0 +1,119 @@
+/**************************************************************************
+ *
+ * Copyright 2009 Younes Manton.
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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.
+ *
+ **************************************************************************/
+
+#include <assert.h>
+#include <error.h>
+#include "testlib.h"
+
+int main(int argc, char **argv)
+{
+ const unsigned int width = 16, height = 16;
+ const unsigned int mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2};
+
+ Display *display;
+ XvPortID port_num;
+ int surface_type_id;
+ unsigned int is_overlay, intra_unsigned;
+ int colorkey;
+ XvMCContext context = {0};
+
+ display = XOpenDisplay(NULL);
+
+ if (!GetPort
+ (
+ display,
+ width,
+ height,
+ XVMC_CHROMA_FORMAT_420,
+ mc_types,
+ 2,
+ &port_num,
+ &surface_type_id,
+ &is_overlay,
+ &intra_unsigned
+ ))
+ {
+ XCloseDisplay(display);
+ error(1, 0, "Error, unable to find a good port.\n");
+ }
+
+ if (is_overlay)
+ {
+ Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0);
+ XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey);
+ }
+
+ /* Test NULL context */
+ /* XXX: XvMCBadContext not a valid return for XvMCCreateContext in the XvMC API, but openChrome driver returns it */
+ assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, NULL) == XvMCBadContext);
+ /* Test invalid port */
+ /* XXX: Success and XvBadPort have the same value, if this call actually gets passed the validation step as of now we'll crash later */
+ assert(XvMCCreateContext(display, -1, surface_type_id, width, height, XVMC_DIRECT, &context) == XvBadPort);
+ /* Test invalid surface */
+ assert(XvMCCreateContext(display, port_num, -1, width, height, XVMC_DIRECT, &context) == BadMatch);
+ /* Test invalid flags */
+ assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, -1, &context) == BadValue);
+ /* Test huge width */
+ assert(XvMCCreateContext(display, port_num, surface_type_id, 16384, height, XVMC_DIRECT, &context) == BadValue);
+ /* Test huge height */
+ assert(XvMCCreateContext(display, port_num, surface_type_id, width, 16384, XVMC_DIRECT, &context) == BadValue);
+ /* Test huge width & height */
+ assert(XvMCCreateContext(display, port_num, surface_type_id, 16384, 16384, XVMC_DIRECT, &context) == BadValue);
+ /* Test valid params */
+ assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success);
+ /* Test context id assigned */
+ assert(context.context_id != 0);
+ /* Test surface type id assigned and correct */
+ assert(context.surface_type_id == surface_type_id);
+ /* Test width & height assigned and correct */
+ assert(context.width == width && context.height == height);
+ /* Test port assigned and correct */
+ assert(context.port == port_num);
+ /* Test flags assigned and correct */
+ assert(context.flags == XVMC_DIRECT);
+ /* Test NULL context */
+ assert(XvMCDestroyContext(display, NULL) == XvMCBadContext);
+ /* Test valid params */
+ assert(XvMCDestroyContext(display, &context) == Success);
+ /* Test awkward but valid width */
+ assert(XvMCCreateContext(display, port_num, surface_type_id, width + 1, height, XVMC_DIRECT, &context) == Success);
+ assert(context.width >= width + 1);
+ assert(XvMCDestroyContext(display, &context) == Success);
+ /* Test awkward but valid height */
+ assert(XvMCCreateContext(display, port_num, surface_type_id, width, height + 1, XVMC_DIRECT, &context) == Success);
+ assert(context.height >= height + 1);
+ assert(XvMCDestroyContext(display, &context) == Success);
+ /* Test awkward but valid width & height */
+ assert(XvMCCreateContext(display, port_num, surface_type_id, width + 1, height + 1, XVMC_DIRECT, &context) == Success);
+ assert(context.width >= width + 1 && context.height >= height + 1);
+ assert(XvMCDestroyContext(display, &context) == Success);
+
+ XvUngrabPort(display, port_num, CurrentTime);
+ XCloseDisplay(display);
+
+ return 0;
+}
diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/test_rendering.c b/src/gallium/state_trackers/xorg/xvmc/tests/test_rendering.c
new file mode 100644
index 0000000000..6058783a79
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xvmc/tests/test_rendering.c
@@ -0,0 +1,317 @@
+/**************************************************************************
+ *
+ * Copyright 2009 Younes Manton.
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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.
+ *
+ **************************************************************************/
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <error.h>
+#include "testlib.h"
+
+#define BLOCK_WIDTH 8
+#define BLOCK_HEIGHT 8
+#define BLOCK_SIZE (BLOCK_WIDTH * BLOCK_HEIGHT)
+#define MACROBLOCK_WIDTH 16
+#define MACROBLOCK_HEIGHT 16
+#define MACROBLOCK_WIDTH_IN_BLOCKS (MACROBLOCK_WIDTH / BLOCK_WIDTH)
+#define MACROBLOCK_HEIGHT_IN_BLOCKS (MACROBLOCK_HEIGHT / BLOCK_HEIGHT)
+#define BLOCKS_PER_MACROBLOCK 6
+
+#define INPUT_WIDTH 16
+#define INPUT_HEIGHT 16
+#define INPUT_WIDTH_IN_MACROBLOCKS (INPUT_WIDTH / MACROBLOCK_WIDTH)
+#define INPUT_HEIGHT_IN_MACROBLOCKS (INPUT_HEIGHT / MACROBLOCK_HEIGHT)
+#define NUM_MACROBLOCKS (INPUT_WIDTH_IN_MACROBLOCKS * INPUT_HEIGHT_IN_MACROBLOCKS)
+
+#define DEFAULT_OUTPUT_WIDTH INPUT_WIDTH
+#define DEFAULT_OUTPUT_HEIGHT INPUT_HEIGHT
+#define DEFAULT_ACCEPTABLE_ERR 0.01
+
+void ParseArgs(int argc, char **argv, unsigned int *output_width, unsigned int *output_height, double *acceptable_error, int *prompt);
+void Gradient(short *block, unsigned int start, unsigned int stop, int horizontal);
+
+void ParseArgs(int argc, char **argv, unsigned int *output_width, unsigned int *output_height, double *acceptable_error, int *prompt)
+{
+ int fail = 0;
+ int i;
+
+ *output_width = DEFAULT_OUTPUT_WIDTH;
+ *output_height = DEFAULT_OUTPUT_WIDTH;
+ *acceptable_error = DEFAULT_ACCEPTABLE_ERR;
+ *prompt = 1;
+
+ for (i = 1; i < argc && !fail; ++i)
+ {
+ if (!strcmp(argv[i], "-w"))
+ {
+ if (sscanf(argv[++i], "%u", output_width) != 1)
+ fail = 1;
+ }
+ else if (!strcmp(argv[i], "-h"))
+ {
+ if (sscanf(argv[++i], "%u", output_height) != 1)
+ fail = 1;
+ }
+ else if (!strcmp(argv[i], "-e"))
+ {
+ if (sscanf(argv[++i], "%lf", acceptable_error) != 1)
+ fail = 1;
+ }
+ else if (strcmp(argv[i], "-n"))
+ *prompt = 0;
+ else
+ fail = 1;
+ }
+
+ if (fail)
+ error
+ (
+ 1, 0,
+ "Bad argument.\n"
+ "\n"
+ "Usage: %s [options]\n"
+ "\t-w <width>\tOutput width\n"
+ "\t-h <height>\tOutput height\n"
+ "\t-e <error>\tAcceptable margin of error per pixel, from 0 to 1\n"
+ "\t-n\tDon't prompt for quit\n",
+ argv[0]
+ );
+}
+
+void Gradient(short *block, unsigned int start, unsigned int stop, int horizontal)
+{
+ unsigned int x, y;
+ unsigned int range = stop - start;
+
+ if (horizontal)
+ {
+ for (y = 0; y < BLOCK_HEIGHT; ++y)
+ for (x = 0; x < BLOCK_WIDTH; ++x)
+ block[y * BLOCK_WIDTH + x] = (short)(start + range * (x / (float)(BLOCK_WIDTH - 1)));
+ }
+ else
+ {
+ for (y = 0; y < BLOCK_HEIGHT; ++y)
+ for (x = 0; x < BLOCK_WIDTH; ++x)
+ block[y * BLOCK_WIDTH + x] = (short)(start + range * (y / (float)(BLOCK_HEIGHT - 1)));
+ }
+}
+
+int main(int argc, char **argv)
+{
+ unsigned int output_width;
+ unsigned int output_height;
+ double acceptable_error;
+ int prompt;
+ Display *display;
+ Window root, window;
+ const unsigned int mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2};
+ XvPortID port_num;
+ int surface_type_id;
+ unsigned int is_overlay, intra_unsigned;
+ int colorkey;
+ XvMCContext context;
+ XvMCSurface surface;
+ XvMCBlockArray block_array;
+ XvMCMacroBlockArray mb_array;
+ int mbx, mby, bx, by;
+ XvMCMacroBlock *mb;
+ short *blocks;
+ int quit = 0;
+
+ ParseArgs(argc, argv, &output_width, &output_height, &acceptable_error, &prompt);
+
+ display = XOpenDisplay(NULL);
+
+ if (!GetPort
+ (
+ display,
+ INPUT_WIDTH,
+ INPUT_HEIGHT,
+ XVMC_CHROMA_FORMAT_420,
+ mc_types,
+ 2,
+ &port_num,
+ &surface_type_id,
+ &is_overlay,
+ &intra_unsigned
+ ))
+ {
+ XCloseDisplay(display);
+ error(1, 0, "Error, unable to find a good port.\n");
+ }
+
+ if (is_overlay)
+ {
+ Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0);
+ XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey);
+ }
+
+ root = XDefaultRootWindow(display);
+ window = XCreateSimpleWindow(display, root, 0, 0, output_width, output_height, 0, 0, colorkey);
+
+ assert(XvMCCreateContext(display, port_num, surface_type_id, INPUT_WIDTH, INPUT_HEIGHT, XVMC_DIRECT, &context) == Success);
+ assert(XvMCCreateSurface(display, &context, &surface) == Success);
+ assert(XvMCCreateBlocks(display, &context, NUM_MACROBLOCKS * BLOCKS_PER_MACROBLOCK, &block_array) == Success);
+ assert(XvMCCreateMacroBlocks(display, &context, NUM_MACROBLOCKS, &mb_array) == Success);
+
+ mb = mb_array.macro_blocks;
+ blocks = block_array.blocks;
+
+ for (mby = 0; mby < INPUT_HEIGHT_IN_MACROBLOCKS; ++mby)
+ for (mbx = 0; mbx < INPUT_WIDTH_IN_MACROBLOCKS; ++mbx)
+ {
+ mb->x = mbx;
+ mb->y = mby;
+ mb->macroblock_type = XVMC_MB_TYPE_INTRA;
+ /*mb->motion_type = ;*/
+ /*mb->motion_vertical_field_select = ;*/
+ mb->dct_type = XVMC_DCT_TYPE_FRAME;
+ /*mb->PMV[0][0][0] = ;
+ mb->PMV[0][0][1] = ;
+ mb->PMV[0][1][0] = ;
+ mb->PMV[0][1][1] = ;
+ mb->PMV[1][0][0] = ;
+ mb->PMV[1][0][1] = ;
+ mb->PMV[1][1][0] = ;
+ mb->PMV[1][1][1] = ;*/
+ mb->index = (mby * INPUT_WIDTH_IN_MACROBLOCKS + mbx) * BLOCKS_PER_MACROBLOCK;
+ mb->coded_block_pattern = 0x3F;
+
+ mb++;
+
+ for (by = 0; by < MACROBLOCK_HEIGHT_IN_BLOCKS; ++by)
+ for (bx = 0; bx < MACROBLOCK_WIDTH_IN_BLOCKS; ++bx)
+ {
+ const int start = 16, stop = 235, range = stop - start;
+
+ Gradient
+ (
+ blocks,
+ (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))),
+ (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))),
+ 1
+ );
+
+ blocks += BLOCK_SIZE;
+ }
+
+ for (by = 0; by < MACROBLOCK_HEIGHT_IN_BLOCKS / 2; ++by)
+ for (bx = 0; bx < MACROBLOCK_WIDTH_IN_BLOCKS / 2; ++bx)
+ {
+ const int start = 16, stop = 240, range = stop - start;
+
+ Gradient
+ (
+ blocks,
+ (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))),
+ (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))),
+ 1
+ );
+
+ blocks += BLOCK_SIZE;
+
+ Gradient
+ (
+ blocks,
+ (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))),
+ (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))),
+ 1
+ );
+
+ blocks += BLOCK_SIZE;
+ }
+ }
+
+ XSelectInput(display, window, ExposureMask | KeyPressMask);
+ XMapWindow(display, window);
+ XSync(display, 0);
+
+ /* Test NULL context */
+ assert(XvMCRenderSurface(display, NULL, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == XvMCBadContext);
+ /* Test NULL surface */
+ assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, NULL, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == XvMCBadSurface);
+ /* Test bad picture structure */
+ assert(XvMCRenderSurface(display, &context, 0, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == BadValue);
+ /* Test valid params */
+ assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == Success);
+
+ /* Test NULL surface */
+ assert(XvMCPutSurface(display, NULL, window, 0, 0, INPUT_WIDTH, INPUT_HEIGHT, 0, 0, output_width, output_height, XVMC_FRAME_PICTURE) == XvMCBadSurface);
+ /* Test bad window */
+ /* XXX: X halts with a bad drawable for some reason, doesn't return BadDrawable as expected */
+ /*assert(XvMCPutSurface(display, &surface, 0, 0, 0, width, height, 0, 0, width, height, XVMC_FRAME_PICTURE) == BadDrawable);*/
+
+ if (prompt)
+ {
+ puts("Press any button to quit...");
+
+ while (!quit)
+ {
+ if (XPending(display) > 0)
+ {
+ XEvent event;
+
+ XNextEvent(display, &event);
+
+ switch (event.type)
+ {
+ case Expose:
+ {
+ /* Test valid params */
+ assert
+ (
+ XvMCPutSurface
+ (
+ display, &surface, window,
+ 0, 0, INPUT_WIDTH, INPUT_HEIGHT,
+ 0, 0, output_width, output_height,
+ XVMC_FRAME_PICTURE
+ ) == Success
+ );
+ break;
+ }
+ case KeyPress:
+ {
+ quit = 1;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ assert(XvMCDestroyBlocks(display, &block_array) == Success);
+ assert(XvMCDestroyMacroBlocks(display, &mb_array) == Success);
+ assert(XvMCDestroySurface(display, &surface) == Success);
+ assert(XvMCDestroyContext(display, &context) == Success);
+
+ XvUngrabPort(display, port_num, CurrentTime);
+ XDestroyWindow(display, window);
+ XCloseDisplay(display);
+
+ return 0;
+}
diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/test_surface.c b/src/gallium/state_trackers/xorg/xvmc/tests/test_surface.c
new file mode 100644
index 0000000000..b65eb265c0
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xvmc/tests/test_surface.c
@@ -0,0 +1,98 @@
+/**************************************************************************
+ *
+ * Copyright 2009 Younes Manton.
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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.
+ *
+ **************************************************************************/
+
+#include <assert.h>
+#include <error.h>
+#include "testlib.h"
+
+int main(int argc, char **argv)
+{
+ const unsigned int width = 16, height = 16;
+ const unsigned int mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2};
+
+ Display *display;
+ XvPortID port_num;
+ int surface_type_id;
+ unsigned int is_overlay, intra_unsigned;
+ int colorkey;
+ XvMCContext context;
+ XvMCSurface surface = {0};
+
+ display = XOpenDisplay(NULL);
+
+ if (!GetPort
+ (
+ display,
+ width,
+ height,
+ XVMC_CHROMA_FORMAT_420,
+ mc_types,
+ 2,
+ &port_num,
+ &surface_type_id,
+ &is_overlay,
+ &intra_unsigned
+ ))
+ {
+ XCloseDisplay(display);
+ error(1, 0, "Error, unable to find a good port.\n");
+ }
+
+ if (is_overlay)
+ {
+ Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0);
+ XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey);
+ }
+
+ assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success);
+
+ /* Test NULL context */
+ assert(XvMCCreateSurface(display, NULL, &surface) == XvMCBadContext);
+ /* Test NULL surface */
+ assert(XvMCCreateSurface(display, &context, NULL) == XvMCBadSurface);
+ /* Test valid params */
+ assert(XvMCCreateSurface(display, &context, &surface) == Success);
+ /* Test surface id assigned */
+ assert(surface.surface_id != 0);
+ /* Test context id assigned and correct */
+ assert(surface.context_id == context.context_id);
+ /* Test surface type id assigned and correct */
+ assert(surface.surface_type_id == surface_type_id);
+ /* Test width & height assigned and correct */
+ assert(surface.width == width && surface.height == height);
+ /* Test valid params */
+ assert(XvMCDestroySurface(display, &surface) == Success);
+ /* Test NULL surface */
+ assert(XvMCDestroySurface(display, NULL) == XvMCBadSurface);
+
+ assert(XvMCDestroyContext(display, &context) == Success);
+
+ XvUngrabPort(display, port_num, CurrentTime);
+ XCloseDisplay(display);
+
+ return 0;
+}
diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/testlib.c b/src/gallium/state_trackers/xorg/xvmc/tests/testlib.c
new file mode 100644
index 0000000000..142c09bb59
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xvmc/tests/testlib.c
@@ -0,0 +1,146 @@
+/**************************************************************************
+ *
+ * Copyright 2009 Younes Manton.
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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.
+ *
+ **************************************************************************/
+
+#include "testlib.h"
+#include <stdio.h>
+
+/*
+void test(int pred, const char *pred_string, const char *doc_string, const char *file, unsigned int line)
+{
+ fputs(doc_string, stderr);
+ if (!pred)
+ fprintf(stderr, " FAIL!\n\t\"%s\" at %s:%u\n", pred_string, file, line);
+ else
+ fputs(" PASS!\n", stderr);
+}
+*/
+
+int GetPort
+(
+ Display *display,
+ unsigned int width,
+ unsigned int height,
+ unsigned int chroma_format,
+ const unsigned int *mc_types,
+ unsigned int num_mc_types,
+ XvPortID *port_id,
+ int *surface_type_id,
+ unsigned int *is_overlay,
+ unsigned int *intra_unsigned
+)
+{
+ unsigned int found_port = 0;
+ XvAdaptorInfo *adaptor_info;
+ unsigned int num_adaptors;
+ int num_types;
+ int ev_base, err_base;
+ unsigned int i, j, k, l;
+
+ if (!XvMCQueryExtension(display, &ev_base, &err_base))
+ return 0;
+ if (XvQueryAdaptors(display, XDefaultRootWindow(display), &num_adaptors, &adaptor_info) != Success)
+ return 0;
+
+ for (i = 0; i < num_adaptors && !found_port; ++i)
+ {
+ if (adaptor_info[i].type & XvImageMask)
+ {
+ XvMCSurfaceInfo *surface_info = XvMCListSurfaceTypes(display, adaptor_info[i].base_id, &num_types);
+
+ if (surface_info)
+ {
+ for (j = 0; j < num_types && !found_port; ++j)
+ {
+ if
+ (
+ surface_info[j].chroma_format == chroma_format &&
+ surface_info[j].max_width >= width &&
+ surface_info[j].max_height >= height
+ )
+ {
+ for (k = 0; k < num_mc_types && !found_port; ++k)
+ {
+ if (surface_info[j].mc_type == mc_types[k])
+ {
+ for (l = 0; l < adaptor_info[i].num_ports && !found_port; ++l)
+ {
+ if (XvGrabPort(display, adaptor_info[i].base_id + l, CurrentTime) == Success)
+ {
+ *port_id = adaptor_info[i].base_id + l;
+ *surface_type_id = surface_info[j].surface_type_id;
+ *is_overlay = surface_info[j].flags & XVMC_OVERLAID_SURFACE;
+ *intra_unsigned = surface_info[j].flags & XVMC_INTRA_UNSIGNED;
+ found_port = 1;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ XFree(surface_info);
+ }
+ }
+ }
+
+ XvFreeAdaptorInfo(adaptor_info);
+
+ return found_port;
+}
+
+unsigned int align(unsigned int value, unsigned int alignment)
+{
+ return (value + alignment - 1) & ~(alignment - 1);
+}
+
+/* From the glibc manual */
+int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y)
+{
+ /* Perform the carry for the later subtraction by updating y. */
+ if (x->tv_usec < y->tv_usec)
+ {
+ int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
+ y->tv_usec -= 1000000 * nsec;
+ y->tv_sec += nsec;
+ }
+ if (x->tv_usec - y->tv_usec > 1000000)
+ {
+ int nsec = (x->tv_usec - y->tv_usec) / 1000000;
+ y->tv_usec += 1000000 * nsec;
+ y->tv_sec -= nsec;
+ }
+
+ /*
+ * Compute the time remaining to wait.
+ * tv_usec is certainly positive.
+ */
+ result->tv_sec = x->tv_sec - y->tv_sec;
+ result->tv_usec = x->tv_usec - y->tv_usec;
+
+ /* Return 1 if result is negative. */
+ return x->tv_sec < y->tv_sec;
+}
diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/testlib.h b/src/gallium/state_trackers/xorg/xvmc/tests/testlib.h
new file mode 100644
index 0000000000..0438e52928
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xvmc/tests/testlib.h
@@ -0,0 +1,69 @@
+/**************************************************************************
+ *
+ * Copyright 2009 Younes Manton.
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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.
+ *
+ **************************************************************************/
+
+#ifndef testlib_h
+#define testlib_h
+
+/*
+#define TEST(pred, doc) test(pred, #pred, doc, __FILE__, __LINE__)
+
+void test(int pred, const char *pred_string, const char *doc_string, const char *file, unsigned int line);
+*/
+
+#include <sys/time.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/XvMClib.h>
+
+/*
+ * display: IN A valid X display
+ * width, height: IN Surface size that the port must display
+ * chroma_format: IN Chroma format that the port must display
+ * mc_types, num_mc_types: IN List of MC types that the port must support, first port that matches the first mc_type will be returned
+ * port_id: OUT Your port's ID
+ * surface_type_id: OUT Your port's surface ID
+ * is_overlay: OUT If 1, port uses overlay surfaces, you need to set a colorkey
+ * intra_unsigned: OUT If 1, port uses unsigned values for intra-coded blocks
+ */
+int GetPort
+(
+ Display *display,
+ unsigned int width,
+ unsigned int height,
+ unsigned int chroma_format,
+ const unsigned int *mc_types,
+ unsigned int num_mc_types,
+ XvPortID *port_id,
+ int *surface_type_id,
+ unsigned int *is_overlay,
+ unsigned int *intra_unsigned
+);
+
+unsigned int align(unsigned int value, unsigned int alignment);
+
+int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y);
+
+#endif
diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/xvmc_bench.c b/src/gallium/state_trackers/xorg/xvmc/tests/xvmc_bench.c
new file mode 100644
index 0000000000..bf94d85623
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xvmc/tests/xvmc_bench.c
@@ -0,0 +1,300 @@
+/**************************************************************************
+ *
+ * Copyright 2009 Younes Manton.
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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.
+ *
+ **************************************************************************/
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <error.h>
+#include <sys/time.h>
+#include "testlib.h"
+
+#define MACROBLOCK_WIDTH 16
+#define MACROBLOCK_HEIGHT 16
+#define BLOCKS_PER_MACROBLOCK 6
+
+#define DEFAULT_INPUT_WIDTH 720
+#define DEFAULT_INPUT_HEIGHT 480
+#define DEFAULT_REPS 100
+
+#define PIPELINE_STEP_MC 1
+#define PIPELINE_STEP_CSC 2
+#define PIPELINE_STEP_SWAP 4
+
+#define MB_TYPE_I 1
+#define MB_TYPE_P 2
+#define MB_TYPE_B 4
+
+struct Config
+{
+ unsigned int input_width;
+ unsigned int input_height;
+ unsigned int output_width;
+ unsigned int output_height;
+ unsigned int pipeline;
+ unsigned int mb_types;
+ unsigned int reps;
+};
+
+void ParseArgs(int argc, char **argv, struct Config *config);
+
+void ParseArgs(int argc, char **argv, struct Config *config)
+{
+ int fail = 0;
+ int i;
+
+ config->input_width = DEFAULT_INPUT_WIDTH;
+ config->input_height = DEFAULT_INPUT_HEIGHT;
+ config->output_width = 0;
+ config->output_height = 0;
+ config->pipeline = 0;
+ config->mb_types = 0;
+ config->reps = DEFAULT_REPS;
+
+ for (i = 1; i < argc && !fail; ++i)
+ {
+ if (!strcmp(argv[i], "-iw"))
+ {
+ if (sscanf(argv[++i], "%u", &config->input_width) != 1)
+ fail = 1;
+ }
+ else if (!strcmp(argv[i], "-ih"))
+ {
+ if (sscanf(argv[++i], "%u", &config->input_height) != 1)
+ fail = 1;
+ }
+ else if (!strcmp(argv[i], "-ow"))
+ {
+ if (sscanf(argv[++i], "%u", &config->output_width) != 1)
+ fail = 1;
+ }
+ else if (!strcmp(argv[i], "-oh"))
+ {
+ if (sscanf(argv[++i], "%u", &config->output_height) != 1)
+ fail = 1;
+ }
+ else if (!strcmp(argv[i], "-p"))
+ {
+ char *token = strtok(argv[++i], ",");
+
+ while (token && !fail)
+ {
+ if (!strcmp(token, "mc"))
+ config->pipeline |= PIPELINE_STEP_MC;
+ else if (!strcmp(token, "csc"))
+ config->pipeline |= PIPELINE_STEP_CSC;
+ else if (!strcmp(token, "swp"))
+ config->pipeline |= PIPELINE_STEP_SWAP;
+ else
+ fail = 1;
+
+ if (!fail)
+ token = strtok(NULL, ",");
+ }
+ }
+ else if (!strcmp(argv[i], "-mb"))
+ {
+ char *token = strtok(argv[++i], ",");
+
+ while (token && !fail)
+ {
+ if (strcmp(token, "i"))
+ config->mb_types |= MB_TYPE_I;
+ else if (strcmp(token, "p"))
+ config->mb_types |= MB_TYPE_P;
+ else if (strcmp(token, "b"))
+ config->mb_types |= MB_TYPE_B;
+ else
+ fail = 1;
+
+ if (!fail)
+ token = strtok(NULL, ",");
+ }
+ }
+ else if (!strcmp(argv[i], "-r"))
+ {
+ if (sscanf(argv[++i], "%u", &config->reps) != 1)
+ fail = 1;
+ }
+ else
+ fail = 1;
+ }
+
+ if (fail)
+ error
+ (
+ 1, 0,
+ "Bad argument.\n"
+ "\n"
+ "Usage: %s [options]\n"
+ "\t-iw <width>\tInput width\n"
+ "\t-ih <height>\tInput height\n"
+ "\t-ow <width>\tOutput width\n"
+ "\t-oh <height>\tOutput height\n"
+ "\t-p <pipeline>\tPipeline to test\n"
+ "\t-mb <mb type>\tMacroBlock types to use\n"
+ "\t-r <reps>\tRepetitions\n\n"
+ "\tPipeline steps: mc,csc,swap\n"
+ "\tMB types: i,p,b\n",
+ argv[0]
+ );
+
+ if (config->output_width == 0)
+ config->output_width = config->input_width;
+ if (config->output_height == 0)
+ config->output_height = config->input_height;
+ if (!config->pipeline)
+ config->pipeline = PIPELINE_STEP_MC | PIPELINE_STEP_CSC | PIPELINE_STEP_SWAP;
+ if (!config->mb_types)
+ config->mb_types = MB_TYPE_I | MB_TYPE_P | MB_TYPE_B;
+}
+
+int main(int argc, char **argv)
+{
+ struct Config config;
+ Display *display;
+ Window root, window;
+ const unsigned int mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2};
+ XvPortID port_num;
+ int surface_type_id;
+ unsigned int is_overlay, intra_unsigned;
+ int colorkey;
+ XvMCContext context;
+ XvMCSurface surface;
+ XvMCBlockArray block_array;
+ XvMCMacroBlockArray mb_array;
+ unsigned int mbw, mbh;
+ unsigned int mbx, mby;
+ unsigned int reps;
+ struct timeval start, stop, diff;
+ double diff_secs;
+
+ ParseArgs(argc, argv, &config);
+
+ mbw = align(config.input_width, MACROBLOCK_WIDTH) / MACROBLOCK_WIDTH;
+ mbh = align(config.input_height, MACROBLOCK_HEIGHT) / MACROBLOCK_HEIGHT;
+
+ display = XOpenDisplay(NULL);
+
+ if (!GetPort
+ (
+ display,
+ config.input_width,
+ config.input_height,
+ XVMC_CHROMA_FORMAT_420,
+ mc_types,
+ 2,
+ &port_num,
+ &surface_type_id,
+ &is_overlay,
+ &intra_unsigned
+ ))
+ {
+ XCloseDisplay(display);
+ error(1, 0, "Error, unable to find a good port.\n");
+ }
+
+ if (is_overlay)
+ {
+ Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0);
+ XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey);
+ }
+
+ root = XDefaultRootWindow(display);
+ window = XCreateSimpleWindow(display, root, 0, 0, config.output_width, config.output_height, 0, 0, colorkey);
+
+ assert(XvMCCreateContext(display, port_num, surface_type_id, config.input_width, config.input_height, XVMC_DIRECT, &context) == Success);
+ assert(XvMCCreateSurface(display, &context, &surface) == Success);
+ assert(XvMCCreateBlocks(display, &context, mbw * mbh * BLOCKS_PER_MACROBLOCK, &block_array) == Success);
+ assert(XvMCCreateMacroBlocks(display, &context, mbw * mbh, &mb_array) == Success);
+
+ for (mby = 0; mby < mbh; ++mby)
+ for (mbx = 0; mbx < mbw; ++mbx)
+ {
+ mb_array.macro_blocks[mby * mbw + mbx].x = mbx;
+ mb_array.macro_blocks[mby * mbw + mbx].y = mby;
+ mb_array.macro_blocks[mby * mbw + mbx].macroblock_type = XVMC_MB_TYPE_INTRA;
+ /*mb->motion_type = ;*/
+ /*mb->motion_vertical_field_select = ;*/
+ mb_array.macro_blocks[mby * mbw + mbx].dct_type = XVMC_DCT_TYPE_FRAME;
+ /*mb->PMV[0][0][0] = ;
+ mb->PMV[0][0][1] = ;
+ mb->PMV[0][1][0] = ;
+ mb->PMV[0][1][1] = ;
+ mb->PMV[1][0][0] = ;
+ mb->PMV[1][0][1] = ;
+ mb->PMV[1][1][0] = ;
+ mb->PMV[1][1][1] = ;*/
+ mb_array.macro_blocks[mby * mbw + mbx].index = (mby * mbw + mbx) * BLOCKS_PER_MACROBLOCK;
+ mb_array.macro_blocks[mby * mbw + mbx].coded_block_pattern = 0x3F;
+ }
+
+ XSelectInput(display, window, ExposureMask | KeyPressMask);
+ XMapWindow(display, window);
+ XSync(display, 0);
+
+ gettimeofday(&start, NULL);
+
+ for (reps = 0; reps < config.reps; ++reps)
+ {
+ if (config.pipeline & PIPELINE_STEP_MC)
+ {
+ assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, mbw * mbh, 0, &mb_array, &block_array) == Success);
+ assert(XvMCFlushSurface(display, &surface) == Success);
+ }
+ if (config.pipeline & PIPELINE_STEP_CSC)
+ assert(XvMCPutSurface(display, &surface, window, 0, 0, config.input_width, config.input_height, 0, 0, config.output_width, config.output_height, XVMC_FRAME_PICTURE) == Success);
+ }
+
+ gettimeofday(&stop, NULL);
+
+ timeval_subtract(&diff, &stop, &start);
+ diff_secs = (double)diff.tv_sec + (double)diff.tv_usec / 1000000.0;
+
+ printf("XvMC Benchmark\n");
+ printf("Input: %u,%u\nOutput: %u,%u\n", config.input_width, config.input_height, config.output_width, config.output_height);
+ printf("Pipeline: ");
+ if (config.pipeline & PIPELINE_STEP_MC)
+ printf("|mc|");
+ if (config.pipeline & PIPELINE_STEP_CSC)
+ printf("|csc|");
+ if (config.pipeline & PIPELINE_STEP_SWAP)
+ printf("|swap|");
+ printf("\n");
+ printf("Reps: %u\n", config.reps);
+ printf("Total time: %.2lf (%.2lf reps / sec)\n", diff_secs, config.reps / diff_secs);
+
+ assert(XvMCDestroyBlocks(display, &block_array) == Success);
+ assert(XvMCDestroyMacroBlocks(display, &mb_array) == Success);
+ assert(XvMCDestroySurface(display, &surface) == Success);
+ assert(XvMCDestroyContext(display, &context) == Success);
+
+ XvUngrabPort(display, port_num, CurrentTime);
+ XDestroyWindow(display, window);
+ XCloseDisplay(display);
+
+ return 0;
+}
diff --git a/src/gallium/state_trackers/xorg/xvmc/xvmc_private.h b/src/gallium/state_trackers/xorg/xvmc/xvmc_private.h
new file mode 100644
index 0000000000..42337631ca
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xvmc/xvmc_private.h
@@ -0,0 +1,58 @@
+/**************************************************************************
+ *
+ * Copyright 2009 Younes Manton.
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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.
+ *
+ **************************************************************************/
+
+#ifndef xvmc_private_h
+#define xvmc_private_h
+
+#include <X11/Xlib.h>
+#include <X11/extensions/XvMClib.h>
+
+#define BLOCK_SIZE_SAMPLES 64
+#define BLOCK_SIZE_BYTES (BLOCK_SIZE_SAMPLES * 2)
+
+struct pipe_video_context;
+struct pipe_surface;
+struct pipe_fence_handle;
+
+typedef struct
+{
+ struct pipe_video_context *vpipe;
+ struct pipe_surface *backbuffer;
+} XvMCContextPrivate;
+
+typedef struct
+{
+ struct pipe_video_surface *pipe_vsfc;
+ struct pipe_fence_handle *render_fence;
+ struct pipe_fence_handle *disp_fence;
+
+ /* Some XvMC functions take a surface but not a context,
+ so we keep track of which context each surface belongs to. */
+ XvMCContext *context;
+} XvMCSurfacePrivate;
+
+#endif /* xvmc_private_h */