vl_mc.c revision b8a6e0e6fc451096d684a1e18529ab4879cdba0a
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_context.h> 31 32#include <util/u_sampler.h> 33#include <util/u_draw.h> 34 35#include <tgsi/tgsi_ureg.h> 36 37#include "vl_defines.h" 38#include "vl_vertex_buffers.h" 39#include "vl_mc.h" 40 41enum VS_OUTPUT 42{ 43 VS_O_VPOS, 44 VS_O_LINE, 45 VS_O_VTOP, 46 VS_O_VBOTTOM 47}; 48 49static struct ureg_dst 50calc_position(struct vl_mc *r, struct ureg_program *shader) 51{ 52 struct ureg_src block_scale; 53 struct ureg_src vrect, vpos; 54 struct ureg_dst t_vpos; 55 struct ureg_dst o_vpos; 56 57 vrect = ureg_DECL_vs_input(shader, VS_I_RECT); 58 vpos = ureg_DECL_vs_input(shader, VS_I_VPOS); 59 60 t_vpos = ureg_DECL_temporary(shader); 61 62 o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, VS_O_VPOS); 63 64 /* 65 * block_scale = (MACROBLOCK_WIDTH, MACROBLOCK_HEIGHT) / (dst.width, dst.height) 66 * 67 * t_vpos = (vpos + vrect) * block_scale 68 * o_vpos.xy = t_vpos 69 * o_vpos.zw = vpos 70 */ 71 block_scale = ureg_imm2f(shader, 72 (float)MACROBLOCK_WIDTH / r->buffer_width, 73 (float)MACROBLOCK_HEIGHT / r->buffer_height); 74 75 ureg_ADD(shader, ureg_writemask(t_vpos, TGSI_WRITEMASK_XY), vpos, vrect); 76 ureg_MUL(shader, ureg_writemask(t_vpos, TGSI_WRITEMASK_XY), ureg_src(t_vpos), block_scale); 77 ureg_MOV(shader, ureg_writemask(o_vpos, TGSI_WRITEMASK_XY), ureg_src(t_vpos)); 78 ureg_MOV(shader, ureg_writemask(o_vpos, TGSI_WRITEMASK_ZW), vpos); 79 80 return t_vpos; 81} 82 83static void * 84create_ycbcr_vert_shader(struct vl_mc *r) 85{ 86 struct ureg_program *shader; 87 struct ureg_src block_scale; 88 struct ureg_src vrect, vpos, eb, flags; 89 struct ureg_dst t_vpos, t_vtex; 90 struct ureg_dst o_line, o_vtex[2]; 91 unsigned label; 92 93 shader = ureg_create(TGSI_PROCESSOR_VERTEX); 94 if (!shader) 95 return NULL; 96 97 vrect = ureg_DECL_vs_input(shader, VS_I_RECT); 98 vpos = ureg_DECL_vs_input(shader, VS_I_VPOS); 99 eb = ureg_DECL_vs_input(shader, VS_I_EB); 100 flags = ureg_DECL_vs_input(shader, VS_I_FLAGS); 101 102 t_vpos = calc_position(r, shader); 103 t_vtex = ureg_DECL_temporary(shader); 104 105 o_line = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_LINE); 106 o_vtex[0] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTOP); 107 o_vtex[1] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VBOTTOM); 108 109 /* 110 * block_scale = (MACROBLOCK_WIDTH, MACROBLOCK_HEIGHT) / (dst.width, dst.height) 111 * 112 * o_line.x = interlaced 113 * o_line.y = vrect 114 * 115 * o_vtex[0].z = vrect.x ? eb.y : eb.x 116 * o_vtex[1].z = vrect.x ? eb.w : eb.z 117 * 118 * if(interlaced) { 119 * t_vtex.x = vrect.x 120 * t_vtex.y = vrect.y * 0.5 121 * t_vtex += vpos 122 * 123 * o_vtex[0].xy = t_vtex * block_scale 124 * 125 * t_vtex.y += 0.5 126 * o_vtex[1].xy = t_vtex * block_scale 127 * } else { 128 * o_vtex[0..1].xy = t_vpos 129 * } 130 * o_vtex[2].xy = t_vpos 131 * 132 */ 133 block_scale = ureg_imm2f(shader, 134 (float)MACROBLOCK_WIDTH / r->buffer_width, 135 (float)MACROBLOCK_HEIGHT / r->buffer_height); 136 137 ureg_MUL(shader, ureg_writemask(o_line, TGSI_WRITEMASK_X), flags, ureg_imm1f(shader, 0.5f)); 138 ureg_MOV(shader, ureg_writemask(o_line, TGSI_WRITEMASK_Y), vrect); 139 140 ureg_MOV(shader, ureg_writemask(o_vtex[0], TGSI_WRITEMASK_XY), ureg_src(t_vpos)); 141 ureg_CMP(shader, ureg_writemask(o_vtex[0], TGSI_WRITEMASK_Z), 142 ureg_negate(ureg_scalar(vrect, TGSI_SWIZZLE_X)), 143 ureg_scalar(eb, TGSI_SWIZZLE_Y), 144 ureg_scalar(eb, TGSI_SWIZZLE_X)); 145 146 ureg_MOV(shader, ureg_writemask(o_vtex[1], TGSI_WRITEMASK_XY), ureg_src(t_vpos)); 147 ureg_CMP(shader, ureg_writemask(o_vtex[1], TGSI_WRITEMASK_Z), 148 ureg_negate(ureg_scalar(vrect, TGSI_SWIZZLE_X)), 149 ureg_scalar(eb, TGSI_SWIZZLE_W), 150 ureg_scalar(eb, TGSI_SWIZZLE_Z)); 151 152 if (r->macroblock_size == MACROBLOCK_HEIGHT) { //TODO 153 ureg_IF(shader, ureg_scalar(flags, TGSI_SWIZZLE_Y), &label); 154 155 ureg_MOV(shader, ureg_writemask(t_vtex, TGSI_WRITEMASK_X), vrect); 156 ureg_MUL(shader, ureg_writemask(t_vtex, TGSI_WRITEMASK_Y), vrect, ureg_imm1f(shader, 0.5f)); 157 ureg_ADD(shader, ureg_writemask(t_vtex, TGSI_WRITEMASK_XY), vpos, ureg_src(t_vtex)); 158 ureg_MUL(shader, ureg_writemask(o_vtex[0], TGSI_WRITEMASK_XY), ureg_src(t_vtex), block_scale); 159 ureg_ADD(shader, ureg_writemask(t_vtex, TGSI_WRITEMASK_Y), ureg_src(t_vtex), ureg_imm1f(shader, 0.5f)); 160 ureg_MUL(shader, ureg_writemask(o_vtex[1], TGSI_WRITEMASK_XY), ureg_src(t_vtex), block_scale); 161 162 ureg_MUL(shader, ureg_writemask(o_line, TGSI_WRITEMASK_Y), 163 ureg_scalar(vrect, TGSI_SWIZZLE_Y), 164 ureg_imm1f(shader, MACROBLOCK_HEIGHT / 2)); 165 166 ureg_fixup_label(shader, label, ureg_get_instruction_number(shader)); 167 ureg_ENDIF(shader); 168 } 169 170 ureg_release_temporary(shader, t_vtex); 171 ureg_release_temporary(shader, t_vpos); 172 173 ureg_END(shader); 174 175 return ureg_create_shader_and_destroy(shader, r->pipe); 176} 177 178static void * 179create_ref_vert_shader(struct vl_mc *r) 180{ 181 struct ureg_program *shader; 182 struct ureg_src mv_scale; 183 struct ureg_src vrect, vmv[2]; 184 struct ureg_dst t_vpos; 185 struct ureg_dst o_vpos, o_line, o_vmv[2]; 186 unsigned i; 187 188 shader = ureg_create(TGSI_PROCESSOR_VERTEX); 189 if (!shader) 190 return NULL; 191 192 vrect = ureg_DECL_vs_input(shader, VS_I_RECT); 193 ureg_DECL_vs_input(shader, VS_I_EB); 194 ureg_DECL_vs_input(shader, VS_I_FLAGS); 195 vmv[0] = ureg_DECL_vs_input(shader, VS_I_MV_TOP); 196 vmv[1] = ureg_DECL_vs_input(shader, VS_I_MV_BOTTOM); 197 198 t_vpos = calc_position(r, shader); 199 200 o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, VS_O_VPOS); 201 o_line = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_LINE); 202 o_vmv[0] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTOP); 203 o_vmv[1] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VBOTTOM); 204 205 /* 206 * mv_scale = 0.5 / (dst.width, dst.height); 207 * 208 * // Apply motion vectors 209 * o_vmv[0..3] = t_vpos + vmv[0..3] * mv_scale 210 * 211 * o_line.y = vrect 212 * 213 */ 214 215 ureg_MUL(shader, ureg_writemask(o_line, TGSI_WRITEMASK_Y), 216 vrect, ureg_imm1f(shader, r->macroblock_size / 2)); 217 218 mv_scale = ureg_imm4f(shader, 219 0.5f / r->buffer_width, 220 0.5f / r->buffer_height, 221 1.0f / 4.0f, 222 1.0f / 255.0f); 223 224 for (i = 0; i < 2; ++i) { 225 ureg_MAD(shader, ureg_writemask(o_vmv[i], TGSI_WRITEMASK_XY), mv_scale, vmv[i], ureg_src(t_vpos)); 226 ureg_MUL(shader, ureg_writemask(o_vmv[i], TGSI_WRITEMASK_ZW), mv_scale, vmv[i]); 227 } 228 229 ureg_release_temporary(shader, t_vpos); 230 231 ureg_END(shader); 232 233 return ureg_create_shader_and_destroy(shader, r->pipe); 234} 235 236static struct ureg_dst 237calc_field(struct ureg_program *shader) 238{ 239 struct ureg_dst tmp; 240 struct ureg_src line; 241 242 tmp = ureg_DECL_temporary(shader); 243 244 line = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_LINE, TGSI_INTERPOLATE_LINEAR); 245 246 /* 247 * line.x is flag for intra frames 248 * line.y going from 0 to 1 if not interlaced 249 * line.y going from 0 to 8 in steps of 0.5 if interlaced 250 * 251 * tmp.xy = fraction(line) 252 * tmp.xy = tmp.xy >= 0.5 ? 1 : 0 253 */ 254 ureg_MOV(shader, ureg_writemask(tmp, TGSI_WRITEMASK_X), line); 255 ureg_FRC(shader, ureg_writemask(tmp, TGSI_WRITEMASK_Y), line); 256 ureg_SGE(shader, ureg_writemask(tmp, TGSI_WRITEMASK_Y), ureg_src(tmp), ureg_imm1f(shader, 0.5f)); 257 258 return tmp; 259} 260 261static void * 262create_ycbcr_frag_shader(struct vl_mc *r, float scale) 263{ 264 struct ureg_program *shader; 265 struct ureg_src tc[2], sampler; 266 struct ureg_dst texel, t_tc, field; 267 struct ureg_dst fragment; 268 unsigned label; 269 270 shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); 271 if (!shader) 272 return NULL; 273 274 tc[0] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTOP, TGSI_INTERPOLATE_LINEAR); 275 tc[1] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VBOTTOM, TGSI_INTERPOLATE_LINEAR); 276 277 sampler = ureg_DECL_sampler(shader, 0); 278 279 t_tc = ureg_DECL_temporary(shader); 280 texel = ureg_DECL_temporary(shader); 281 282 fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0); 283 284 field = calc_field(shader); 285 286 /* 287 * texel.y = tex(field.y ? tc[1] : tc[0], sampler[0]) 288 * texel.cb = tex(tc[2], sampler[1]) 289 * texel.cr = tex(tc[2], sampler[2]) 290 */ 291 292 ureg_CMP(shader, ureg_writemask(t_tc, TGSI_WRITEMASK_XYZ), 293 ureg_negate(ureg_scalar(ureg_src(field), TGSI_SWIZZLE_Y)), 294 tc[1], tc[0]); 295 296 ureg_SLT(shader, ureg_writemask(t_tc, TGSI_WRITEMASK_Z), ureg_src(t_tc), ureg_imm1f(shader, 0.5f)); 297 298 ureg_MOV(shader, fragment, ureg_imm4f(shader, 0.0f, 0.0f, 0.0f, 1.0f)); 299 ureg_IF(shader, ureg_scalar(ureg_src(t_tc), TGSI_SWIZZLE_Z), &label); 300 301 ureg_TEX(shader, texel, TGSI_TEXTURE_3D, ureg_src(t_tc), sampler); 302 303 if (scale != 1.0f) 304 ureg_MAD(shader, ureg_writemask(fragment, TGSI_WRITEMASK_XYZ), 305 ureg_src(texel), ureg_imm1f(shader, scale), 306 ureg_scalar(ureg_src(field), TGSI_SWIZZLE_X)); 307 else 308 ureg_ADD(shader, ureg_writemask(fragment, TGSI_WRITEMASK_XYZ), 309 ureg_src(texel), ureg_scalar(ureg_src(field), TGSI_SWIZZLE_X)); 310 311 ureg_fixup_label(shader, label, ureg_get_instruction_number(shader)); 312 ureg_ENDIF(shader); 313 314 ureg_release_temporary(shader, t_tc); 315 ureg_release_temporary(shader, texel); 316 317 return ureg_create_shader_and_destroy(shader, r->pipe); 318} 319 320static void * 321create_ref_frag_shader(struct vl_mc *r) 322{ 323 const float y_scale = 324 r->buffer_height / 2 * 325 r->macroblock_size / MACROBLOCK_HEIGHT; 326 327 struct ureg_program *shader; 328 struct ureg_src tc[2], sampler; 329 struct ureg_dst ref, field; 330 struct ureg_dst fragment; 331 unsigned label; 332 333 shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); 334 if (!shader) 335 return NULL; 336 337 tc[0] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTOP, TGSI_INTERPOLATE_LINEAR); 338 tc[1] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VBOTTOM, TGSI_INTERPOLATE_LINEAR); 339 340 sampler = ureg_DECL_sampler(shader, 0); 341 ref = ureg_DECL_temporary(shader); 342 343 fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0); 344 345 field = calc_field(shader); 346 347 /* 348 * ref = field.z ? tc[1] : tc[0] 349 * 350 * // Adjust tc acording to top/bottom field selection 351 * if (|ref.z|) { 352 * ref.y *= y_scale 353 * ref.y = floor(ref.y) 354 * ref.y += ref.z 355 * ref.y /= y_scale 356 * } 357 * fragment.xyz = tex(ref, sampler[0]) 358 */ 359 ureg_CMP(shader, ureg_writemask(ref, TGSI_WRITEMASK_XYZ), 360 ureg_negate(ureg_scalar(ureg_src(field), TGSI_SWIZZLE_Y)), 361 tc[1], tc[0]); 362 ureg_CMP(shader, ureg_writemask(fragment, TGSI_WRITEMASK_W), 363 ureg_negate(ureg_scalar(ureg_src(field), TGSI_SWIZZLE_Y)), 364 tc[1], tc[0]); 365 366 ureg_IF(shader, ureg_scalar(ureg_src(ref), TGSI_SWIZZLE_Z), &label); 367 368 ureg_MUL(shader, ureg_writemask(ref, TGSI_WRITEMASK_Y), 369 ureg_src(ref), ureg_imm1f(shader, y_scale)); 370 ureg_FLR(shader, ureg_writemask(ref, TGSI_WRITEMASK_Y), ureg_src(ref)); 371 ureg_ADD(shader, ureg_writemask(ref, TGSI_WRITEMASK_Y), 372 ureg_src(ref), ureg_scalar(ureg_src(ref), TGSI_SWIZZLE_Z)); 373 ureg_MUL(shader, ureg_writemask(ref, TGSI_WRITEMASK_Y), 374 ureg_src(ref), ureg_imm1f(shader, 1.0f / y_scale)); 375 376 ureg_fixup_label(shader, label, ureg_get_instruction_number(shader)); 377 ureg_ENDIF(shader); 378 379 ureg_TEX(shader, ureg_writemask(fragment, TGSI_WRITEMASK_XYZ), TGSI_TEXTURE_2D, ureg_src(ref), sampler); 380 381 ureg_release_temporary(shader, ref); 382 383 ureg_release_temporary(shader, field); 384 ureg_END(shader); 385 386 return ureg_create_shader_and_destroy(shader, r->pipe); 387} 388 389static bool 390init_pipe_state(struct vl_mc *r) 391{ 392 struct pipe_sampler_state sampler; 393 struct pipe_blend_state blend; 394 struct pipe_rasterizer_state rs_state; 395 396 assert(r); 397 398 memset(&sampler, 0, sizeof(sampler)); 399 sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 400 sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 401 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_BORDER; 402 sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR; 403 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; 404 sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR; 405 sampler.compare_mode = PIPE_TEX_COMPARE_NONE; 406 sampler.compare_func = PIPE_FUNC_ALWAYS; 407 sampler.normalized_coords = 1; 408 r->sampler_ref = r->pipe->create_sampler_state(r->pipe, &sampler); 409 if (!r->sampler_ref) 410 goto error_sampler_ref; 411 412 sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; 413 sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; 414 r->sampler_ycbcr = r->pipe->create_sampler_state(r->pipe, &sampler); 415 if (!r->sampler_ycbcr) 416 goto error_sampler_ycbcr; 417 418 memset(&blend, 0, sizeof blend); 419 blend.independent_blend_enable = 0; 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_ZERO; 424 blend.rt[0].alpha_func = PIPE_BLEND_ADD; 425 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA; 426 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; 427 blend.logicop_enable = 0; 428 blend.logicop_func = PIPE_LOGICOP_CLEAR; 429 blend.rt[0].colormask = PIPE_MASK_RGBA; 430 blend.dither = 0; 431 r->blend_clear = r->pipe->create_blend_state(r->pipe, &blend); 432 if (!r->blend_clear) 433 goto error_blend_clear; 434 435 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE; 436 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE; 437 r->blend_add = r->pipe->create_blend_state(r->pipe, &blend); 438 if (!r->blend_add) 439 goto error_blend_add; 440 441 memset(&rs_state, 0, sizeof(rs_state)); 442 /*rs_state.sprite_coord_enable */ 443 rs_state.sprite_coord_mode = PIPE_SPRITE_COORD_UPPER_LEFT; 444 rs_state.point_quad_rasterization = true; 445 rs_state.point_size = BLOCK_WIDTH; 446 rs_state.gl_rasterization_rules = true; 447 r->rs_state = r->pipe->create_rasterizer_state(r->pipe, &rs_state); 448 if (!r->rs_state) 449 goto error_rs_state; 450 451 return true; 452 453error_rs_state: 454 r->pipe->delete_blend_state(r->pipe, r->blend_add); 455 456error_blend_add: 457 r->pipe->delete_blend_state(r->pipe, r->blend_clear); 458 459error_blend_clear: 460 r->pipe->delete_sampler_state(r->pipe, r->sampler_ref); 461 462error_sampler_ref: 463 r->pipe->delete_sampler_state(r->pipe, r->sampler_ycbcr); 464 465error_sampler_ycbcr: 466 return false; 467} 468 469static void 470cleanup_pipe_state(struct vl_mc *r) 471{ 472 assert(r); 473 474 r->pipe->delete_sampler_state(r->pipe, r->sampler_ref); 475 r->pipe->delete_sampler_state(r->pipe, r->sampler_ycbcr); 476 r->pipe->delete_blend_state(r->pipe, r->blend_clear); 477 r->pipe->delete_blend_state(r->pipe, r->blend_add); 478 r->pipe->delete_rasterizer_state(r->pipe, r->rs_state); 479} 480 481bool 482vl_mc_init(struct vl_mc *renderer, struct pipe_context *pipe, 483 unsigned buffer_width, unsigned buffer_height, 484 unsigned macroblock_size, float scale) 485{ 486 assert(renderer); 487 assert(pipe); 488 489 memset(renderer, 0, sizeof(struct vl_mc)); 490 491 renderer->pipe = pipe; 492 renderer->buffer_width = buffer_width; 493 renderer->buffer_height = buffer_height; 494 renderer->macroblock_size = macroblock_size; 495 496 if (!init_pipe_state(renderer)) 497 goto error_pipe_state; 498 499 renderer->vs_ref = create_ref_vert_shader(renderer); 500 if (!renderer->vs_ref) 501 goto error_vs_ref; 502 503 renderer->vs_ycbcr = create_ycbcr_vert_shader(renderer); 504 if (!renderer->vs_ycbcr) 505 goto error_vs_ycbcr; 506 507 renderer->fs_ref = create_ref_frag_shader(renderer); 508 if (!renderer->fs_ref) 509 goto error_fs_ref; 510 511 renderer->fs_ycbcr = create_ycbcr_frag_shader(renderer, scale); 512 if (!renderer->fs_ycbcr) 513 goto error_fs_ycbcr; 514 515 return true; 516 517error_fs_ycbcr: 518 renderer->pipe->delete_fs_state(renderer->pipe, renderer->fs_ref); 519 520error_fs_ref: 521 renderer->pipe->delete_vs_state(renderer->pipe, renderer->vs_ycbcr); 522 523error_vs_ycbcr: 524 renderer->pipe->delete_vs_state(renderer->pipe, renderer->vs_ref); 525 526error_vs_ref: 527 cleanup_pipe_state(renderer); 528 529error_pipe_state: 530 return false; 531} 532 533void 534vl_mc_cleanup(struct vl_mc *renderer) 535{ 536 assert(renderer); 537 538 cleanup_pipe_state(renderer); 539 540 renderer->pipe->delete_vs_state(renderer->pipe, renderer->vs_ref); 541 renderer->pipe->delete_vs_state(renderer->pipe, renderer->vs_ycbcr); 542 renderer->pipe->delete_fs_state(renderer->pipe, renderer->fs_ref); 543 renderer->pipe->delete_fs_state(renderer->pipe, renderer->fs_ycbcr); 544} 545 546bool 547vl_mc_init_buffer(struct vl_mc *renderer, struct vl_mc_buffer *buffer, 548 struct pipe_sampler_view *source) 549{ 550 assert(renderer && buffer); 551 assert(source); 552 553 buffer->renderer = renderer; 554 555 buffer->viewport.scale[2] = 1; 556 buffer->viewport.scale[3] = 1; 557 buffer->viewport.translate[0] = 0; 558 buffer->viewport.translate[1] = 0; 559 buffer->viewport.translate[2] = 0; 560 buffer->viewport.translate[3] = 0; 561 562 buffer->fb_state.nr_cbufs = 1; 563 buffer->fb_state.zsbuf = NULL; 564 565 pipe_sampler_view_reference(&buffer->source, source); 566 567 return true; 568} 569 570void 571vl_mc_cleanup_buffer(struct vl_mc_buffer *buffer) 572{ 573 assert(buffer); 574 575 pipe_sampler_view_reference(&buffer->source, NULL); 576} 577 578void 579vl_mc_set_surface(struct vl_mc_buffer *buffer, struct pipe_surface *surface) 580{ 581 assert(buffer && surface); 582 583 buffer->surface_cleared = false; 584 585 buffer->viewport.scale[0] = surface->width; 586 buffer->viewport.scale[1] = surface->height; 587 588 buffer->fb_state.width = surface->width; 589 buffer->fb_state.height = surface->height; 590 buffer->fb_state.cbufs[0] = surface; 591} 592 593static void 594prepare_pipe_4_rendering(struct vl_mc_buffer *buffer) 595{ 596 struct vl_mc *renderer; 597 598 assert(buffer); 599 600 renderer = buffer->renderer; 601 renderer->pipe->bind_rasterizer_state(renderer->pipe, renderer->rs_state); 602 603 if (buffer->surface_cleared) 604 renderer->pipe->bind_blend_state(renderer->pipe, renderer->blend_add); 605 else { 606 renderer->pipe->bind_blend_state(renderer->pipe, renderer->blend_clear); 607 buffer->surface_cleared = true; 608 } 609 610 renderer->pipe->set_framebuffer_state(renderer->pipe, &buffer->fb_state); 611 renderer->pipe->set_viewport_state(renderer->pipe, &buffer->viewport); 612} 613 614void 615vl_mc_render_ref(struct vl_mc_buffer *buffer, struct pipe_sampler_view *ref) 616{ 617 struct vl_mc *renderer; 618 619 assert(buffer && ref); 620 621 prepare_pipe_4_rendering(buffer); 622 623 renderer = buffer->renderer; 624 625 renderer->pipe->bind_vs_state(renderer->pipe, renderer->vs_ref); 626 renderer->pipe->bind_fs_state(renderer->pipe, renderer->fs_ref); 627 628 renderer->pipe->set_fragment_sampler_views(renderer->pipe, 1, &ref); 629 renderer->pipe->bind_fragment_sampler_states(renderer->pipe, 1, &renderer->sampler_ref); 630 631 util_draw_arrays_instanced(renderer->pipe, PIPE_PRIM_QUADS, 0, 4, 0, 632 renderer->buffer_width / MACROBLOCK_WIDTH * 633 renderer->buffer_height / MACROBLOCK_HEIGHT); 634} 635 636void 637vl_mc_render_ycbcr(struct vl_mc_buffer *buffer, unsigned num_instances) 638{ 639 struct vl_mc *renderer; 640 641 assert(buffer); 642 643 if (num_instances == 0) 644 return; 645 646 prepare_pipe_4_rendering(buffer); 647 648 renderer = buffer->renderer; 649 650 renderer->pipe->bind_vs_state(renderer->pipe, renderer->vs_ycbcr); 651 renderer->pipe->bind_fs_state(renderer->pipe, renderer->fs_ycbcr); 652 653 renderer->pipe->set_fragment_sampler_views(renderer->pipe, 1, &buffer->source); 654 renderer->pipe->bind_fragment_sampler_states(renderer->pipe, 1, &renderer->sampler_ycbcr); 655 656 util_draw_arrays_instanced(renderer->pipe, PIPE_PRIM_QUADS, 0, 4, 0, num_instances); 657} 658