vl/compositor: add per vertex color suport
authorChristian König <deathsimple@vodafone.de>
Mon, 27 Feb 2012 15:07:51 +0000 (16:07 +0100)
committerChristian König <deathsimple@vodafone.de>
Fri, 2 Mar 2012 12:14:21 +0000 (13:14 +0100)
Used in subtitles, for example.

Signed-off-by: Christian König <deathsimple@vodafone.de>
src/gallium/auxiliary/vl/vl_compositor.c
src/gallium/auxiliary/vl/vl_compositor.h
src/gallium/state_trackers/vdpau/mixer.c
src/gallium/state_trackers/vdpau/output.c
src/gallium/state_trackers/vdpau/presentation.c
src/gallium/state_trackers/xvmc/surface.c

index b03029805619fd473c6489fc0407fb1e148764e7..1e8d37f2be9954312d07c7f558aefd680f407de0 100644 (file)
@@ -47,6 +47,7 @@ enum VS_OUTPUT
 {
    VS_O_VPOS,
    VS_O_VTEX,
+   VS_O_COLOR,
    VS_O_VTOP,
    VS_O_VBOTTOM,
 };
@@ -57,9 +58,9 @@ static void *
 create_vert_shader(struct vl_compositor *c)
 {
    struct ureg_program *shader;
-   struct ureg_src vpos, vtex;
+   struct ureg_src vpos, vtex, color;
    struct ureg_dst tmp;
-   struct ureg_dst o_vpos, o_vtex;
+   struct ureg_dst o_vpos, o_vtex, o_color;
    struct ureg_dst o_vtop, o_vbottom;
 
    shader = ureg_create(TGSI_PROCESSOR_VERTEX);
@@ -68,19 +69,37 @@ create_vert_shader(struct vl_compositor *c)
 
    vpos = ureg_DECL_vs_input(shader, 0);
    vtex = ureg_DECL_vs_input(shader, 1);
+   color = ureg_DECL_vs_input(shader, 2);
    tmp = ureg_DECL_temporary(shader);
    o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, VS_O_VPOS);
    o_vtex = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX);
+   o_color = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, VS_O_COLOR);
    o_vtop = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTOP);
    o_vbottom = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VBOTTOM);
 
    /*
     * o_vpos = vpos
     * o_vtex = vtex
+    * o_color = color
     */
    ureg_MOV(shader, o_vpos, vpos);
    ureg_MOV(shader, o_vtex, vtex);
+   ureg_MOV(shader, o_color, color);
 
+   /*
+    * tmp.x = vtex.w / 2
+    * tmp.y = vtex.w / 4
+    *
+    * o_vtop.x = vtex.x
+    * o_vtop.y = vtex.y * tmp.x + 0.25f
+    * o_vtop.z = vtex.y * tmp.y + 0.25f
+    * o_vtop.w = 1 / tmp.x
+    *
+    * o_vbottom.x = vtex.x
+    * o_vbottom.y = vtex.y * tmp.x - 0.25f
+    * o_vbottom.z = vtex.y * tmp.y - 0.25f
+    * o_vbottom.w = 1 / tmp.y
+    */
    ureg_MUL(shader, ureg_writemask(tmp, TGSI_WRITEMASK_X),
             ureg_scalar(vtex, TGSI_SWIZZLE_W), ureg_imm1f(shader, 0.5f));
    ureg_MUL(shader, ureg_writemask(tmp, TGSI_WRITEMASK_Y),
@@ -295,22 +314,24 @@ static void *
 create_frag_shader_rgba(struct vl_compositor *c)
 {
    struct ureg_program *shader;
-   struct ureg_src tc;
-   struct ureg_src sampler;
-   struct ureg_dst fragment;
+   struct ureg_src tc, color, sampler;
+   struct ureg_dst texel, fragment;
 
    shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
    if (!shader)
       return false;
 
    tc = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX, TGSI_INTERPOLATE_LINEAR);
+   color = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_COLOR, VS_O_COLOR, TGSI_INTERPOLATE_LINEAR);
    sampler = ureg_DECL_sampler(shader, 0);
+   texel = ureg_DECL_temporary(shader);
    fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
 
    /*
     * fragment = tex(tc, sampler)
     */
-   ureg_TEX(shader, fragment, TGSI_TEXTURE_2D, tc, sampler);
+   ureg_TEX(shader, texel, TGSI_TEXTURE_2D, tc, sampler);
+   ureg_MUL(shader, fragment, ureg_src(texel), color);
    ureg_END(shader);
 
    return ureg_create_shader_and_destroy(shader, c->pipe);
@@ -422,7 +443,7 @@ init_pipe_state(struct vl_compositor *c)
    c->blend_add = c->pipe->create_blend_state(c->pipe, &blend);
 
    memset(&rast, 0, sizeof rast);
-   rast.flatshade = 1;
+   rast.flatshade = 0;
    rast.front_ccw = 1;
    rast.cull_face = PIPE_FACE_NONE;
    rast.fill_back = PIPE_POLYGON_MODE_FILL;
@@ -495,14 +516,14 @@ create_vertex_buffer(struct vl_compositor *c)
 static bool
 init_buffers(struct vl_compositor *c)
 {
-   struct pipe_vertex_element vertex_elems[2];
+   struct pipe_vertex_element vertex_elems[3];
 
    assert(c);
 
    /*
     * Create our vertex buffer and vertex buffer elements
     */
-   c->vertex_buf.stride = sizeof(struct vertex2f) + sizeof(struct vertex4f);
+   c->vertex_buf.stride = sizeof(struct vertex2f) + sizeof(struct vertex4f) * 2;
    c->vertex_buf.buffer_offset = 0;
    create_vertex_buffer(c);
 
@@ -514,7 +535,11 @@ init_buffers(struct vl_compositor *c)
    vertex_elems[1].instance_divisor = 0;
    vertex_elems[1].vertex_buffer_index = 0;
    vertex_elems[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
-   c->vertex_elems_state = c->pipe->create_vertex_elements_state(c->pipe, 2, vertex_elems);
+   vertex_elems[2].src_offset = sizeof(struct vertex2f) + sizeof(struct vertex4f);
+   vertex_elems[2].instance_divisor = 0;
+   vertex_elems[2].vertex_buffer_index = 0;
+   vertex_elems[2].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+   c->vertex_elems_state = c->pipe->create_vertex_elements_state(c->pipe, 3, vertex_elems);
 
    return true;
 }
@@ -574,24 +599,40 @@ gen_rect_verts(struct vertex2f *vb, struct vl_compositor_layer *layer)
    vb[ 1].x = layer->src.tl.x;
    vb[ 1].y = layer->src.tl.y;
    vb[ 2] = layer->zw;
-
-   vb[ 3].x = layer->dst.br.x;
-   vb[ 3].y = layer->dst.tl.y;
-   vb[ 4].x = layer->src.br.x;
-   vb[ 4].y = layer->src.tl.y;
-   vb[ 5] = layer->zw;
-
-   vb[ 6].x = layer->dst.br.x;
-   vb[ 6].y = layer->dst.br.y;
-   vb[ 7].x = layer->src.br.x;
-   vb[ 7].y = layer->src.br.y;
-   vb[ 8] = layer->zw;
-
-   vb[ 9].x = layer->dst.tl.x;
-   vb[ 9].y = layer->dst.br.y;
-   vb[10].x = layer->src.tl.x;
-   vb[10].y = layer->src.br.y;
-   vb[11] = layer->zw;
+   vb[ 3].x = layer->colors[0].x;
+   vb[ 3].y = layer->colors[0].y;
+   vb[ 4].x = layer->colors[0].z;
+   vb[ 4].y = layer->colors[0].w;
+
+   vb[ 5].x = layer->dst.br.x;
+   vb[ 5].y = layer->dst.tl.y;
+   vb[ 6].x = layer->src.br.x;
+   vb[ 6].y = layer->src.tl.y;
+   vb[ 7] = layer->zw;
+   vb[ 8].x = layer->colors[1].x;
+   vb[ 8].y = layer->colors[1].y;
+   vb[ 9].x = layer->colors[1].z;
+   vb[ 9].y = layer->colors[1].w;
+
+   vb[10].x = layer->dst.br.x;
+   vb[10].y = layer->dst.br.y;
+   vb[11].x = layer->src.br.x;
+   vb[11].y = layer->src.br.y;
+   vb[12] = layer->zw;
+   vb[13].x = layer->colors[2].x;
+   vb[13].y = layer->colors[2].y;
+   vb[14].x = layer->colors[2].z;
+   vb[14].y = layer->colors[2].w;
+
+   vb[15].x = layer->dst.tl.x;
+   vb[15].y = layer->dst.br.y;
+   vb[16].x = layer->src.tl.x;
+   vb[16].y = layer->src.br.y;
+   vb[17] = layer->zw;
+   vb[18].x = layer->colors[3].x;
+   vb[18].y = layer->colors[3].y;
+   vb[19].x = layer->colors[3].z;
+   vb[19].y = layer->colors[3].w;
 }
 
 static INLINE struct u_rect
@@ -638,7 +679,7 @@ gen_vertex_data(struct vl_compositor *c, struct vl_compositor_state *s, struct u
       if (s->used_layers & (1 << i)) {
          struct vl_compositor_layer *layer = &s->layers[i];
          gen_rect_verts(vb, layer);
-         vb += 12;
+         vb += 20;
 
          if (dirty && layer->clearing) {
             struct u_rect drawn = calc_drawn_area(s, layer);
@@ -728,11 +769,14 @@ vl_compositor_clear_layers(struct vl_compositor_state *s)
 
    s->used_layers = 0;
    for ( i = 0; i < VL_COMPOSITOR_MAX_LAYERS; ++i) {
+      struct vertex4f v_one = { 1.0f, 1.0f, 1.0f, 1.0f };
       s->layers[i].clearing = i ? false : true;
       s->layers[i].blend = NULL;
       s->layers[i].fs = NULL;
       for ( j = 0; j < 3; j++)
          pipe_sampler_view_reference(&s->layers[i].sampler_views[j], NULL);
+      for ( j = 0; j < 4; ++j)
+         s->layers[i].colors[j] = v_one;
    }
 }
 
@@ -895,8 +939,11 @@ vl_compositor_set_rgba_layer(struct vl_compositor_state *s,
                              unsigned layer,
                              struct pipe_sampler_view *rgba,
                              struct u_rect *src_rect,
-                             struct u_rect *dst_rect)
+                             struct u_rect *dst_rect,
+                             struct vertex4f *colors)
 {
+   unsigned i;
+
    assert(s && c && rgba);
 
    assert(layer < VL_COMPOSITOR_MAX_LAYERS);
@@ -912,6 +959,10 @@ vl_compositor_set_rgba_layer(struct vl_compositor_state *s,
    calc_src_and_dst(&s->layers[layer], rgba->texture->width0, rgba->texture->height0,
                     src_rect ? *src_rect : default_rect(&s->layers[layer]),
                     dst_rect ? *dst_rect : default_rect(&s->layers[layer]));
+
+   if (colors)
+      for (i = 0; i < 4; ++i)
+         s->layers[layer].colors[i] = colors[i];
 }
 
 void
index f998a2e081c554b411666883eba4ce5162ee7316..f86a3f5f8dbbd98b0a9f879199c472bc63fe03b4 100644 (file)
@@ -65,6 +65,7 @@ struct vl_compositor_layer
       struct vertex2f tl, br;
    } src, dst;
    struct vertex2f zw;
+   struct vertex4f colors[4];
 };
 
 struct vl_compositor_state
@@ -207,7 +208,8 @@ vl_compositor_set_rgba_layer(struct vl_compositor_state *state,
                              unsigned layer,
                              struct pipe_sampler_view *rgba,
                              struct u_rect *src_rect,
-                             struct u_rect *dst_rect);
+                             struct u_rect *dst_rect,
+                             struct vertex4f *colors);
 
 /*@}*/
 
index ead9323eb8ff9702dd5be9bddec69296b12c5ace..066d60974f186b6a9637c475834de8587abab1b4 100644 (file)
@@ -244,7 +244,7 @@ VdpStatus vlVdpVideoMixerRender(VdpVideoMixer mixer,
       if (!bg)
          return VDP_STATUS_INVALID_HANDLE;
       vl_compositor_set_rgba_layer(&vmixer->cstate, compositor, layer++, bg->sampler_view,
-                                   RectToPipe(background_source_rect, &src_rect), NULL);
+                                   RectToPipe(background_source_rect, &src_rect), NULL, NULL);
    }
 
    vl_compositor_clear_layers(&vmixer->cstate);
index 0ea502939c3bcb4933963bb5a8c587a7bb6d6932..9113e2574e293a83048fd646f23bb85f8b5a8a72 100644 (file)
@@ -472,7 +472,7 @@ vlVdpOutputSurfaceRenderOutputSurface(VdpOutputSurface destination_surface,
    vl_compositor_clear_layers(cstate);
    vl_compositor_set_layer_blend(cstate, 0, blend, false);
    vl_compositor_set_rgba_layer(cstate, compositor, 0, src_vlsurface->sampler_view,
-                                RectToPipe(source_rect, &src_rect), NULL);
+                                RectToPipe(source_rect, &src_rect), NULL, NULL);
    vl_compositor_set_dst_area(cstate, RectToPipe(destination_rect, &dst_rect));
    vl_compositor_render(cstate, compositor, dst_vlsurface->surface, NULL);
 
index 4d12bb3e700ab6394c622f92b2cac1e8ffd38fbc..55437d7c4bd9b532796b61d40d7c21164293b987 100644 (file)
@@ -241,7 +241,7 @@ vlVdpPresentationQueueDisplay(VdpPresentationQueue presentation_queue,
    dst_clip.y1 = clip_height ? clip_height : surf_draw->height;
 
    vl_compositor_clear_layers(&pq->cstate);
-   vl_compositor_set_rgba_layer(&pq->cstate, compositor, 0, surf->sampler_view, &src_rect, NULL);
+   vl_compositor_set_rgba_layer(&pq->cstate, compositor, 0, surf->sampler_view, &src_rect, NULL, NULL);
    vl_compositor_set_dst_clip(&pq->cstate, &dst_clip);
    vl_compositor_render(&pq->cstate, compositor, surf_draw, dirty_area);
 
index 33b7dc2b1642107669c3830874de03fc60b58f4a..fcf6e619166f08e1ef4c8bca3ad3f25eeed488cc 100644 (file)
@@ -423,7 +423,7 @@ Status XvMCPutSurface(Display *dpy, XvMCSurface *surface, Drawable drawable,
                                          &subpicture_priv->src_rect, &subpicture_priv->dst_rect, true);
       else
          vl_compositor_set_rgba_layer(cstate, compositor, 1, subpicture_priv->sampler,
-                                      &subpicture_priv->src_rect, &subpicture_priv->dst_rect);
+                                      &subpicture_priv->src_rect, &subpicture_priv->dst_rect, NULL);
 
       surface_priv->subpicture = NULL;
       subpicture_priv->surface = NULL;