vl_compositor.c revision 74a4e9089488e7f341d21053bbf2d4aa52b99b70
1/************************************************************************** 2 * 3 * Copyright 2009 Younes Manton. 4 * All Rights Reserved. 5 * 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: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 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. 25 * 26 **************************************************************************/ 27 28#include <assert.h> 29 30#include "pipe/p_compiler.h" 31#include "pipe/p_context.h" 32 33#include "util/u_memory.h" 34#include "util/u_draw.h" 35#include "util/u_surface.h" 36 37#include "tgsi/tgsi_ureg.h" 38 39#include "vl_csc.h" 40#include "vl_types.h" 41#include "vl_compositor.h" 42 43#define MIN_DIRTY (0) 44#define MAX_DIRTY (1 << 15) 45 46enum VS_OUTPUT 47{ 48 VS_O_VPOS, 49 VS_O_VTEX, 50 VS_O_COLOR, 51 VS_O_VTOP, 52 VS_O_VBOTTOM, 53}; 54 55typedef float csc_matrix[16]; 56 57static void * 58create_vert_shader(struct vl_compositor *c) 59{ 60 struct ureg_program *shader; 61 struct ureg_src vpos, vtex, color; 62 struct ureg_dst tmp; 63 struct ureg_dst o_vpos, o_vtex, o_color; 64 struct ureg_dst o_vtop, o_vbottom; 65 66 shader = ureg_create(TGSI_PROCESSOR_VERTEX); 67 if (!shader) 68 return false; 69 70 vpos = ureg_DECL_vs_input(shader, 0); 71 vtex = ureg_DECL_vs_input(shader, 1); 72 color = ureg_DECL_vs_input(shader, 2); 73 tmp = ureg_DECL_temporary(shader); 74 o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, VS_O_VPOS); 75 o_vtex = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX); 76 o_color = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, VS_O_COLOR); 77 o_vtop = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTOP); 78 o_vbottom = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VBOTTOM); 79 80 /* 81 * o_vpos = vpos 82 * o_vtex = vtex 83 * o_color = color 84 */ 85 ureg_MOV(shader, o_vpos, vpos); 86 ureg_MOV(shader, o_vtex, vtex); 87 ureg_MOV(shader, o_color, color); 88 89 /* 90 * tmp.x = vtex.w / 2 91 * tmp.y = vtex.w / 4 92 * 93 * o_vtop.x = vtex.x 94 * o_vtop.y = vtex.y * tmp.x + 0.25f 95 * o_vtop.z = vtex.y * tmp.y + 0.25f 96 * o_vtop.w = 1 / tmp.x 97 * 98 * o_vbottom.x = vtex.x 99 * o_vbottom.y = vtex.y * tmp.x - 0.25f 100 * o_vbottom.z = vtex.y * tmp.y - 0.25f 101 * o_vbottom.w = 1 / tmp.y 102 */ 103 ureg_MUL(shader, ureg_writemask(tmp, TGSI_WRITEMASK_X), 104 ureg_scalar(vtex, TGSI_SWIZZLE_W), ureg_imm1f(shader, 0.5f)); 105 ureg_MUL(shader, ureg_writemask(tmp, TGSI_WRITEMASK_Y), 106 ureg_scalar(vtex, TGSI_SWIZZLE_W), ureg_imm1f(shader, 0.25f)); 107 108 ureg_MOV(shader, ureg_writemask(o_vtop, TGSI_WRITEMASK_X), vtex); 109 ureg_MAD(shader, ureg_writemask(o_vtop, TGSI_WRITEMASK_Y), ureg_scalar(vtex, TGSI_SWIZZLE_Y), 110 ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X), ureg_imm1f(shader, 0.25f)); 111 ureg_MAD(shader, ureg_writemask(o_vtop, TGSI_WRITEMASK_Z), ureg_scalar(vtex, TGSI_SWIZZLE_Y), 112 ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_Y), ureg_imm1f(shader, 0.25f)); 113 ureg_RCP(shader, ureg_writemask(o_vtop, TGSI_WRITEMASK_W), 114 ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X)); 115 116 ureg_MOV(shader, ureg_writemask(o_vbottom, TGSI_WRITEMASK_X), vtex); 117 ureg_MAD(shader, ureg_writemask(o_vbottom, TGSI_WRITEMASK_Y), ureg_scalar(vtex, TGSI_SWIZZLE_Y), 118 ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X), ureg_imm1f(shader, -0.25f)); 119 ureg_MAD(shader, ureg_writemask(o_vbottom, TGSI_WRITEMASK_Z), ureg_scalar(vtex, TGSI_SWIZZLE_Y), 120 ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_Y), ureg_imm1f(shader, -0.25f)); 121 ureg_RCP(shader, ureg_writemask(o_vbottom, TGSI_WRITEMASK_W), 122 ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_Y)); 123 124 ureg_END(shader); 125 126 return ureg_create_shader_and_destroy(shader, c->pipe); 127} 128 129static void * 130create_frag_shader_video_buffer(struct vl_compositor *c) 131{ 132 struct ureg_program *shader; 133 struct ureg_src tc; 134 struct ureg_src csc[3]; 135 struct ureg_src sampler[3]; 136 struct ureg_dst texel; 137 struct ureg_dst fragment; 138 unsigned i; 139 140 shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); 141 if (!shader) 142 return false; 143 144 tc = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, 1, TGSI_INTERPOLATE_LINEAR); 145 for (i = 0; i < 3; ++i) { 146 csc[i] = ureg_DECL_constant(shader, i); 147 sampler[i] = ureg_DECL_sampler(shader, i); 148 } 149 texel = ureg_DECL_temporary(shader); 150 fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0); 151 152 /* 153 * texel.xyz = tex(tc, sampler[i]) 154 * fragment = csc * texel 155 */ 156 for (i = 0; i < 3; ++i) 157 ureg_TEX(shader, ureg_writemask(texel, TGSI_WRITEMASK_X << i), TGSI_TEXTURE_3D, tc, sampler[i]); 158 159 ureg_MOV(shader, ureg_writemask(texel, TGSI_WRITEMASK_W), ureg_imm1f(shader, 1.0f)); 160 161 for (i = 0; i < 3; ++i) 162 ureg_DP4(shader, ureg_writemask(fragment, TGSI_WRITEMASK_X << i), csc[i], ureg_src(texel)); 163 164 ureg_MOV(shader, ureg_writemask(fragment, TGSI_WRITEMASK_W), ureg_imm1f(shader, 1.0f)); 165 166 ureg_release_temporary(shader, texel); 167 ureg_END(shader); 168 169 return ureg_create_shader_and_destroy(shader, c->pipe); 170} 171 172static void * 173create_frag_shader_weave(struct vl_compositor *c) 174{ 175 struct ureg_program *shader; 176 struct ureg_src i_tc[2]; 177 struct ureg_src csc[3]; 178 struct ureg_src sampler[3]; 179 struct ureg_dst t_tc[2]; 180 struct ureg_dst t_texel[2]; 181 struct ureg_dst o_fragment; 182 unsigned i, j; 183 184 shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); 185 if (!shader) 186 return false; 187 188 i_tc[0] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTOP, TGSI_INTERPOLATE_LINEAR); 189 i_tc[1] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VBOTTOM, TGSI_INTERPOLATE_LINEAR); 190 191 for (i = 0; i < 3; ++i) { 192 csc[i] = ureg_DECL_constant(shader, i); 193 sampler[i] = ureg_DECL_sampler(shader, i); 194 } 195 196 for (i = 0; i < 2; ++i) { 197 t_tc[i] = ureg_DECL_temporary(shader); 198 t_texel[i] = ureg_DECL_temporary(shader); 199 } 200 o_fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0); 201 202 /* calculate the texture offsets 203 * t_tc.x = i_tc.x 204 * t_tc.y = (round(i_tc.y) + 0.5) / height * 2 205 */ 206 for (i = 0; i < 2; ++i) { 207 ureg_MOV(shader, ureg_writemask(t_tc[i], TGSI_WRITEMASK_X), i_tc[i]); 208 ureg_ROUND(shader, ureg_writemask(t_tc[i], TGSI_WRITEMASK_YZ), i_tc[i]); 209 ureg_MOV(shader, ureg_writemask(t_tc[i], TGSI_WRITEMASK_W), 210 ureg_imm1f(shader, i ? 0.75f : 0.25f)); 211 ureg_ADD(shader, ureg_writemask(t_tc[i], TGSI_WRITEMASK_YZ), 212 ureg_src(t_tc[i]), ureg_imm1f(shader, 0.5f)); 213 ureg_MUL(shader, ureg_writemask(t_tc[i], TGSI_WRITEMASK_Y), 214 ureg_src(t_tc[i]), ureg_scalar(i_tc[0], TGSI_SWIZZLE_W)); 215 ureg_MUL(shader, ureg_writemask(t_tc[i], TGSI_WRITEMASK_Z), 216 ureg_src(t_tc[i]), ureg_scalar(i_tc[1], TGSI_SWIZZLE_W)); 217 } 218 219 /* fetch the texels 220 * texel[0..1].x = tex(t_tc[0..1][0]) 221 * texel[0..1].y = tex(t_tc[0..1][1]) 222 * texel[0..1].z = tex(t_tc[0..1][2]) 223 */ 224 for (i = 0; i < 2; ++i) 225 for (j = 0; j < 3; ++j) { 226 struct ureg_src src = ureg_swizzle(ureg_src(t_tc[i]), 227 TGSI_SWIZZLE_X, j ? TGSI_SWIZZLE_Z : TGSI_SWIZZLE_Y, TGSI_SWIZZLE_W, TGSI_SWIZZLE_W); 228 229 ureg_TEX(shader, ureg_writemask(t_texel[i], TGSI_WRITEMASK_X << j), 230 TGSI_TEXTURE_3D, src, sampler[j]); 231 } 232 233 /* calculate linear interpolation factor 234 * factor = |round(i_tc.y) - i_tc.y| * 2 235 */ 236 ureg_ROUND(shader, ureg_writemask(t_tc[0], TGSI_WRITEMASK_YZ), i_tc[0]); 237 ureg_ADD(shader, ureg_writemask(t_tc[0], TGSI_WRITEMASK_YZ), 238 ureg_src(t_tc[0]), ureg_negate(i_tc[0])); 239 ureg_MUL(shader, ureg_writemask(t_tc[0], TGSI_WRITEMASK_XY), 240 ureg_abs(ureg_src(t_tc[0])), ureg_imm1f(shader, 2.0f)); 241 ureg_LRP(shader, t_texel[0], ureg_swizzle(ureg_src(t_tc[0]), 242 TGSI_SWIZZLE_Y, TGSI_SWIZZLE_Z, TGSI_SWIZZLE_Z, TGSI_SWIZZLE_Z), 243 ureg_src(t_texel[1]), ureg_src(t_texel[0])); 244 245 /* and finally do colour space transformation 246 * fragment = csc * texel 247 */ 248 ureg_MOV(shader, ureg_writemask(t_texel[0], TGSI_WRITEMASK_W), ureg_imm1f(shader, 1.0f)); 249 for (i = 0; i < 3; ++i) 250 ureg_DP4(shader, ureg_writemask(o_fragment, TGSI_WRITEMASK_X << i), csc[i], ureg_src(t_texel[0])); 251 252 ureg_MOV(shader, ureg_writemask(o_fragment, TGSI_WRITEMASK_W), ureg_imm1f(shader, 1.0f)); 253 254 for (i = 0; i < 2; ++i) { 255 ureg_release_temporary(shader, t_texel[i]); 256 ureg_release_temporary(shader, t_tc[i]); 257 } 258 259 ureg_END(shader); 260 261 return ureg_create_shader_and_destroy(shader, c->pipe); 262} 263 264static void * 265create_frag_shader_palette(struct vl_compositor *c, bool include_cc) 266{ 267 struct ureg_program *shader; 268 struct ureg_src csc[3]; 269 struct ureg_src tc; 270 struct ureg_src sampler; 271 struct ureg_src palette; 272 struct ureg_dst texel; 273 struct ureg_dst fragment; 274 unsigned i; 275 276 shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); 277 if (!shader) 278 return false; 279 280 for (i = 0; include_cc && i < 3; ++i) 281 csc[i] = ureg_DECL_constant(shader, i); 282 283 tc = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX, TGSI_INTERPOLATE_LINEAR); 284 sampler = ureg_DECL_sampler(shader, 0); 285 palette = ureg_DECL_sampler(shader, 1); 286 287 texel = ureg_DECL_temporary(shader); 288 fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0); 289 290 /* 291 * texel = tex(tc, sampler) 292 * fragment.xyz = tex(texel, palette) * csc 293 * fragment.a = texel.a 294 */ 295 ureg_TEX(shader, texel, TGSI_TEXTURE_2D, tc, sampler); 296 ureg_MOV(shader, ureg_writemask(fragment, TGSI_WRITEMASK_W), ureg_src(texel)); 297 298 if (include_cc) { 299 ureg_TEX(shader, texel, TGSI_TEXTURE_1D, ureg_src(texel), palette); 300 for (i = 0; i < 3; ++i) 301 ureg_DP4(shader, ureg_writemask(fragment, TGSI_WRITEMASK_X << i), csc[i], ureg_src(texel)); 302 } else { 303 ureg_TEX(shader, ureg_writemask(fragment, TGSI_WRITEMASK_XYZ), 304 TGSI_TEXTURE_1D, ureg_src(texel), palette); 305 } 306 307 ureg_release_temporary(shader, texel); 308 ureg_END(shader); 309 310 return ureg_create_shader_and_destroy(shader, c->pipe); 311} 312 313static void * 314create_frag_shader_rgba(struct vl_compositor *c) 315{ 316 struct ureg_program *shader; 317 struct ureg_src tc, color, sampler; 318 struct ureg_dst texel, fragment; 319 320 shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); 321 if (!shader) 322 return false; 323 324 tc = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX, TGSI_INTERPOLATE_LINEAR); 325 color = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_COLOR, VS_O_COLOR, TGSI_INTERPOLATE_LINEAR); 326 sampler = ureg_DECL_sampler(shader, 0); 327 texel = ureg_DECL_temporary(shader); 328 fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0); 329 330 /* 331 * fragment = tex(tc, sampler) 332 */ 333 ureg_TEX(shader, texel, TGSI_TEXTURE_2D, tc, sampler); 334 ureg_MUL(shader, fragment, ureg_src(texel), color); 335 ureg_END(shader); 336 337 return ureg_create_shader_and_destroy(shader, c->pipe); 338} 339 340static bool 341init_shaders(struct vl_compositor *c) 342{ 343 assert(c); 344 345 c->vs = create_vert_shader(c); 346 if (!c->vs) { 347 debug_printf("Unable to create vertex shader.\n"); 348 return false; 349 } 350 351 c->fs_video_buffer = create_frag_shader_video_buffer(c); 352 if (!c->fs_video_buffer) { 353 debug_printf("Unable to create YCbCr-to-RGB fragment shader.\n"); 354 return false; 355 } 356 357 c->fs_weave = create_frag_shader_weave(c); 358 if (!c->fs_weave) { 359 debug_printf("Unable to create YCbCr-to-RGB weave fragment shader.\n"); 360 return false; 361 } 362 363 c->fs_palette.yuv = create_frag_shader_palette(c, true); 364 if (!c->fs_palette.yuv) { 365 debug_printf("Unable to create YUV-Palette-to-RGB fragment shader.\n"); 366 return false; 367 } 368 369 c->fs_palette.rgb = create_frag_shader_palette(c, false); 370 if (!c->fs_palette.rgb) { 371 debug_printf("Unable to create RGB-Palette-to-RGB fragment shader.\n"); 372 return false; 373 } 374 375 c->fs_rgba = create_frag_shader_rgba(c); 376 if (!c->fs_rgba) { 377 debug_printf("Unable to create RGB-to-RGB fragment shader.\n"); 378 return false; 379 } 380 381 return true; 382} 383 384static void cleanup_shaders(struct vl_compositor *c) 385{ 386 assert(c); 387 388 c->pipe->delete_vs_state(c->pipe, c->vs); 389 c->pipe->delete_fs_state(c->pipe, c->fs_video_buffer); 390 c->pipe->delete_fs_state(c->pipe, c->fs_weave); 391 c->pipe->delete_fs_state(c->pipe, c->fs_palette.yuv); 392 c->pipe->delete_fs_state(c->pipe, c->fs_palette.rgb); 393 c->pipe->delete_fs_state(c->pipe, c->fs_rgba); 394} 395 396static bool 397init_pipe_state(struct vl_compositor *c) 398{ 399 struct pipe_rasterizer_state rast; 400 struct pipe_sampler_state sampler; 401 struct pipe_blend_state blend; 402 struct pipe_depth_stencil_alpha_state dsa; 403 unsigned i; 404 405 assert(c); 406 407 c->fb_state.nr_cbufs = 1; 408 c->fb_state.zsbuf = NULL; 409 410 memset(&sampler, 0, sizeof(sampler)); 411 sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 412 sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 413 sampler.wrap_r = PIPE_TEX_WRAP_REPEAT; 414 sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR; 415 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; 416 sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR; 417 sampler.compare_mode = PIPE_TEX_COMPARE_NONE; 418 sampler.compare_func = PIPE_FUNC_ALWAYS; 419 sampler.normalized_coords = 1; 420 421 c->sampler_linear = c->pipe->create_sampler_state(c->pipe, &sampler); 422 423 sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; 424 sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; 425 c->sampler_nearest = c->pipe->create_sampler_state(c->pipe, &sampler); 426 427 memset(&blend, 0, sizeof blend); 428 blend.independent_blend_enable = 0; 429 blend.rt[0].blend_enable = 0; 430 blend.logicop_enable = 0; 431 blend.logicop_func = PIPE_LOGICOP_CLEAR; 432 blend.rt[0].colormask = PIPE_MASK_RGBA; 433 blend.dither = 0; 434 c->blend_clear = c->pipe->create_blend_state(c->pipe, &blend); 435 436 blend.rt[0].blend_enable = 1; 437 blend.rt[0].rgb_func = PIPE_BLEND_ADD; 438 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA; 439 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; 440 blend.rt[0].alpha_func = PIPE_BLEND_ADD; 441 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; 442 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE; 443 c->blend_add = c->pipe->create_blend_state(c->pipe, &blend); 444 445 memset(&rast, 0, sizeof rast); 446 rast.flatshade = 0; 447 rast.front_ccw = 1; 448 rast.cull_face = PIPE_FACE_NONE; 449 rast.fill_back = PIPE_POLYGON_MODE_FILL; 450 rast.fill_front = PIPE_POLYGON_MODE_FILL; 451 rast.scissor = 1; 452 rast.line_width = 1; 453 rast.point_size_per_vertex = 1; 454 rast.offset_units = 1; 455 rast.offset_scale = 1; 456 rast.gl_rasterization_rules = 1; 457 rast.depth_clip = 1; 458 459 c->rast = c->pipe->create_rasterizer_state(c->pipe, &rast); 460 461 memset(&dsa, 0, sizeof dsa); 462 dsa.depth.enabled = 0; 463 dsa.depth.writemask = 0; 464 dsa.depth.func = PIPE_FUNC_ALWAYS; 465 for (i = 0; i < 2; ++i) { 466 dsa.stencil[i].enabled = 0; 467 dsa.stencil[i].func = PIPE_FUNC_ALWAYS; 468 dsa.stencil[i].fail_op = PIPE_STENCIL_OP_KEEP; 469 dsa.stencil[i].zpass_op = PIPE_STENCIL_OP_KEEP; 470 dsa.stencil[i].zfail_op = PIPE_STENCIL_OP_KEEP; 471 dsa.stencil[i].valuemask = 0; 472 dsa.stencil[i].writemask = 0; 473 } 474 dsa.alpha.enabled = 0; 475 dsa.alpha.func = PIPE_FUNC_ALWAYS; 476 dsa.alpha.ref_value = 0; 477 c->dsa = c->pipe->create_depth_stencil_alpha_state(c->pipe, &dsa); 478 c->pipe->bind_depth_stencil_alpha_state(c->pipe, c->dsa); 479 480 return true; 481} 482 483static void cleanup_pipe_state(struct vl_compositor *c) 484{ 485 assert(c); 486 487 /* Asserted in softpipe_delete_fs_state() for some reason */ 488 c->pipe->bind_vs_state(c->pipe, NULL); 489 c->pipe->bind_fs_state(c->pipe, NULL); 490 491 c->pipe->delete_depth_stencil_alpha_state(c->pipe, c->dsa); 492 c->pipe->delete_sampler_state(c->pipe, c->sampler_linear); 493 c->pipe->delete_sampler_state(c->pipe, c->sampler_nearest); 494 c->pipe->delete_blend_state(c->pipe, c->blend_clear); 495 c->pipe->delete_blend_state(c->pipe, c->blend_add); 496 c->pipe->delete_rasterizer_state(c->pipe, c->rast); 497} 498 499static bool 500create_vertex_buffer(struct vl_compositor *c) 501{ 502 assert(c); 503 504 pipe_resource_reference(&c->vertex_buf.buffer, NULL); 505 c->vertex_buf.buffer = pipe_buffer_create 506 ( 507 c->pipe->screen, 508 PIPE_BIND_VERTEX_BUFFER, 509 PIPE_USAGE_STREAM, 510 c->vertex_buf.stride * VL_COMPOSITOR_MAX_LAYERS * 4 511 ); 512 513 return c->vertex_buf.buffer != NULL; 514} 515 516static bool 517init_buffers(struct vl_compositor *c) 518{ 519 struct pipe_vertex_element vertex_elems[3]; 520 521 assert(c); 522 523 /* 524 * Create our vertex buffer and vertex buffer elements 525 */ 526 c->vertex_buf.stride = sizeof(struct vertex2f) + sizeof(struct vertex4f) * 2; 527 c->vertex_buf.buffer_offset = 0; 528 create_vertex_buffer(c); 529 530 vertex_elems[0].src_offset = 0; 531 vertex_elems[0].instance_divisor = 0; 532 vertex_elems[0].vertex_buffer_index = 0; 533 vertex_elems[0].src_format = PIPE_FORMAT_R32G32_FLOAT; 534 vertex_elems[1].src_offset = sizeof(struct vertex2f); 535 vertex_elems[1].instance_divisor = 0; 536 vertex_elems[1].vertex_buffer_index = 0; 537 vertex_elems[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; 538 vertex_elems[2].src_offset = sizeof(struct vertex2f) + sizeof(struct vertex4f); 539 vertex_elems[2].instance_divisor = 0; 540 vertex_elems[2].vertex_buffer_index = 0; 541 vertex_elems[2].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; 542 c->vertex_elems_state = c->pipe->create_vertex_elements_state(c->pipe, 3, vertex_elems); 543 544 return true; 545} 546 547static void 548cleanup_buffers(struct vl_compositor *c) 549{ 550 assert(c); 551 552 c->pipe->delete_vertex_elements_state(c->pipe, c->vertex_elems_state); 553 pipe_resource_reference(&c->vertex_buf.buffer, NULL); 554} 555 556static INLINE struct u_rect 557default_rect(struct vl_compositor_layer *layer) 558{ 559 struct pipe_resource *res = layer->sampler_views[0]->texture; 560 struct u_rect rect = { 0, res->width0, 0, res->height0 * res->depth0 }; 561 return rect; 562} 563 564static INLINE struct vertex2f 565calc_topleft(struct vertex2f size, struct u_rect rect) 566{ 567 struct vertex2f res = { rect.x0 / size.x, rect.y0 / size.y }; 568 return res; 569} 570 571static INLINE struct vertex2f 572calc_bottomright(struct vertex2f size, struct u_rect rect) 573{ 574 struct vertex2f res = { rect.x1 / size.x, rect.y1 / size.y }; 575 return res; 576} 577 578static INLINE void 579calc_src_and_dst(struct vl_compositor_layer *layer, unsigned width, unsigned height, 580 struct u_rect src, struct u_rect dst) 581{ 582 struct vertex2f size = { width, height }; 583 584 layer->src.tl = calc_topleft(size, src); 585 layer->src.br = calc_bottomright(size, src); 586 layer->dst.tl = calc_topleft(size, dst); 587 layer->dst.br = calc_bottomright(size, dst); 588 layer->zw.x = 0.0f; 589 layer->zw.y = size.y; 590} 591 592static void 593gen_rect_verts(struct vertex2f *vb, struct vl_compositor_layer *layer) 594{ 595 assert(vb && layer); 596 597 vb[ 0].x = layer->dst.tl.x; 598 vb[ 0].y = layer->dst.tl.y; 599 vb[ 1].x = layer->src.tl.x; 600 vb[ 1].y = layer->src.tl.y; 601 vb[ 2] = layer->zw; 602 vb[ 3].x = layer->colors[0].x; 603 vb[ 3].y = layer->colors[0].y; 604 vb[ 4].x = layer->colors[0].z; 605 vb[ 4].y = layer->colors[0].w; 606 607 vb[ 5].x = layer->dst.br.x; 608 vb[ 5].y = layer->dst.tl.y; 609 vb[ 6].x = layer->src.br.x; 610 vb[ 6].y = layer->src.tl.y; 611 vb[ 7] = layer->zw; 612 vb[ 8].x = layer->colors[1].x; 613 vb[ 8].y = layer->colors[1].y; 614 vb[ 9].x = layer->colors[1].z; 615 vb[ 9].y = layer->colors[1].w; 616 617 vb[10].x = layer->dst.br.x; 618 vb[10].y = layer->dst.br.y; 619 vb[11].x = layer->src.br.x; 620 vb[11].y = layer->src.br.y; 621 vb[12] = layer->zw; 622 vb[13].x = layer->colors[2].x; 623 vb[13].y = layer->colors[2].y; 624 vb[14].x = layer->colors[2].z; 625 vb[14].y = layer->colors[2].w; 626 627 vb[15].x = layer->dst.tl.x; 628 vb[15].y = layer->dst.br.y; 629 vb[16].x = layer->src.tl.x; 630 vb[16].y = layer->src.br.y; 631 vb[17] = layer->zw; 632 vb[18].x = layer->colors[3].x; 633 vb[18].y = layer->colors[3].y; 634 vb[19].x = layer->colors[3].z; 635 vb[19].y = layer->colors[3].w; 636} 637 638static INLINE struct u_rect 639calc_drawn_area(struct vl_compositor_state *s, struct vl_compositor_layer *layer) 640{ 641 struct u_rect result; 642 643 // scale 644 result.x0 = layer->dst.tl.x * layer->viewport.scale[0] + layer->viewport.translate[0]; 645 result.y0 = layer->dst.tl.y * layer->viewport.scale[1] + layer->viewport.translate[1]; 646 result.x1 = layer->dst.br.x * layer->viewport.scale[0] + layer->viewport.translate[0]; 647 result.y1 = layer->dst.br.y * layer->viewport.scale[1] + layer->viewport.translate[1]; 648 649 // and clip 650 result.x0 = MAX2(result.x0, s->scissor.minx); 651 result.y0 = MAX2(result.y0, s->scissor.miny); 652 result.x1 = MIN2(result.x1, s->scissor.maxx); 653 result.y1 = MIN2(result.y1, s->scissor.maxy); 654 return result; 655} 656 657static void 658gen_vertex_data(struct vl_compositor *c, struct vl_compositor_state *s, struct u_rect *dirty) 659{ 660 struct vertex2f *vb; 661 struct pipe_transfer *buf_transfer; 662 unsigned i; 663 664 assert(c); 665 666 vb = pipe_buffer_map(c->pipe, c->vertex_buf.buffer, 667 PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE | PIPE_TRANSFER_DONTBLOCK, 668 &buf_transfer); 669 670 if (!vb) { 671 // If buffer is still locked from last draw create a new one 672 create_vertex_buffer(c); 673 vb = pipe_buffer_map(c->pipe, c->vertex_buf.buffer, 674 PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE, 675 &buf_transfer); 676 } 677 678 for (i = 0; i < VL_COMPOSITOR_MAX_LAYERS; i++) { 679 if (s->used_layers & (1 << i)) { 680 struct vl_compositor_layer *layer = &s->layers[i]; 681 gen_rect_verts(vb, layer); 682 vb += 20; 683 684 if (!layer->viewport_valid) { 685 layer->viewport.scale[0] = c->fb_state.width; 686 layer->viewport.scale[1] = c->fb_state.height; 687 layer->viewport.translate[0] = 0; 688 layer->viewport.translate[1] = 0; 689 } 690 691 if (dirty && layer->clearing) { 692 struct u_rect drawn = calc_drawn_area(s, layer); 693 if ( 694 dirty->x0 >= drawn.x0 && 695 dirty->y0 >= drawn.y0 && 696 dirty->x1 <= drawn.x1 && 697 dirty->y1 <= drawn.y1) { 698 699 // We clear the dirty area anyway, no need for clear_render_target 700 dirty->x0 = dirty->y0 = MAX_DIRTY; 701 dirty->x1 = dirty->y1 = MIN_DIRTY; 702 } 703 } 704 } 705 } 706 707 pipe_buffer_unmap(c->pipe, buf_transfer); 708} 709 710static void 711draw_layers(struct vl_compositor *c, struct vl_compositor_state *s, struct u_rect *dirty) 712{ 713 unsigned vb_index, i; 714 715 assert(c); 716 717 for (i = 0, vb_index = 0; i < VL_COMPOSITOR_MAX_LAYERS; ++i) { 718 if (s->used_layers & (1 << i)) { 719 struct vl_compositor_layer *layer = &s->layers[i]; 720 struct pipe_sampler_view **samplers = &layer->sampler_views[0]; 721 unsigned num_sampler_views = !samplers[1] ? 1 : !samplers[2] ? 2 : 3; 722 void *blend = layer->blend ? layer->blend : i ? c->blend_add : c->blend_clear; 723 724 c->pipe->bind_blend_state(c->pipe, blend); 725 c->pipe->set_viewport_state(c->pipe, &layer->viewport); 726 c->pipe->bind_fs_state(c->pipe, layer->fs); 727 c->pipe->bind_fragment_sampler_states(c->pipe, num_sampler_views, layer->samplers); 728 c->pipe->set_fragment_sampler_views(c->pipe, num_sampler_views, samplers); 729 util_draw_arrays(c->pipe, PIPE_PRIM_QUADS, vb_index * 4, 4); 730 vb_index++; 731 732 if (dirty) { 733 // Remember the currently drawn area as dirty for the next draw command 734 struct u_rect drawn = calc_drawn_area(s, layer); 735 dirty->x0 = MIN2(drawn.x0, dirty->x0); 736 dirty->y0 = MIN2(drawn.y0, dirty->y0); 737 dirty->x1 = MAX2(drawn.x1, dirty->x1); 738 dirty->y1 = MAX2(drawn.y1, dirty->y1); 739 } 740 } 741 } 742} 743 744void 745vl_compositor_reset_dirty_area(struct u_rect *dirty) 746{ 747 assert(dirty); 748 749 dirty->x0 = dirty->y0 = MIN_DIRTY; 750 dirty->x1 = dirty->y1 = MAX_DIRTY; 751} 752 753void 754vl_compositor_set_clear_color(struct vl_compositor_state *s, union pipe_color_union *color) 755{ 756 assert(s); 757 assert(color); 758 759 s->clear_color = *color; 760} 761 762void 763vl_compositor_get_clear_color(struct vl_compositor_state *s, union pipe_color_union *color) 764{ 765 assert(s); 766 assert(color); 767 768 *color = s->clear_color; 769} 770 771void 772vl_compositor_clear_layers(struct vl_compositor_state *s) 773{ 774 unsigned i, j; 775 776 assert(s); 777 778 s->used_layers = 0; 779 for ( i = 0; i < VL_COMPOSITOR_MAX_LAYERS; ++i) { 780 struct vertex4f v_one = { 1.0f, 1.0f, 1.0f, 1.0f }; 781 s->layers[i].clearing = i ? false : true; 782 s->layers[i].blend = NULL; 783 s->layers[i].fs = NULL; 784 s->layers[i].viewport.scale[2] = 1; 785 s->layers[i].viewport.scale[3] = 1; 786 s->layers[i].viewport.translate[2] = 0; 787 s->layers[i].viewport.translate[3] = 0; 788 789 for ( j = 0; j < 3; j++) 790 pipe_sampler_view_reference(&s->layers[i].sampler_views[j], NULL); 791 for ( j = 0; j < 4; ++j) 792 s->layers[i].colors[j] = v_one; 793 } 794} 795 796void 797vl_compositor_cleanup(struct vl_compositor *c) 798{ 799 assert(c); 800 801 cleanup_buffers(c); 802 cleanup_shaders(c); 803 cleanup_pipe_state(c); 804} 805 806void 807vl_compositor_set_csc_matrix(struct vl_compositor_state *s, const float matrix[16]) 808{ 809 struct pipe_transfer *buf_transfer; 810 811 assert(s); 812 813 memcpy 814 ( 815 pipe_buffer_map(s->pipe, s->csc_matrix, 816 PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE, 817 &buf_transfer), 818 matrix, 819 sizeof(csc_matrix) 820 ); 821 822 pipe_buffer_unmap(s->pipe, buf_transfer); 823} 824 825void 826vl_compositor_set_dst_clip(struct vl_compositor_state *s, struct u_rect *dst_clip) 827{ 828 assert(s); 829 830 s->scissor_valid = dst_clip != NULL; 831 if (dst_clip) { 832 s->scissor.minx = dst_clip->x0; 833 s->scissor.miny = dst_clip->y0; 834 s->scissor.maxx = dst_clip->x1; 835 s->scissor.maxy = dst_clip->y1; 836 } 837} 838 839void 840vl_compositor_set_layer_blend(struct vl_compositor_state *s, 841 unsigned layer, void *blend, 842 bool is_clearing) 843{ 844 assert(s && blend); 845 846 assert(layer < VL_COMPOSITOR_MAX_LAYERS); 847 848 s->layers[layer].clearing = is_clearing; 849 s->layers[layer].blend = blend; 850} 851 852void 853vl_compositor_set_layer_dst_area(struct vl_compositor_state *s, 854 unsigned layer, struct u_rect *dst_area) 855{ 856 assert(s); 857 858 assert(layer < VL_COMPOSITOR_MAX_LAYERS); 859 860 s->layers[layer].viewport_valid = dst_area != NULL; 861 if (dst_area) { 862 s->layers[layer].viewport.scale[0] = dst_area->x1 - dst_area->x0; 863 s->layers[layer].viewport.scale[1] = dst_area->y1 - dst_area->y0; 864 s->layers[layer].viewport.translate[0] = dst_area->x0; 865 s->layers[layer].viewport.translate[1] = dst_area->y0; 866 } 867} 868 869void 870vl_compositor_set_buffer_layer(struct vl_compositor_state *s, 871 struct vl_compositor *c, 872 unsigned layer, 873 struct pipe_video_buffer *buffer, 874 struct u_rect *src_rect, 875 struct u_rect *dst_rect, 876 enum vl_compositor_deinterlace deinterlace) 877{ 878 struct pipe_sampler_view **sampler_views; 879 unsigned i; 880 881 assert(s && c && buffer); 882 883 assert(layer < VL_COMPOSITOR_MAX_LAYERS); 884 885 s->used_layers |= 1 << layer; 886 sampler_views = buffer->get_sampler_view_components(buffer); 887 for (i = 0; i < 3; ++i) { 888 s->layers[layer].samplers[i] = c->sampler_linear; 889 pipe_sampler_view_reference(&s->layers[layer].sampler_views[i], sampler_views[i]); 890 } 891 892 calc_src_and_dst(&s->layers[layer], buffer->width, buffer->height, 893 src_rect ? *src_rect : default_rect(&s->layers[layer]), 894 dst_rect ? *dst_rect : default_rect(&s->layers[layer])); 895 896 if (buffer->interlaced) { 897 float half_a_line = 0.5f / s->layers[layer].zw.y; 898 switch(deinterlace) { 899 case VL_COMPOSITOR_WEAVE: 900 s->layers[layer].fs = c->fs_weave; 901 break; 902 903 case VL_COMPOSITOR_BOB_TOP: 904 s->layers[layer].zw.x = 0.25f; 905 s->layers[layer].src.tl.y += half_a_line; 906 s->layers[layer].src.br.y += half_a_line; 907 s->layers[layer].fs = c->fs_video_buffer; 908 break; 909 910 case VL_COMPOSITOR_BOB_BOTTOM: 911 s->layers[layer].zw.x = 0.75f; 912 s->layers[layer].src.tl.y -= half_a_line; 913 s->layers[layer].src.br.y -= half_a_line; 914 s->layers[layer].fs = c->fs_video_buffer; 915 break; 916 } 917 918 } else 919 s->layers[layer].fs = c->fs_video_buffer; 920} 921 922void 923vl_compositor_set_palette_layer(struct vl_compositor_state *s, 924 struct vl_compositor *c, 925 unsigned layer, 926 struct pipe_sampler_view *indexes, 927 struct pipe_sampler_view *palette, 928 struct u_rect *src_rect, 929 struct u_rect *dst_rect, 930 bool include_color_conversion) 931{ 932 assert(s && c && indexes && palette); 933 934 assert(layer < VL_COMPOSITOR_MAX_LAYERS); 935 936 s->used_layers |= 1 << layer; 937 938 s->layers[layer].fs = include_color_conversion ? 939 c->fs_palette.yuv : c->fs_palette.rgb; 940 941 s->layers[layer].samplers[0] = c->sampler_linear; 942 s->layers[layer].samplers[1] = c->sampler_nearest; 943 s->layers[layer].samplers[2] = NULL; 944 pipe_sampler_view_reference(&s->layers[layer].sampler_views[0], indexes); 945 pipe_sampler_view_reference(&s->layers[layer].sampler_views[1], palette); 946 pipe_sampler_view_reference(&s->layers[layer].sampler_views[2], NULL); 947 calc_src_and_dst(&s->layers[layer], indexes->texture->width0, indexes->texture->height0, 948 src_rect ? *src_rect : default_rect(&s->layers[layer]), 949 dst_rect ? *dst_rect : default_rect(&s->layers[layer])); 950} 951 952void 953vl_compositor_set_rgba_layer(struct vl_compositor_state *s, 954 struct vl_compositor *c, 955 unsigned layer, 956 struct pipe_sampler_view *rgba, 957 struct u_rect *src_rect, 958 struct u_rect *dst_rect, 959 struct vertex4f *colors) 960{ 961 unsigned i; 962 963 assert(s && c && rgba); 964 965 assert(layer < VL_COMPOSITOR_MAX_LAYERS); 966 967 s->used_layers |= 1 << layer; 968 s->layers[layer].fs = c->fs_rgba; 969 s->layers[layer].samplers[0] = c->sampler_linear; 970 s->layers[layer].samplers[1] = NULL; 971 s->layers[layer].samplers[2] = NULL; 972 pipe_sampler_view_reference(&s->layers[layer].sampler_views[0], rgba); 973 pipe_sampler_view_reference(&s->layers[layer].sampler_views[1], NULL); 974 pipe_sampler_view_reference(&s->layers[layer].sampler_views[2], NULL); 975 calc_src_and_dst(&s->layers[layer], rgba->texture->width0, rgba->texture->height0, 976 src_rect ? *src_rect : default_rect(&s->layers[layer]), 977 dst_rect ? *dst_rect : default_rect(&s->layers[layer])); 978 979 if (colors) 980 for (i = 0; i < 4; ++i) 981 s->layers[layer].colors[i] = colors[i]; 982} 983 984void 985vl_compositor_render(struct vl_compositor_state *s, 986 struct vl_compositor *c, 987 struct pipe_surface *dst_surface, 988 struct u_rect *dirty_area) 989{ 990 assert(c); 991 assert(dst_surface); 992 993 c->fb_state.width = dst_surface->width; 994 c->fb_state.height = dst_surface->height; 995 c->fb_state.cbufs[0] = dst_surface; 996 997 if (!s->scissor_valid) { 998 s->scissor.minx = 0; 999 s->scissor.miny = 0; 1000 s->scissor.maxx = dst_surface->width; 1001 s->scissor.maxy = dst_surface->height; 1002 } 1003 1004 gen_vertex_data(c, s, dirty_area); 1005 1006 if (dirty_area && (dirty_area->x0 < dirty_area->x1 || 1007 dirty_area->y0 < dirty_area->y1)) { 1008 1009 c->pipe->clear_render_target(c->pipe, dst_surface, &s->clear_color, 1010 0, 0, dst_surface->width, dst_surface->height); 1011 dirty_area->x0 = dirty_area->y0 = MAX_DIRTY; 1012 dirty_area->x1 = dirty_area->y1 = MIN_DIRTY; 1013 } 1014 1015 c->pipe->set_scissor_state(c->pipe, &s->scissor); 1016 c->pipe->set_framebuffer_state(c->pipe, &c->fb_state); 1017 c->pipe->bind_vs_state(c->pipe, c->vs); 1018 c->pipe->set_vertex_buffers(c->pipe, 1, &c->vertex_buf); 1019 c->pipe->bind_vertex_elements_state(c->pipe, c->vertex_elems_state); 1020 c->pipe->set_constant_buffer(c->pipe, PIPE_SHADER_FRAGMENT, 0, s->csc_matrix); 1021 c->pipe->bind_rasterizer_state(c->pipe, c->rast); 1022 1023 draw_layers(c, s, dirty_area); 1024} 1025 1026bool 1027vl_compositor_init(struct vl_compositor *c, struct pipe_context *pipe) 1028{ 1029 assert(c); 1030 1031 memset(c, 0, sizeof(*c)); 1032 1033 c->pipe = pipe; 1034 1035 if (!init_pipe_state(c)) 1036 return false; 1037 1038 if (!init_shaders(c)) { 1039 cleanup_pipe_state(c); 1040 return false; 1041 } 1042 1043 if (!init_buffers(c)) { 1044 cleanup_shaders(c); 1045 cleanup_pipe_state(c); 1046 return false; 1047 } 1048 1049 return true; 1050} 1051 1052bool 1053vl_compositor_init_state(struct vl_compositor_state *s, struct pipe_context *pipe) 1054{ 1055 csc_matrix csc_matrix; 1056 1057 assert(s); 1058 1059 memset(s, 0, sizeof(*s)); 1060 1061 s->pipe = pipe; 1062 1063 s->clear_color.f[0] = s->clear_color.f[1] = 0.0f; 1064 s->clear_color.f[2] = s->clear_color.f[3] = 0.0f; 1065 1066 /* 1067 * Create our fragment shader's constant buffer 1068 * Const buffer contains the color conversion matrix and bias vectors 1069 */ 1070 /* XXX: Create with IMMUTABLE/STATIC... although it does change every once in a long while... */ 1071 s->csc_matrix = pipe_buffer_create 1072 ( 1073 pipe->screen, 1074 PIPE_BIND_CONSTANT_BUFFER, 1075 PIPE_USAGE_STATIC, 1076 sizeof(csc_matrix) 1077 ); 1078 1079 vl_compositor_clear_layers(s); 1080 1081 vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_IDENTITY, NULL, true, csc_matrix); 1082 vl_compositor_set_csc_matrix(s, csc_matrix); 1083 1084 return true; 1085} 1086 1087void 1088vl_compositor_cleanup_state(struct vl_compositor_state *s) 1089{ 1090 assert(s); 1091 1092 vl_compositor_clear_layers(s); 1093 pipe_resource_reference(&s->csc_matrix, NULL); 1094} 1095