summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZack Rusin <[email protected]>2009-10-24 01:05:40 -0400
committerZack Rusin <[email protected]>2009-10-26 08:15:48 -0400
commita9f8baf00b264a9b370ecb611334af3063674ce5 (patch)
tree487fcef2fb9805db33c913b1c53bd9d6d070509d
parent6b8ce4cc4f9acdd9227e26a812dd911f45b623a5 (diff)
st/xorg: add yuv vertex shader
plus some general fixes
-rw-r--r--src/gallium/state_trackers/xorg/xorg_exa_tgsi.c15
-rw-r--r--src/gallium/state_trackers/xorg/xorg_exa_tgsi.h4
-rw-r--r--src/gallium/state_trackers/xorg/xorg_renderer.c45
-rw-r--r--src/gallium/state_trackers/xorg/xorg_renderer.h2
-rw-r--r--src/gallium/state_trackers/xorg/xorg_xv.c167
5 files changed, 200 insertions, 33 deletions
diff --git a/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c b/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c
index 95038917018..7cb11dc42bd 100644
--- a/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c
+++ b/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c
@@ -236,6 +236,7 @@ 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);
@@ -254,6 +255,20 @@ create_vs(struct pipe_context *pipe,
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);
+
+ src = ureg_DECL_vs_input(ureg, input_slot++);
+ dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 1);
+ ureg_MOV(ureg, dst, src);
+
+ src = ureg_DECL_vs_input(ureg, input_slot++);
+ dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 2);
+ ureg_MOV(ureg, dst, src);
+ }
+
if (is_composite) {
src = ureg_DECL_vs_input(ureg, input_slot++);
dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 0);
diff --git a/src/gallium/state_trackers/xorg/xorg_exa_tgsi.h b/src/gallium/state_trackers/xorg/xorg_exa_tgsi.h
index b373d1357bb..d3bfa304c2b 100644
--- a/src/gallium/state_trackers/xorg/xorg_exa_tgsi.h
+++ b/src/gallium/state_trackers/xorg/xorg_exa_tgsi.h
@@ -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 {
diff --git a/src/gallium/state_trackers/xorg/xorg_renderer.c b/src/gallium/state_trackers/xorg/xorg_renderer.c
index 51941f091cb..ec5268f9d6c 100644
--- a/src/gallium/state_trackers/xorg/xorg_renderer.c
+++ b/src/gallium/state_trackers/xorg/xorg_renderer.c
@@ -224,6 +224,44 @@ setup_vertex_data2(struct xorg_renderer *r,
sizeof(r->vertices3));
}
+static struct pipe_buffer *
+setup_vertex_data_yuv(struct xorg_renderer *r,
+ float srcX, float srcY,
+ float dstX, float dstY,
+ float width, float height,
+ struct pipe_texture **tex)
+{
+ float s0, t0, s1, t1;
+ float spt0[2], spt1[2];
+
+ spt0[0] = srcX;
+ spt0[1] = srcY;
+ spt1[0] = srcX + width;
+ spt1[1] = srcY + height;
+
+ 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 + 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 void
@@ -825,6 +863,13 @@ void renderer_draw_textures(struct xorg_renderer *r,
textures[0], textures[1],
src_matrix, mask_matrix);
break;
+ case 3:
+ buf = setup_vertex_data_yuv(r,
+ pos[0], pos[1],
+ pos[2], pos[3],
+ width, height,
+ textures);
+ break;
default:
debug_assert(!"Unsupported number of textures");
break;
diff --git a/src/gallium/state_trackers/xorg/xorg_renderer.h b/src/gallium/state_trackers/xorg/xorg_renderer.h
index 3e37c9aa930..f86ef670bee 100644
--- a/src/gallium/state_trackers/xorg/xorg_renderer.h
+++ b/src/gallium/state_trackers/xorg/xorg_renderer.h
@@ -16,7 +16,7 @@ struct xorg_renderer {
struct pipe_constant_buffer vs_const_buffer;
struct pipe_constant_buffer fs_const_buffer;
- /* we should combine these two */
+ /* we should combine these three */
float vertices2[4][2][4];
float vertices3[4][3][4];
};
diff --git a/src/gallium/state_trackers/xorg/xorg_xv.c b/src/gallium/state_trackers/xorg/xorg_xv.c
index 6d057b4c75f..983310f9b52 100644
--- a/src/gallium/state_trackers/xorg/xorg_xv.c
+++ b/src/gallium/state_trackers/xorg/xorg_xv.c
@@ -6,6 +6,9 @@
#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"
@@ -280,43 +283,144 @@ copy_packed_data(ScrnInfoPtr pScrn,
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_video_constants(struct xorg_renderer *r, boolean hdtv)
+setup_fs_video_constants(struct xorg_renderer *r, boolean hdtv)
{
- struct pipe_context *pipe = r->pipe;
const int param_bytes = 12 * sizeof(float);
- struct pipe_constant_buffer *cbuf = &r->fs_const_buffer;
+ 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 dst_x, int dst_y,
+ int w, int h)
+{
+ int pos[4] = {src_x, src_y,
+ dst_x, dst_y};
+ struct pipe_texture **textures = port->yuv[port->current_set];
+
+ renderer_draw_textures(port->r,
+ pos, w, h,
+ textures,
+ 3, /*bound samplers/textures */
+ NULL, NULL /* no transformations */);
+}
+
+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;
- pipe_buffer_reference(&cbuf->buffer, NULL);
- cbuf->buffer = pipe_buffer_create(pipe->screen, 16,
- PIPE_BUFFER_USAGE_CONSTANT,
- param_bytes);
+ 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;
- if (cbuf->buffer) {
- const float *video_constants = (hdtv) ? bt_709 : bt_601;
+ vs_traits |= VS_YUV;
+ fs_traits |= FS_YUV;
- pipe_buffer_write(pipe->screen, cbuf->buffer,
- 0, param_bytes, video_constants);
+ 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;
+ }
}
- pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, cbuf);
+}
+
+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,
short width, short height,
- int x1, int y1, int x2, int y2,
- short src_w, short src_h, short drw_w, short drw_h,
PixmapPtr pPixmap)
{
+ modesettingPtr ms = modesettingPTR(pScrn);
BoxPtr pbox;
int nbox;
int dxo, dyo;
Bool hdtv;
- float tc0[2], tc1[2], tc2[2];
+ 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));
- setup_video_constants(pPriv->r, hdtv);
REGION_TRANSLATE(pScrn->pScreen, dstRegion, -pPixmap->screen_x,
-pPixmap->screen_y);
@@ -327,32 +431,32 @@ display_video(ScrnInfoPtr pScrn, struct xorg_xv_port_priv *pPriv, int id,
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;
- tc0[0] = (double) (box_x1 - dxo) / (double) drw_w; /* u0 */
- tc0[1] = (double) (box_y1 - dyo) / (double) drw_h; /* v0 */
- tc1[0] = (double) (box_x2 - dxo) / (double) drw_w; /* u1 */
- tc1[1] = tc0[1];
- tc2[0] = tc0[0];
- tc2[1] = (double) (box_y2 - dyo) / (double) drw_h; /* v1 */
-
-#if 0
x = box_x1;
y = box_y1;
w = box_x2 - box_x1;
h = box_y2 - box_y1;
+ draw_yuv(pPriv, x, y, x, y, w, h);
+
pbox++;
- draw_yuv(pScrn, x, y, w, h, &src, 1, FALSE,
- 0, tc0, tc1, tc2, 1,
- pPriv->conversionData);
-#endif
}
DamageDamageRegion(&pPixmap->drawable, dstRegion);
+
return TRUE;
}
@@ -412,9 +516,10 @@ put_image(ScrnInfoPtr pScrn,
pPixmap = (PixmapPtr)pDraw;
}
- display_video(pScrn, pPriv, id, clipBoxes, width, height,
- x1, y1, x2, y2,
- src_w, src_h, drw_w, drw_h, pPixmap);
+ 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;