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