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