vl_compositor.c revision 3841d3fd1358cd3ecbe71d173e52551420a07f4e
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->size = size; 583} 584 585static void 586gen_rect_verts(struct vertex2f *vb, struct vl_compositor_layer *layer) 587{ 588 assert(vb && layer); 589 590 vb[ 0].x = layer->dst.tl.x; 591 vb[ 0].y = layer->dst.tl.y; 592 vb[ 1].x = layer->src.tl.x; 593 vb[ 1].y = layer->src.tl.y; 594 vb[ 2] = layer->size; 595 596 vb[ 3].x = layer->dst.br.x; 597 vb[ 3].y = layer->dst.tl.y; 598 vb[ 4].x = layer->src.br.x; 599 vb[ 4].y = layer->src.tl.y; 600 vb[ 5] = layer->size; 601 602 vb[ 6].x = layer->dst.br.x; 603 vb[ 6].y = layer->dst.br.y; 604 vb[ 7].x = layer->src.br.x; 605 vb[ 7].y = layer->src.br.y; 606 vb[ 8] = layer->size; 607 608 vb[ 9].x = layer->dst.tl.x; 609 vb[ 9].y = layer->dst.br.y; 610 vb[10].x = layer->src.tl.x; 611 vb[10].y = layer->src.br.y; 612 vb[11] = layer->size; 613} 614 615static INLINE struct u_rect 616calc_drawn_area(struct vl_compositor *c, struct vl_compositor_layer *layer) 617{ 618 struct u_rect result; 619 620 // scale 621 result.x0 = layer->dst.tl.x * c->viewport.scale[0] + c->viewport.translate[0]; 622 result.y0 = layer->dst.tl.y * c->viewport.scale[1] + c->viewport.translate[1]; 623 result.x1 = layer->dst.br.x * c->viewport.scale[0] + c->viewport.translate[0]; 624 result.y1 = layer->dst.br.y * c->viewport.scale[1] + c->viewport.translate[1]; 625 626 // and clip 627 result.x0 = MAX2(result.x0, c->scissor.minx); 628 result.y0 = MAX2(result.y0, c->scissor.miny); 629 result.x1 = MIN2(result.x1, c->scissor.maxx); 630 result.y1 = MIN2(result.y1, c->scissor.maxy); 631 return result; 632} 633 634static void 635gen_vertex_data(struct vl_compositor *c, struct u_rect *dirty) 636{ 637 struct vertex2f *vb; 638 struct pipe_transfer *buf_transfer; 639 unsigned i; 640 641 assert(c); 642 643 vb = pipe_buffer_map(c->pipe, c->vertex_buf.buffer, 644 PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE | PIPE_TRANSFER_DONTBLOCK, 645 &buf_transfer); 646 647 if (!vb) { 648 // If buffer is still locked from last draw create a new one 649 create_vertex_buffer(c); 650 vb = pipe_buffer_map(c->pipe, c->vertex_buf.buffer, 651 PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE, 652 &buf_transfer); 653 } 654 655 for (i = 0; i < VL_COMPOSITOR_MAX_LAYERS; i++) { 656 if (c->used_layers & (1 << i)) { 657 struct vl_compositor_layer *layer = &c->layers[i]; 658 gen_rect_verts(vb, layer); 659 vb += 12; 660 661 if (dirty && layer->clearing) { 662 struct u_rect drawn = calc_drawn_area(c, layer); 663 if ( 664 dirty->x0 >= drawn.x0 && 665 dirty->y0 >= drawn.y0 && 666 dirty->x1 <= drawn.x1 && 667 dirty->y1 <= drawn.y1) { 668 669 // We clear the dirty area anyway, no need for clear_render_target 670 dirty->x0 = dirty->y0 = MAX_DIRTY; 671 dirty->x1 = dirty->y1 = MIN_DIRTY; 672 } 673 } 674 } 675 } 676 677 pipe_buffer_unmap(c->pipe, buf_transfer); 678} 679 680static void 681draw_layers(struct vl_compositor *c, struct u_rect *dirty) 682{ 683 unsigned vb_index, i; 684 685 assert(c); 686 687 for (i = 0, vb_index = 0; i < VL_COMPOSITOR_MAX_LAYERS; ++i) { 688 if (c->used_layers & (1 << i)) { 689 struct vl_compositor_layer *layer = &c->layers[i]; 690 struct pipe_sampler_view **samplers = &layer->sampler_views[0]; 691 unsigned num_sampler_views = !samplers[1] ? 1 : !samplers[2] ? 2 : 3; 692 693 c->pipe->bind_blend_state(c->pipe, layer->blend); 694 c->pipe->bind_fs_state(c->pipe, layer->fs); 695 c->pipe->bind_fragment_sampler_states(c->pipe, num_sampler_views, layer->samplers); 696 c->pipe->set_fragment_sampler_views(c->pipe, num_sampler_views, samplers); 697 util_draw_arrays(c->pipe, PIPE_PRIM_QUADS, vb_index * 4, 4); 698 vb_index++; 699 700 if (dirty) { 701 // Remember the currently drawn area as dirty for the next draw command 702 struct u_rect drawn = calc_drawn_area(c, layer); 703 dirty->x0 = MIN2(drawn.x0, dirty->x0); 704 dirty->y0 = MIN2(drawn.y0, dirty->y0); 705 dirty->x1 = MAX2(drawn.x1, dirty->x1); 706 dirty->y1 = MAX2(drawn.y1, dirty->y1); 707 } 708 } 709 } 710} 711 712void 713vl_compositor_reset_dirty_area(struct u_rect *dirty) 714{ 715 assert(dirty); 716 717 dirty->x0 = dirty->y0 = MIN_DIRTY; 718 dirty->x1 = dirty->y1 = MAX_DIRTY; 719} 720 721void 722vl_compositor_set_clear_color(struct vl_compositor *c, union pipe_color_union *color) 723{ 724 assert(c); 725 726 c->clear_color = *color; 727} 728 729void 730vl_compositor_get_clear_color(struct vl_compositor *c, union pipe_color_union *color) 731{ 732 assert(c); 733 assert(color); 734 735 *color = c->clear_color; 736} 737 738void 739vl_compositor_clear_layers(struct vl_compositor *c) 740{ 741 unsigned i, j; 742 743 assert(c); 744 745 c->used_layers = 0; 746 for ( i = 0; i < VL_COMPOSITOR_MAX_LAYERS; ++i) { 747 c->layers[i].clearing = i ? false : true; 748 c->layers[i].blend = i ? c->blend_add : c->blend_clear; 749 c->layers[i].fs = NULL; 750 for ( j = 0; j < 3; j++) 751 pipe_sampler_view_reference(&c->layers[i].sampler_views[j], NULL); 752 } 753} 754 755void 756vl_compositor_cleanup(struct vl_compositor *c) 757{ 758 assert(c); 759 760 vl_compositor_clear_layers(c); 761 762 cleanup_buffers(c); 763 cleanup_shaders(c); 764 cleanup_pipe_state(c); 765} 766 767void 768vl_compositor_set_csc_matrix(struct vl_compositor *c, const float matrix[16]) 769{ 770 struct pipe_transfer *buf_transfer; 771 772 assert(c); 773 774 memcpy 775 ( 776 pipe_buffer_map(c->pipe, c->csc_matrix, 777 PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE, 778 &buf_transfer), 779 matrix, 780 sizeof(csc_matrix) 781 ); 782 783 pipe_buffer_unmap(c->pipe, buf_transfer); 784} 785 786void 787vl_compositor_set_layer_blend(struct vl_compositor *c, 788 unsigned layer, void *blend, 789 bool is_clearing) 790{ 791 assert(c && blend); 792 793 assert(layer < VL_COMPOSITOR_MAX_LAYERS); 794 795 c->layers[layer].clearing = is_clearing; 796 c->layers[layer].blend = blend; 797} 798 799void 800vl_compositor_set_buffer_layer(struct vl_compositor *c, 801 unsigned layer, 802 struct pipe_video_buffer *buffer, 803 struct pipe_video_rect *src_rect, 804 struct pipe_video_rect *dst_rect) 805{ 806 struct pipe_sampler_view **sampler_views; 807 unsigned i; 808 809 assert(c && buffer); 810 811 assert(layer < VL_COMPOSITOR_MAX_LAYERS); 812 813 c->used_layers |= 1 << layer; 814 c->layers[layer].fs = buffer->interlaced ? c->fs_weave : c->fs_video_buffer; 815 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 827void 828vl_compositor_set_palette_layer(struct vl_compositor *c, 829 unsigned layer, 830 struct pipe_sampler_view *indexes, 831 struct pipe_sampler_view *palette, 832 struct pipe_video_rect *src_rect, 833 struct pipe_video_rect *dst_rect, 834 bool include_color_conversion) 835{ 836 assert(c && indexes && palette); 837 838 assert(layer < VL_COMPOSITOR_MAX_LAYERS); 839 840 c->used_layers |= 1 << layer; 841 842 c->layers[layer].fs = include_color_conversion ? 843 c->fs_palette.yuv : c->fs_palette.rgb; 844 845 c->layers[layer].samplers[0] = c->sampler_linear; 846 c->layers[layer].samplers[1] = c->sampler_nearest; 847 c->layers[layer].samplers[2] = NULL; 848 pipe_sampler_view_reference(&c->layers[layer].sampler_views[0], indexes); 849 pipe_sampler_view_reference(&c->layers[layer].sampler_views[1], palette); 850 pipe_sampler_view_reference(&c->layers[layer].sampler_views[2], NULL); 851 calc_src_and_dst(&c->layers[layer], indexes->texture->width0, indexes->texture->height0, 852 src_rect ? *src_rect : default_rect(&c->layers[layer]), 853 dst_rect ? *dst_rect : default_rect(&c->layers[layer])); 854} 855 856void 857vl_compositor_set_rgba_layer(struct vl_compositor *c, 858 unsigned layer, 859 struct pipe_sampler_view *rgba, 860 struct pipe_video_rect *src_rect, 861 struct pipe_video_rect *dst_rect) 862{ 863 assert(c && rgba); 864 865 assert(layer < VL_COMPOSITOR_MAX_LAYERS); 866 867 c->used_layers |= 1 << layer; 868 c->layers[layer].fs = c->fs_rgba; 869 c->layers[layer].samplers[0] = c->sampler_linear; 870 c->layers[layer].samplers[1] = NULL; 871 c->layers[layer].samplers[2] = NULL; 872 pipe_sampler_view_reference(&c->layers[layer].sampler_views[0], rgba); 873 pipe_sampler_view_reference(&c->layers[layer].sampler_views[1], NULL); 874 pipe_sampler_view_reference(&c->layers[layer].sampler_views[2], NULL); 875 calc_src_and_dst(&c->layers[layer], rgba->texture->width0, rgba->texture->height0, 876 src_rect ? *src_rect : default_rect(&c->layers[layer]), 877 dst_rect ? *dst_rect : default_rect(&c->layers[layer])); 878} 879 880void 881vl_compositor_render(struct vl_compositor *c, 882 struct pipe_surface *dst_surface, 883 struct pipe_video_rect *dst_area, 884 struct pipe_video_rect *dst_clip, 885 struct u_rect *dirty_area) 886{ 887 assert(c); 888 assert(dst_surface); 889 890 c->fb_state.width = dst_surface->width; 891 c->fb_state.height = dst_surface->height; 892 c->fb_state.cbufs[0] = dst_surface; 893 894 if (dst_area) { 895 c->viewport.scale[0] = dst_area->w; 896 c->viewport.scale[1] = dst_area->h; 897 c->viewport.translate[0] = dst_area->x; 898 c->viewport.translate[1] = dst_area->y; 899 } else { 900 c->viewport.scale[0] = dst_surface->width; 901 c->viewport.scale[1] = dst_surface->height; 902 c->viewport.translate[0] = 0; 903 c->viewport.translate[1] = 0; 904 } 905 906 if (dst_clip) { 907 c->scissor.minx = dst_clip->x; 908 c->scissor.miny = dst_clip->y; 909 c->scissor.maxx = dst_clip->x + dst_clip->w; 910 c->scissor.maxy = dst_clip->y + dst_clip->h; 911 } else { 912 c->scissor.minx = 0; 913 c->scissor.miny = 0; 914 c->scissor.maxx = dst_surface->width; 915 c->scissor.maxy = dst_surface->height; 916 } 917 918 gen_vertex_data(c, dirty_area); 919 920 if (dirty_area && (dirty_area->x0 < dirty_area->x1 || 921 dirty_area->y0 < dirty_area->y1)) { 922 923 c->pipe->clear_render_target(c->pipe, dst_surface, &c->clear_color, 924 0, 0, dst_surface->width, dst_surface->height); 925 dirty_area->x0 = dirty_area->y0 = MAX_DIRTY; 926 dirty_area->x0 = dirty_area->y1 = MIN_DIRTY; 927 } 928 929 c->pipe->set_scissor_state(c->pipe, &c->scissor); 930 c->pipe->set_framebuffer_state(c->pipe, &c->fb_state); 931 c->pipe->set_viewport_state(c->pipe, &c->viewport); 932 c->pipe->bind_vs_state(c->pipe, c->vs); 933 c->pipe->set_vertex_buffers(c->pipe, 1, &c->vertex_buf); 934 c->pipe->bind_vertex_elements_state(c->pipe, c->vertex_elems_state); 935 c->pipe->set_constant_buffer(c->pipe, PIPE_SHADER_FRAGMENT, 0, c->csc_matrix); 936 c->pipe->bind_rasterizer_state(c->pipe, c->rast); 937 938 draw_layers(c, dirty_area); 939} 940 941bool 942vl_compositor_init(struct vl_compositor *c, struct pipe_context *pipe) 943{ 944 csc_matrix csc_matrix; 945 946 c->pipe = pipe; 947 948 if (!init_pipe_state(c)) 949 return false; 950 951 if (!init_shaders(c)) { 952 cleanup_pipe_state(c); 953 return false; 954 } 955 956 if (!init_buffers(c)) { 957 cleanup_shaders(c); 958 cleanup_pipe_state(c); 959 return false; 960 } 961 962 vl_compositor_clear_layers(c); 963 964 vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_IDENTITY, NULL, true, csc_matrix); 965 vl_compositor_set_csc_matrix(c, csc_matrix); 966 967 c->clear_color.f[0] = c->clear_color.f[1] = 0.0f; 968 c->clear_color.f[2] = c->clear_color.f[3] = 0.0f; 969 970 return true; 971} 972