1 /**************************************************************************
3 * Copyright 2009 Younes Manton.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
28 #include "vl_compositor.h"
30 #include <pipe/p_context.h>
31 #include <pipe/p_inlines.h>
32 #include <tgsi/tgsi_ureg.h>
33 #include <util/u_memory.h>
36 struct vertex_shader_consts
38 struct vertex4f dst_scale
;
39 struct vertex4f dst_trans
;
40 struct vertex4f src_scale
;
41 struct vertex4f src_trans
;
44 struct fragment_shader_consts
50 u_video_rects_equal(struct pipe_video_rect
*a
, struct pipe_video_rect
*b
)
67 create_vert_shader(struct vl_compositor
*c
)
69 struct ureg_program
*shader
;
70 struct ureg_src vpos
, vtex
;
71 struct ureg_dst o_vpos
, o_vtex
;
73 shader
= ureg_create(TGSI_PROCESSOR_VERTEX
);
77 vpos
= ureg_DECL_vs_input(shader
, 0);
78 vtex
= ureg_DECL_vs_input(shader
, 1);
79 o_vpos
= ureg_DECL_output(shader
, TGSI_SEMANTIC_POSITION
, 0);
80 o_vtex
= ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, 1);
86 ureg_MOV(shader
, o_vpos
, vpos
);
87 ureg_MOV(shader
, o_vtex
, vtex
);
91 c
->vertex_shader
= ureg_create_shader_and_destroy(shader
, c
->pipe
);
92 if (!c
->vertex_shader
)
99 create_frag_shader(struct vl_compositor
*c
)
101 struct ureg_program
*shader
;
103 struct ureg_src csc
[4];
104 struct ureg_src sampler
;
105 struct ureg_dst texel
;
106 struct ureg_dst fragment
;
109 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
113 tc
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, 1, TGSI_INTERPOLATE_LINEAR
);
114 for (i
= 0; i
< 4; ++i
)
115 csc
[i
] = ureg_DECL_constant(shader
, i
);
116 sampler
= ureg_DECL_sampler(shader
, 0);
117 texel
= ureg_DECL_temporary(shader
);
118 fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
121 * texel = tex(tc, sampler)
122 * fragment = csc * texel
124 ureg_TEX(shader
, texel
, TGSI_TEXTURE_2D
, tc
, sampler
);
125 for (i
= 0; i
< 4; ++i
)
126 ureg_DP4(shader
, ureg_writemask(fragment
, TGSI_WRITEMASK_X
<< i
), csc
[i
], ureg_src(texel
));
128 ureg_release_temporary(shader
, texel
);
131 c
->fragment_shader
= ureg_create_shader_and_destroy(shader
, c
->pipe
);
132 if (!c
->fragment_shader
)
139 init_pipe_state(struct vl_compositor
*c
)
141 struct pipe_sampler_state sampler
;
145 c
->fb_state
.nr_cbufs
= 1;
146 c
->fb_state
.zsbuf
= NULL
;
148 sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
149 sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
150 sampler
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
151 sampler
.min_img_filter
= PIPE_TEX_FILTER_LINEAR
;
152 sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
153 sampler
.mag_img_filter
= PIPE_TEX_FILTER_LINEAR
;
154 sampler
.compare_mode
= PIPE_TEX_COMPARE_NONE
;
155 sampler
.compare_func
= PIPE_FUNC_ALWAYS
;
156 sampler
.normalized_coords
= 1;
157 /*sampler.prefilter = ;*/
158 /*sampler.lod_bias = ;*/
159 /*sampler.min_lod = ;*/
160 /*sampler.max_lod = ;*/
161 /*sampler.border_color[i] = ;*/
162 /*sampler.max_anisotropy = ;*/
163 c
->sampler
= c
->pipe
->create_sampler_state(c
->pipe
, &sampler
);
168 static void cleanup_pipe_state(struct vl_compositor
*c
)
172 c
->pipe
->delete_sampler_state(c
->pipe
, c
->sampler
);
176 init_shaders(struct vl_compositor
*c
)
180 create_vert_shader(c
);
181 create_frag_shader(c
);
186 static void cleanup_shaders(struct vl_compositor
*c
)
190 c
->pipe
->delete_vs_state(c
->pipe
, c
->vertex_shader
);
191 c
->pipe
->delete_fs_state(c
->pipe
, c
->fragment_shader
);
195 init_buffers(struct vl_compositor
*c
)
197 struct fragment_shader_consts fsc
;
202 * Create our vertex buffer and vertex buffer elements
204 c
->vertex_buf
.stride
= sizeof(struct vertex4f
);
205 c
->vertex_buf
.max_index
= (VL_COMPOSITOR_MAX_LAYERS
+ 2) * 6 - 1;
206 c
->vertex_buf
.buffer_offset
= 0;
207 c
->vertex_buf
.buffer
= pipe_buffer_create
211 PIPE_BUFFER_USAGE_VERTEX
,
212 sizeof(struct vertex4f
) * (VL_COMPOSITOR_MAX_LAYERS
+ 2) * 6
215 c
->vertex_elems
[0].src_offset
= 0;
216 c
->vertex_elems
[0].vertex_buffer_index
= 0;
217 c
->vertex_elems
[0].nr_components
= 2;
218 c
->vertex_elems
[0].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
219 c
->vertex_elems
[1].src_offset
= sizeof(struct vertex2f
);
220 c
->vertex_elems
[1].vertex_buffer_index
= 0;
221 c
->vertex_elems
[1].nr_components
= 2;
222 c
->vertex_elems
[1].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
225 * Create our fragment shader's constant buffer
226 * Const buffer contains the color conversion matrix and bias vectors
228 c
->fs_const_buf
.buffer
= pipe_buffer_create
232 PIPE_BUFFER_USAGE_CONSTANT
,
233 sizeof(struct fragment_shader_consts
)
236 vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_IDENTITY
, NULL
, true, fsc
.matrix
);
238 vl_compositor_set_csc_matrix(c
, fsc
.matrix
);
244 cleanup_buffers(struct vl_compositor
*c
)
248 pipe_buffer_reference(&c
->vertex_buf
.buffer
, NULL
);
249 pipe_buffer_reference(&c
->fs_const_buf
.buffer
, NULL
);
252 bool vl_compositor_init(struct vl_compositor
*compositor
, struct pipe_context
*pipe
)
258 memset(compositor
, 0, sizeof(struct vl_compositor
));
260 compositor
->pipe
= pipe
;
262 if (!init_pipe_state(compositor
))
264 if (!init_shaders(compositor
)) {
265 cleanup_pipe_state(compositor
);
268 if (!init_buffers(compositor
)) {
269 cleanup_shaders(compositor
);
270 cleanup_pipe_state(compositor
);
274 compositor
->fb_state
.width
= 0;
275 compositor
->fb_state
.height
= 0;
276 compositor
->bg
= NULL
;
277 compositor
->dirty_bg
= false;
278 for (i
= 0; i
< VL_COMPOSITOR_MAX_LAYERS
; ++i
)
279 compositor
->layers
[i
] = NULL
;
280 compositor
->dirty_layers
= 0;
285 void vl_compositor_cleanup(struct vl_compositor
*compositor
)
289 cleanup_buffers(compositor
);
290 cleanup_shaders(compositor
);
291 cleanup_pipe_state(compositor
);
294 void vl_compositor_set_background(struct vl_compositor
*compositor
,
295 struct pipe_texture
*bg
, struct pipe_video_rect
*bg_src_rect
)
298 assert((bg
&& bg_src_rect
) || (!bg
&& !bg_src_rect
));
300 if (compositor
->bg
!= bg
||
301 !u_video_rects_equal(&compositor
->bg_src_rect
, bg_src_rect
)) {
302 pipe_texture_reference(&compositor
->bg
, bg
);
303 /*if (!u_video_rects_equal(&compositor->bg_src_rect, bg_src_rect))*/
304 compositor
->bg_src_rect
= *bg_src_rect
;
305 compositor
->dirty_bg
= true;
309 void vl_compositor_set_layers(struct vl_compositor
*compositor
,
310 struct pipe_texture
*layers
[],
311 struct pipe_video_rect
*src_rects
[],
312 struct pipe_video_rect
*dst_rects
[],
318 assert(num_layers
<= VL_COMPOSITOR_MAX_LAYERS
);
320 for (i
= 0; i
< num_layers
; ++i
)
322 assert((layers
[i
] && src_rects
[i
] && dst_rects
[i
]) ||
323 (!layers
[i
] && !src_rects
[i
] && !dst_rects
[i
]));
325 if (compositor
->layers
[i
] != layers
[i
] ||
326 !u_video_rects_equal(&compositor
->layer_src_rects
[i
], src_rects
[i
]) ||
327 !u_video_rects_equal(&compositor
->layer_dst_rects
[i
], dst_rects
[i
]))
329 pipe_texture_reference(&compositor
->layers
[i
], layers
[i
]);
330 /*if (!u_video_rects_equal(&compositor->layer_src_rects[i], src_rects[i]))*/
331 compositor
->layer_src_rects
[i
] = *src_rects
[i
];
332 /*if (!u_video_rects_equal(&compositor->layer_dst_rects[i], dst_rects[i]))*/
333 compositor
->layer_dst_rects
[i
] = *dst_rects
[i
];
334 compositor
->dirty_layers
|= 1 << i
;
338 for (; i
< VL_COMPOSITOR_MAX_LAYERS
; ++i
)
339 pipe_texture_reference(&compositor
->layers
[i
], NULL
);
342 static void gen_rect_verts(unsigned pos
,
343 struct pipe_video_rect
*src_rect
,
344 struct vertex2f
*src_inv_size
,
345 struct pipe_video_rect
*dst_rect
,
346 struct vertex2f
*dst_inv_size
,
349 assert(pos
< VL_COMPOSITOR_MAX_LAYERS
+ 2);
351 assert(src_inv_size
);
352 assert((dst_rect
&& dst_inv_size
) /*|| (!dst_rect && !dst_inv_size)*/);
355 vb
[pos
* 6 + 0].x
= dst_rect
->x
* dst_inv_size
->x
;
356 vb
[pos
* 6 + 0].y
= dst_rect
->y
* dst_inv_size
->y
;
357 vb
[pos
* 6 + 0].z
= src_rect
->x
* src_inv_size
->x
;
358 vb
[pos
* 6 + 0].w
= src_rect
->y
* src_inv_size
->y
;
360 vb
[pos
* 6 + 1].x
= dst_rect
->x
* dst_inv_size
->x
;
361 vb
[pos
* 6 + 1].y
= (dst_rect
->y
+ dst_rect
->h
) * dst_inv_size
->y
;
362 vb
[pos
* 6 + 1].z
= src_rect
->x
* src_inv_size
->x
;
363 vb
[pos
* 6 + 1].w
= (src_rect
->y
+ src_rect
->h
) * src_inv_size
->y
;
365 vb
[pos
* 6 + 2].x
= (dst_rect
->x
+ dst_rect
->w
) * dst_inv_size
->x
;
366 vb
[pos
* 6 + 2].y
= dst_rect
->y
* dst_inv_size
->y
;
367 vb
[pos
* 6 + 2].z
= (src_rect
->x
+ src_rect
->w
) * src_inv_size
->x
;
368 vb
[pos
* 6 + 2].w
= src_rect
->y
* src_inv_size
->y
;
370 vb
[pos
* 6 + 3].x
= (dst_rect
->x
+ dst_rect
->w
) * dst_inv_size
->x
;
371 vb
[pos
* 6 + 3].y
= dst_rect
->y
* dst_inv_size
->y
;
372 vb
[pos
* 6 + 3].z
= (src_rect
->x
+ src_rect
->w
) * src_inv_size
->x
;
373 vb
[pos
* 6 + 3].w
= src_rect
->y
* src_inv_size
->y
;
375 vb
[pos
* 6 + 4].x
= dst_rect
->x
* dst_inv_size
->x
;
376 vb
[pos
* 6 + 4].y
= (dst_rect
->y
+ dst_rect
->h
) * dst_inv_size
->y
;
377 vb
[pos
* 6 + 4].z
= src_rect
->x
* src_inv_size
->x
;
378 vb
[pos
* 6 + 4].w
= (src_rect
->y
+ src_rect
->h
) * src_inv_size
->y
;
380 vb
[pos
* 6 + 5].x
= (dst_rect
->x
+ dst_rect
->w
) * dst_inv_size
->x
;
381 vb
[pos
* 6 + 5].y
= (dst_rect
->y
+ dst_rect
->h
) * dst_inv_size
->y
;
382 vb
[pos
* 6 + 5].z
= (src_rect
->x
+ src_rect
->w
) * src_inv_size
->x
;
383 vb
[pos
* 6 + 5].w
= (src_rect
->y
+ src_rect
->h
) * src_inv_size
->y
;
386 static unsigned gen_data(struct vl_compositor
*c
,
387 struct pipe_texture
*src_surface
,
388 struct pipe_video_rect
*src_rect
,
389 struct pipe_video_rect
*dst_rect
,
390 struct pipe_texture
**textures
)
393 unsigned num_rects
= 0;
402 vb
= pipe_buffer_map(c
->pipe
->screen
, c
->vertex_buf
.buffer
,
403 PIPE_BUFFER_USAGE_CPU_WRITE
| PIPE_BUFFER_USAGE_DISCARD
);
409 struct vertex2f bg_inv_size
= {1.0f
/ c
->bg
->width0
, 1.0f
/ c
->bg
->height0
};
410 gen_rect_verts(num_rects
, &c
->bg_src_rect
, &bg_inv_size
, NULL
, NULL
, vb
);
411 textures
[num_rects
] = c
->bg
;
417 struct vertex2f src_inv_size
= { 1.0f
/ src_surface
->width0
, 1.0f
/ src_surface
->height0
};
418 gen_rect_verts(num_rects
, src_rect
, &src_inv_size
, dst_rect
, &c
->fb_inv_size
, vb
);
419 textures
[num_rects
] = src_surface
;
423 for (i
= 0; c
->dirty_layers
> 0; i
++) {
424 assert(i
< VL_COMPOSITOR_MAX_LAYERS
);
426 if (c
->dirty_layers
& (1 << i
)) {
427 struct vertex2f layer_inv_size
= {1.0f
/ c
->layers
[i
]->width0
, 1.0f
/ c
->layers
[i
]->height0
};
428 gen_rect_verts(num_rects
, &c
->layer_src_rects
[i
], &layer_inv_size
,
429 &c
->layer_dst_rects
[i
], &c
->fb_inv_size
, vb
);
430 textures
[num_rects
] = c
->layers
[i
];
432 c
->dirty_layers
&= ~(1 << i
);
436 pipe_buffer_unmap(c
->pipe
->screen
, c
->vertex_buf
.buffer
);
441 static void draw_layers(struct vl_compositor
*c
,
442 struct pipe_texture
*src_surface
,
443 struct pipe_video_rect
*src_rect
,
444 struct pipe_video_rect
*dst_rect
)
447 struct pipe_texture
*textures
[VL_COMPOSITOR_MAX_LAYERS
+ 2];
455 num_rects
= gen_data(c
, src_surface
, src_rect
, dst_rect
, textures
);
457 for (i
= 0; i
< num_rects
; ++i
) {
458 c
->pipe
->set_fragment_sampler_textures(c
->pipe
, 1, &textures
[i
]);
459 c
->pipe
->draw_arrays(c
->pipe
, PIPE_PRIM_TRIANGLES
, i
* 6, 6);
463 void vl_compositor_render(struct vl_compositor
*compositor
,
464 struct pipe_texture
*src_surface
,
465 enum pipe_mpeg12_picture_type picture_type
,
466 /*unsigned num_past_surfaces,
467 struct pipe_texture *past_surfaces,
468 unsigned num_future_surfaces,
469 struct pipe_texture *future_surfaces,*/
470 struct pipe_video_rect
*src_area
,
471 struct pipe_texture
*dst_surface
,
472 struct pipe_video_rect
*dst_area
,
473 struct pipe_fence_handle
**fence
)
480 assert(picture_type
== PIPE_MPEG12_PICTURE_TYPE_FRAME
);
482 if (compositor
->fb_state
.width
!= dst_surface
->width0
) {
483 compositor
->fb_inv_size
.x
= 1.0f
/ dst_surface
->width0
;
484 compositor
->fb_state
.width
= dst_surface
->width0
;
486 if (compositor
->fb_state
.height
!= dst_surface
->height0
) {
487 compositor
->fb_inv_size
.y
= 1.0f
/ dst_surface
->height0
;
488 compositor
->fb_state
.height
= dst_surface
->height0
;
491 compositor
->fb_state
.cbufs
[0] = compositor
->pipe
->screen
->get_tex_surface
493 compositor
->pipe
->screen
,
495 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ_WRITE
498 compositor
->viewport
.scale
[0] = compositor
->fb_state
.width
;
499 compositor
->viewport
.scale
[1] = compositor
->fb_state
.height
;
500 compositor
->viewport
.scale
[2] = 1;
501 compositor
->viewport
.scale
[3] = 1;
502 compositor
->viewport
.translate
[0] = 0;
503 compositor
->viewport
.translate
[1] = 0;
504 compositor
->viewport
.translate
[2] = 0;
505 compositor
->viewport
.translate
[3] = 0;
507 compositor
->pipe
->set_framebuffer_state(compositor
->pipe
, &compositor
->fb_state
);
508 compositor
->pipe
->set_viewport_state(compositor
->pipe
, &compositor
->viewport
);
509 compositor
->pipe
->bind_fragment_sampler_states(compositor
->pipe
, 1, &compositor
->sampler
);
510 compositor
->pipe
->bind_vs_state(compositor
->pipe
, compositor
->vertex_shader
);
511 compositor
->pipe
->bind_fs_state(compositor
->pipe
, compositor
->fragment_shader
);
512 compositor
->pipe
->set_vertex_buffers(compositor
->pipe
, 1, &compositor
->vertex_buf
);
513 compositor
->pipe
->set_vertex_elements(compositor
->pipe
, 2, compositor
->vertex_elems
);
514 compositor
->pipe
->set_constant_buffer(compositor
->pipe
, PIPE_SHADER_FRAGMENT
, 0, &compositor
->fs_const_buf
);
516 draw_layers(compositor
, src_surface
, src_area
, dst_area
);
518 assert(!compositor
->dirty_bg
&& !compositor
->dirty_layers
);
519 compositor
->pipe
->flush(compositor
->pipe
, PIPE_FLUSH_RENDER_CACHE
, fence
);
521 pipe_surface_reference(&compositor
->fb_state
.cbufs
[0], NULL
);
524 void vl_compositor_set_csc_matrix(struct vl_compositor
*compositor
, const float *mat
)
530 pipe_buffer_map(compositor
->pipe
->screen
, compositor
->fs_const_buf
.buffer
,
531 PIPE_BUFFER_USAGE_CPU_WRITE
| PIPE_BUFFER_USAGE_DISCARD
),
533 sizeof(struct fragment_shader_consts
)
536 pipe_buffer_unmap(compositor
->pipe
->screen
, compositor
->fs_const_buf
.buffer
);