1 /**************************************************************************
3 * Copyright 2009 Younes Manton.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
28 #include "vl_mpeg12_mc_renderer.h"
29 #include "util/u_draw.h"
31 #include <pipe/p_context.h>
32 #include <util/u_inlines.h>
33 #include <util/u_format.h>
34 #include <util/u_math.h>
35 #include <util/u_memory.h>
36 #include <util/u_keymap.h>
37 #include <util/u_sampler.h>
38 #include <tgsi/tgsi_ureg.h>
40 #define DEFAULT_BUF_ALIGNMENT 1
41 #define MACROBLOCK_WIDTH 16
42 #define MACROBLOCK_HEIGHT 16
44 #define BLOCK_HEIGHT 8
45 #define ZERO_BLOCK_NIL -1.0f
46 #define ZERO_BLOCK_IS_NIL(zb) ((zb).x < 0.0f)
47 #define SCALE_FACTOR_16_TO_9 (32767.0f / 255.0f)
49 struct vertex_shader_consts
54 struct fragment_shader_consts
56 struct vertex4f multiplier
;
63 struct vertex2f luma_tc
;
64 struct vertex2f cb_tc
;
65 struct vertex2f cr_tc
;
70 MACROBLOCK_TYPE_INTRA
,
71 MACROBLOCK_TYPE_FWD_FRAME_PRED
,
72 MACROBLOCK_TYPE_FWD_FIELD_PRED
,
73 MACROBLOCK_TYPE_BKWD_FRAME_PRED
,
74 MACROBLOCK_TYPE_BKWD_FIELD_PRED
,
75 MACROBLOCK_TYPE_BI_FRAME_PRED
,
76 MACROBLOCK_TYPE_BI_FIELD_PRED
,
82 create_vert_shader(struct vl_mpeg12_mc_renderer
*r
, unsigned ref_frames
, unsigned mv_per_frame
)
84 struct ureg_program
*shader
;
85 struct ureg_src norm
, mbs
;
86 struct ureg_src vpos
, vtex
[3], vmv
[4];
88 struct ureg_dst o_vpos
, o_vtex
[3], o_vmv
[4], o_line
;
91 shader
= ureg_create(TGSI_PROCESSOR_VERTEX
);
95 norm
= ureg_DECL_constant(shader
, 0);
96 mbs
= ureg_imm2f(shader
, MACROBLOCK_WIDTH
, MACROBLOCK_HEIGHT
);
97 temp
= ureg_DECL_temporary(shader
);
99 vpos
= ureg_DECL_vs_input(shader
, 0);
100 o_vpos
= ureg_DECL_output(shader
, TGSI_SEMANTIC_POSITION
, 0);
102 for (i
= 0; i
< 3; ++i
) {
103 vtex
[i
] = ureg_DECL_vs_input(shader
, 1 + i
);
104 o_vtex
[i
] = ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, 1 + i
);
108 for (i
= 0; i
< ref_frames
; ++i
) {
109 for (j
= 0; j
< 2; ++j
) {
110 if(j
< mv_per_frame
) {
111 vmv
[count
] = ureg_DECL_vs_input(shader
, 4 + i
* 2 + j
);
112 o_vmv
[count
] = ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, 4 + count
);
115 /* workaround for r600g */
116 else if(ref_frames
== 2)
117 ureg_DECL_vs_input(shader
, 4 + i
* 2 + j
);
121 o_line
= ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, 4 + count
);
124 * o_vpos = vpos * norm * mbs
125 * o_vtex[0..2] = vtex[0..2] * norm * mbs
126 * o_vmv[0..count] = o_vpos + vmv[0..4] * 0.5 // Apply motion vector
127 * o_frc = fract(vpos) * mbs
129 ureg_MUL(shader
, ureg_writemask(temp
, TGSI_WRITEMASK_XY
), vpos
, mbs
);
130 ureg_MUL(shader
, ureg_writemask(o_vpos
, TGSI_WRITEMASK_XY
), ureg_src(temp
), norm
);
131 ureg_MOV(shader
, ureg_writemask(o_vpos
, TGSI_WRITEMASK_ZW
), vpos
);
132 for (i
= 0; i
< 3; ++i
) {
133 ureg_MUL(shader
, ureg_writemask(temp
, TGSI_WRITEMASK_XY
), vtex
[i
], mbs
);
134 ureg_MUL(shader
, ureg_writemask(o_vtex
[i
], TGSI_WRITEMASK_XY
), ureg_src(temp
), norm
);
136 for (i
= 0; i
< count
; ++i
) {
137 ureg_MUL(shader
, ureg_writemask(temp
, TGSI_WRITEMASK_XY
), vmv
[i
],
138 ureg_scalar(ureg_imm1f(shader
, 0.5f
), TGSI_SWIZZLE_X
));
139 ureg_MAD(shader
, ureg_writemask(o_vmv
[i
], TGSI_WRITEMASK_XY
), ureg_src(temp
), norm
, ureg_src(o_vpos
));
141 if (mv_per_frame
== 2) {
142 ureg_MOV(shader
, ureg_writemask(o_line
, TGSI_WRITEMASK_X
), ureg_imm1f(shader
, 1.0f
));
143 ureg_MUL(shader
, ureg_writemask(o_line
, TGSI_WRITEMASK_Y
), vpos
, ureg_imm1f(shader
, MACROBLOCK_HEIGHT
/ 2));
146 ureg_release_temporary(shader
, temp
);
149 return ureg_create_shader_and_destroy(shader
, r
->pipe
);
153 create_intra_frag_shader(struct vl_mpeg12_mc_renderer
*r
)
155 struct ureg_program
*shader
;
156 struct ureg_src tc
[3];
157 struct ureg_src sampler
[3];
158 struct ureg_dst texel
, temp
;
159 struct ureg_dst fragment
;
162 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
166 for (i
= 0; i
< 3; ++i
) {
167 tc
[i
] = ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, i
+ 1, TGSI_INTERPOLATE_LINEAR
);
168 sampler
[i
] = ureg_DECL_sampler(shader
, i
);
170 texel
= ureg_DECL_temporary(shader
);
171 temp
= ureg_DECL_temporary(shader
);
172 fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
175 * texel.r = tex(tc[0], sampler[0])
176 * texel.g = tex(tc[1], sampler[1])
177 * texel.b = tex(tc[2], sampler[2])
178 * fragment = texel * scale
180 for (i
= 0; i
< 3; ++i
) {
181 /* Nouveau can't writemask tex dst regs (yet?), do in two steps */
182 ureg_TEX(shader
, temp
, TGSI_TEXTURE_2D
, tc
[i
], sampler
[i
]);
183 ureg_MOV(shader
, ureg_writemask(texel
, TGSI_WRITEMASK_X
<< i
), ureg_scalar(ureg_src(temp
), TGSI_SWIZZLE_X
));
185 ureg_MUL(shader
, fragment
, ureg_src(texel
), ureg_scalar(ureg_imm1f(shader
, SCALE_FACTOR_16_TO_9
), TGSI_SWIZZLE_X
));
187 ureg_release_temporary(shader
, texel
);
188 ureg_release_temporary(shader
, temp
);
191 return ureg_create_shader_and_destroy(shader
, r
->pipe
);
195 create_frame_pred_frag_shader(struct vl_mpeg12_mc_renderer
*r
)
197 struct ureg_program
*shader
;
198 struct ureg_src tc
[4];
199 struct ureg_src sampler
[4];
200 struct ureg_dst texel
, ref
;
201 struct ureg_dst fragment
;
204 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
208 for (i
= 0; i
< 4; ++i
) {
209 tc
[i
] = ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, i
+ 1, TGSI_INTERPOLATE_LINEAR
);
210 sampler
[i
] = ureg_DECL_sampler(shader
, i
);
212 texel
= ureg_DECL_temporary(shader
);
213 ref
= ureg_DECL_temporary(shader
);
214 fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
217 * texel.r = tex(tc[0], sampler[0])
218 * texel.g = tex(tc[1], sampler[1])
219 * texel.b = tex(tc[2], sampler[2])
220 * ref = tex(tc[3], sampler[3])
221 * fragment = texel * scale + ref
223 for (i
= 0; i
< 3; ++i
) {
224 /* Nouveau can't writemask tex dst regs (yet?), do in two steps */
225 ureg_TEX(shader
, ref
, TGSI_TEXTURE_2D
, tc
[i
], sampler
[i
]);
226 ureg_MOV(shader
, ureg_writemask(texel
, TGSI_WRITEMASK_X
<< i
), ureg_scalar(ureg_src(ref
), TGSI_SWIZZLE_X
));
228 ureg_TEX(shader
, ref
, TGSI_TEXTURE_2D
, tc
[3], sampler
[3]);
229 ureg_MAD(shader
, fragment
, ureg_src(texel
), ureg_scalar(ureg_imm1f(shader
, SCALE_FACTOR_16_TO_9
), TGSI_SWIZZLE_X
), ureg_src(ref
));
231 ureg_release_temporary(shader
, texel
);
232 ureg_release_temporary(shader
, ref
);
235 return ureg_create_shader_and_destroy(shader
, r
->pipe
);
239 create_field_pred_frag_shader(struct vl_mpeg12_mc_renderer
*r
)
241 struct ureg_program
*shader
;
242 struct ureg_src tc
[5], line
;
243 struct ureg_src sampler
[4];
244 struct ureg_dst texel
, ref
, tmp
;
245 struct ureg_dst fragment
;
248 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
252 for (i
= 0; i
< 5; ++i
)
253 tc
[i
] = ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, i
+ 1, TGSI_INTERPOLATE_LINEAR
);
254 line
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, 6, TGSI_INTERPOLATE_LINEAR
);
255 for (i
= 0; i
< 4; ++i
)
256 sampler
[i
] = ureg_DECL_sampler(shader
, i
);
258 texel
= ureg_DECL_temporary(shader
);
259 ref
= ureg_DECL_temporary(shader
);
260 tmp
= ureg_DECL_temporary(shader
);
261 fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
264 * texel.r = tex(tc[0], sampler[0])
265 * texel.g = tex(tc[1], sampler[1])
266 * texel.b = tex(tc[2], sampler[2])
268 * ref = tex(tc[3], sampler[3])
270 * ref = tex(tc[4], sampler[3])
271 * fragment = texel * scale + ref
273 for (i
= 0; i
< 3; ++i
) {
274 /* Nouveau can't writemask tex dst regs (yet?), do in two steps */
275 ureg_TEX(shader
, tmp
, TGSI_TEXTURE_2D
, tc
[i
], sampler
[i
]);
276 ureg_MOV(shader
, ureg_writemask(texel
, TGSI_WRITEMASK_X
<< i
), ureg_scalar(ureg_src(tmp
), TGSI_SWIZZLE_X
));
279 ureg_FRC(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_Y
), line
);
280 ureg_SGE(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_Y
), ureg_src(tmp
), ureg_imm1f(shader
, 0.5f
));
281 ureg_IF(shader
, ureg_scalar(ureg_src(tmp
), TGSI_SWIZZLE_Y
), &label
);
282 ureg_TEX(shader
, ref
, TGSI_TEXTURE_2D
, tc
[4], sampler
[3]);
283 ureg_ELSE(shader
, &label
);
284 ureg_TEX(shader
, ref
, TGSI_TEXTURE_2D
, tc
[3], sampler
[3]);
287 ureg_MAD(shader
, fragment
, ureg_src(texel
), ureg_scalar(ureg_imm1f(shader
, SCALE_FACTOR_16_TO_9
), TGSI_SWIZZLE_X
), ureg_src(ref
));
289 ureg_release_temporary(shader
, tmp
);
290 ureg_release_temporary(shader
, texel
);
291 ureg_release_temporary(shader
, ref
);
294 return ureg_create_shader_and_destroy(shader
, r
->pipe
);
298 create_frame_bi_pred_frag_shader(struct vl_mpeg12_mc_renderer
*r
)
300 struct ureg_program
*shader
;
301 struct ureg_src tc
[5];
302 struct ureg_src sampler
[5];
303 struct ureg_dst texel
, ref
[2], tmp
;
304 struct ureg_dst fragment
;
307 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
311 for (i
= 0; i
< 5; ++i
) {
312 tc
[i
] = ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, i
+ 1, TGSI_INTERPOLATE_LINEAR
);
313 sampler
[i
] = ureg_DECL_sampler(shader
, i
);
315 texel
= ureg_DECL_temporary(shader
);
316 ref
[0] = ureg_DECL_temporary(shader
);
317 ref
[1] = ureg_DECL_temporary(shader
);
318 tmp
= ureg_DECL_temporary(shader
);
319 fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
322 * texel.r = tex(tc[0], sampler[0])
323 * texel.g = tex(tc[1], sampler[1])
324 * texel.b = tex(tc[2], sampler[2])
325 * ref[0..1 = tex(tc[3..4], sampler[3..4])
326 * ref[0] = lerp(ref[0], ref[1], 0.5)
327 * fragment = texel * scale + ref[0]
329 for (i
= 0; i
< 3; ++i
) {
330 /* Nouveau can't writemask tex dst regs (yet?), do in two steps */
331 ureg_TEX(shader
, tmp
, TGSI_TEXTURE_2D
, tc
[i
], sampler
[i
]);
332 ureg_MOV(shader
, ureg_writemask(texel
, TGSI_WRITEMASK_X
<< i
), ureg_scalar(ureg_src(tmp
), TGSI_SWIZZLE_X
));
334 ureg_TEX(shader
, ref
[0], TGSI_TEXTURE_2D
, tc
[3], sampler
[3]);
335 ureg_TEX(shader
, ref
[1], TGSI_TEXTURE_2D
, tc
[4], sampler
[4]);
336 ureg_LRP(shader
, ref
[0], ureg_scalar(ureg_imm1f(shader
, 0.5f
), TGSI_SWIZZLE_X
), ureg_src(ref
[0]), ureg_src(ref
[1]));
338 ureg_MAD(shader
, fragment
, ureg_src(texel
), ureg_scalar(ureg_imm1f(shader
, SCALE_FACTOR_16_TO_9
), TGSI_SWIZZLE_X
), ureg_src(ref
[0]));
340 ureg_release_temporary(shader
, tmp
);
341 ureg_release_temporary(shader
, texel
);
342 ureg_release_temporary(shader
, ref
[0]);
343 ureg_release_temporary(shader
, ref
[1]);
346 return ureg_create_shader_and_destroy(shader
, r
->pipe
);
350 create_field_bi_pred_frag_shader(struct vl_mpeg12_mc_renderer
*r
)
352 struct ureg_program
*shader
;
353 struct ureg_src tc
[7], line
;
354 struct ureg_src sampler
[5];
355 struct ureg_dst texel
, ref
[2], tmp
;
356 struct ureg_dst fragment
;
359 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
363 for (i
= 0; i
< 7; ++i
)
364 tc
[i
] = ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, i
+ 1, TGSI_INTERPOLATE_LINEAR
);
365 line
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, 8, TGSI_INTERPOLATE_LINEAR
);
366 for (i
= 0; i
< 5; ++i
)
367 sampler
[i
] = ureg_DECL_sampler(shader
, i
);
369 texel
= ureg_DECL_temporary(shader
);
370 ref
[0] = ureg_DECL_temporary(shader
);
371 ref
[1] = ureg_DECL_temporary(shader
);
372 tmp
= ureg_DECL_temporary(shader
);
373 fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
376 * texel.r = tex(tc[0], sampler[0])
377 * texel.g = tex(tc[1], sampler[1])
378 * texel.b = tex(tc[2], sampler[2])
379 * ref[0..1 = tex(tc[3..4], sampler[3..4])
380 * ref[0] = lerp(ref[0], ref[1], 0.5)
381 * fragment = texel * scale + ref[0]
383 for (i
= 0; i
< 3; ++i
) {
384 /* Nouveau can't writemask tex dst regs (yet?), do in two steps */
385 ureg_TEX(shader
, ref
[0], TGSI_TEXTURE_2D
, tc
[i
], sampler
[i
]);
386 ureg_MOV(shader
, ureg_writemask(texel
, TGSI_WRITEMASK_X
<< i
), ureg_scalar(ureg_src(ref
[0]), TGSI_SWIZZLE_X
));
389 ureg_FRC(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_Y
), line
);
390 ureg_SGE(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_Y
), ureg_src(tmp
), ureg_imm1f(shader
, 0.5f
));
391 ureg_IF(shader
, ureg_scalar(ureg_src(tmp
), TGSI_SWIZZLE_Y
), &label
);
392 ureg_TEX(shader
, ref
[0], TGSI_TEXTURE_2D
, tc
[4], sampler
[3]);
393 ureg_TEX(shader
, ref
[1], TGSI_TEXTURE_2D
, tc
[6], sampler
[4]);
394 ureg_ELSE(shader
, &label
);
395 ureg_TEX(shader
, ref
[0], TGSI_TEXTURE_2D
, tc
[3], sampler
[3]);
396 ureg_TEX(shader
, ref
[1], TGSI_TEXTURE_2D
, tc
[5], sampler
[4]);
399 ureg_LRP(shader
, ref
[0], ureg_scalar(ureg_imm1f(shader
, 0.5f
), TGSI_SWIZZLE_X
), ureg_src(ref
[0]), ureg_src(ref
[1]));
401 ureg_MAD(shader
, fragment
, ureg_src(texel
), ureg_scalar(ureg_imm1f(shader
, SCALE_FACTOR_16_TO_9
), TGSI_SWIZZLE_X
), ureg_src(ref
[0]));
403 ureg_release_temporary(shader
, tmp
);
404 ureg_release_temporary(shader
, texel
);
405 ureg_release_temporary(shader
, ref
[0]);
406 ureg_release_temporary(shader
, ref
[1]);
409 return ureg_create_shader_and_destroy(shader
, r
->pipe
);
413 xfer_buffers_map(struct vl_mpeg12_mc_renderer
*r
)
419 for (i
= 0; i
< 3; ++i
) {
420 struct pipe_box rect
=
423 r
->textures
.all
[i
]->width0
,
424 r
->textures
.all
[i
]->height0
,
428 r
->tex_transfer
[i
] = r
->pipe
->get_transfer
430 r
->pipe
, r
->textures
.all
[i
],
432 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD
,
436 r
->texels
[i
] = r
->pipe
->transfer_map(r
->pipe
, r
->tex_transfer
[i
]);
441 xfer_buffers_unmap(struct vl_mpeg12_mc_renderer
*r
)
447 for (i
= 0; i
< 3; ++i
) {
448 r
->pipe
->transfer_unmap(r
->pipe
, r
->tex_transfer
[i
]);
449 r
->pipe
->transfer_destroy(r
->pipe
, r
->tex_transfer
[i
]);
454 init_pipe_state(struct vl_mpeg12_mc_renderer
*r
)
456 struct pipe_sampler_state sampler
;
462 r
->viewport
.scale
[0] = r
->pot_buffers
?
463 util_next_power_of_two(r
->picture_width
) : r
->picture_width
;
464 r
->viewport
.scale
[1] = r
->pot_buffers
?
465 util_next_power_of_two(r
->picture_height
) : r
->picture_height
;
466 r
->viewport
.scale
[2] = 1;
467 r
->viewport
.scale
[3] = 1;
468 r
->viewport
.translate
[0] = 0;
469 r
->viewport
.translate
[1] = 0;
470 r
->viewport
.translate
[2] = 0;
471 r
->viewport
.translate
[3] = 0;
473 r
->fb_state
.width
= r
->pot_buffers
?
474 util_next_power_of_two(r
->picture_width
) : r
->picture_width
;
475 r
->fb_state
.height
= r
->pot_buffers
?
476 util_next_power_of_two(r
->picture_height
) : r
->picture_height
;
477 r
->fb_state
.nr_cbufs
= 1;
478 r
->fb_state
.zsbuf
= NULL
;
481 filters
[0] = PIPE_TEX_FILTER_NEAREST
;
483 if (r
->chroma_format
== PIPE_VIDEO_CHROMA_FORMAT_444
||
484 r
->eb_handling
== VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_ONE
) {
485 filters
[1] = PIPE_TEX_FILTER_NEAREST
;
486 filters
[2] = PIPE_TEX_FILTER_NEAREST
;
489 filters
[1] = PIPE_TEX_FILTER_LINEAR
;
490 filters
[2] = PIPE_TEX_FILTER_LINEAR
;
492 /* Fwd, bkwd ref filters */
493 filters
[3] = PIPE_TEX_FILTER_LINEAR
;
494 filters
[4] = PIPE_TEX_FILTER_LINEAR
;
496 for (i
= 0; i
< 5; ++i
) {
497 memset(&sampler
, 0, sizeof(sampler
));
498 sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
499 sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
500 sampler
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
501 sampler
.min_img_filter
= filters
[i
];
502 sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
503 sampler
.mag_img_filter
= filters
[i
];
504 sampler
.compare_mode
= PIPE_TEX_COMPARE_NONE
;
505 sampler
.compare_func
= PIPE_FUNC_ALWAYS
;
506 sampler
.normalized_coords
= 1;
507 /*sampler.shadow_ambient = ; */
508 /*sampler.lod_bias = ; */
510 /*sampler.max_lod = ; */
511 /*sampler.border_color[i] = ; */
512 /*sampler.max_anisotropy = ; */
513 r
->samplers
.all
[i
] = r
->pipe
->create_sampler_state(r
->pipe
, &sampler
);
520 cleanup_pipe_state(struct vl_mpeg12_mc_renderer
*r
)
526 for (i
= 0; i
< 5; ++i
)
527 r
->pipe
->delete_sampler_state(r
->pipe
, r
->samplers
.all
[i
]);
531 init_shaders(struct vl_mpeg12_mc_renderer
*r
)
535 assert(r
->i_vs
= create_vert_shader(r
, 0, 0));
536 assert(r
->i_fs
= create_intra_frag_shader(r
));
538 assert(r
->p_vs
[0] = create_vert_shader(r
, 1, 1));
539 assert(r
->p_vs
[1] = create_vert_shader(r
, 1, 2));
540 assert(r
->p_fs
[0] = create_frame_pred_frag_shader(r
));
541 assert(r
->p_fs
[1] = create_field_pred_frag_shader(r
));
543 assert(r
->b_vs
[0] = create_vert_shader(r
, 2, 1));
544 assert(r
->b_vs
[1] = create_vert_shader(r
, 2, 2));
545 assert(r
->b_fs
[0] = create_frame_bi_pred_frag_shader(r
));
546 assert(r
->b_fs
[1] = create_field_bi_pred_frag_shader(r
));
552 cleanup_shaders(struct vl_mpeg12_mc_renderer
*r
)
556 r
->pipe
->delete_vs_state(r
->pipe
, r
->i_vs
);
557 r
->pipe
->delete_fs_state(r
->pipe
, r
->i_fs
);
558 r
->pipe
->delete_vs_state(r
->pipe
, r
->p_vs
[0]);
559 r
->pipe
->delete_vs_state(r
->pipe
, r
->p_vs
[1]);
560 r
->pipe
->delete_fs_state(r
->pipe
, r
->p_fs
[0]);
561 r
->pipe
->delete_fs_state(r
->pipe
, r
->p_fs
[1]);
562 r
->pipe
->delete_vs_state(r
->pipe
, r
->b_vs
[0]);
563 r
->pipe
->delete_vs_state(r
->pipe
, r
->b_vs
[1]);
564 r
->pipe
->delete_fs_state(r
->pipe
, r
->b_fs
[0]);
565 r
->pipe
->delete_fs_state(r
->pipe
, r
->b_fs
[1]);
569 init_buffers(struct vl_mpeg12_mc_renderer
*r
)
571 struct pipe_resource
template;
572 struct pipe_vertex_element vertex_elems
[8];
573 struct pipe_sampler_view sampler_view
;
576 align(r
->picture_width
, MACROBLOCK_WIDTH
) / MACROBLOCK_WIDTH
;
578 align(r
->picture_height
, MACROBLOCK_HEIGHT
) / MACROBLOCK_HEIGHT
;
584 r
->macroblocks_per_batch
=
585 mbw
* (r
->bufmode
== VL_MPEG12_MC_RENDERER_BUFFER_PICTURE
? mbh
: 1);
586 r
->num_macroblocks
= 0;
587 r
->macroblock_buf
= MALLOC(r
->macroblocks_per_batch
* sizeof(struct pipe_mpeg12_macroblock
));
589 memset(&template, 0, sizeof(struct pipe_resource
));
590 template.target
= PIPE_TEXTURE_2D
;
591 /* TODO: Accomodate HW that can't do this and also for cases when this isn't precise enough */
592 template.format
= PIPE_FORMAT_R16_SNORM
;
593 template.last_level
= 0;
594 template.width0
= r
->pot_buffers
?
595 util_next_power_of_two(r
->picture_width
) : r
->picture_width
;
596 template.height0
= r
->pot_buffers
?
597 util_next_power_of_two(r
->picture_height
) : r
->picture_height
;
599 template.usage
= PIPE_USAGE_DYNAMIC
;
600 template.bind
= PIPE_BIND_SAMPLER_VIEW
;
603 r
->textures
.individual
.y
= r
->pipe
->screen
->resource_create(r
->pipe
->screen
, &template);
605 if (r
->chroma_format
== PIPE_VIDEO_CHROMA_FORMAT_420
) {
606 template.width0
= r
->pot_buffers
?
607 util_next_power_of_two(r
->picture_width
/ 2) :
608 r
->picture_width
/ 2;
609 template.height0
= r
->pot_buffers
?
610 util_next_power_of_two(r
->picture_height
/ 2) :
611 r
->picture_height
/ 2;
613 else if (r
->chroma_format
== PIPE_VIDEO_CHROMA_FORMAT_422
)
614 template.height0
= r
->pot_buffers
?
615 util_next_power_of_two(r
->picture_height
/ 2) :
616 r
->picture_height
/ 2;
618 r
->textures
.individual
.cb
=
619 r
->pipe
->screen
->resource_create(r
->pipe
->screen
, &template);
620 r
->textures
.individual
.cr
=
621 r
->pipe
->screen
->resource_create(r
->pipe
->screen
, &template);
623 for (i
= 0; i
< 3; ++i
) {
624 u_sampler_view_default_template(&sampler_view
,
626 r
->textures
.all
[i
]->format
);
627 r
->sampler_views
.all
[i
] = r
->pipe
->create_sampler_view(r
->pipe
, r
->textures
.all
[i
], &sampler_view
);
630 r
->vertex_bufs
.individual
.ycbcr
.stride
= sizeof(struct vertex2f
) * 4;
631 r
->vertex_bufs
.individual
.ycbcr
.max_index
= 24 * r
->macroblocks_per_batch
- 1;
632 r
->vertex_bufs
.individual
.ycbcr
.buffer_offset
= 0;
633 /* XXX: Create with usage DYNAMIC or STREAM */
634 r
->vertex_bufs
.individual
.ycbcr
.buffer
= pipe_buffer_create
637 PIPE_BIND_VERTEX_BUFFER
,
638 sizeof(struct vertex2f
) * 4 * 24 * r
->macroblocks_per_batch
641 for (i
= 1; i
< 3; ++i
) {
642 r
->vertex_bufs
.all
[i
].stride
= sizeof(struct vertex2f
) * 2;
643 r
->vertex_bufs
.all
[i
].max_index
= 24 * r
->macroblocks_per_batch
- 1;
644 r
->vertex_bufs
.all
[i
].buffer_offset
= 0;
645 /* XXX: Create with usage DYNAMIC or STREAM */
646 r
->vertex_bufs
.all
[i
].buffer
= pipe_buffer_create
649 PIPE_BIND_VERTEX_BUFFER
,
650 sizeof(struct vertex2f
) * 2 * 24 * r
->macroblocks_per_batch
654 memset(&vertex_elems
, 0, sizeof(vertex_elems
));
656 /* Position element */
657 vertex_elems
[0].src_offset
= 0;
658 vertex_elems
[0].instance_divisor
= 0;
659 vertex_elems
[0].vertex_buffer_index
= 0;
660 vertex_elems
[0].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
662 /* Luma, texcoord element */
663 vertex_elems
[1].src_offset
= sizeof(struct vertex2f
);
664 vertex_elems
[1].instance_divisor
= 0;
665 vertex_elems
[1].vertex_buffer_index
= 0;
666 vertex_elems
[1].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
668 /* Chroma Cr texcoord element */
669 vertex_elems
[2].src_offset
= sizeof(struct vertex2f
) * 2;
670 vertex_elems
[2].instance_divisor
= 0;
671 vertex_elems
[2].vertex_buffer_index
= 0;
672 vertex_elems
[2].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
674 /* Chroma Cb texcoord element */
675 vertex_elems
[3].src_offset
= sizeof(struct vertex2f
) * 3;
676 vertex_elems
[3].instance_divisor
= 0;
677 vertex_elems
[3].vertex_buffer_index
= 0;
678 vertex_elems
[3].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
680 /* First ref surface top field texcoord element */
681 vertex_elems
[4].src_offset
= 0;
682 vertex_elems
[4].instance_divisor
= 0;
683 vertex_elems
[4].vertex_buffer_index
= 1;
684 vertex_elems
[4].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
686 /* First ref surface bottom field texcoord element */
687 vertex_elems
[5].src_offset
= sizeof(struct vertex2f
);
688 vertex_elems
[5].instance_divisor
= 0;
689 vertex_elems
[5].vertex_buffer_index
= 1;
690 vertex_elems
[5].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
692 /* Second ref surface top field texcoord element */
693 vertex_elems
[6].src_offset
= 0;
694 vertex_elems
[6].instance_divisor
= 0;
695 vertex_elems
[6].vertex_buffer_index
= 2;
696 vertex_elems
[6].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
698 /* Second ref surface bottom field texcoord element */
699 vertex_elems
[7].src_offset
= sizeof(struct vertex2f
);
700 vertex_elems
[7].instance_divisor
= 0;
701 vertex_elems
[7].vertex_buffer_index
= 2;
702 vertex_elems
[7].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
704 r
->vertex_elems_state
.individual
.i
= r
->pipe
->create_vertex_elements_state(r
->pipe
, 4, vertex_elems
);
705 r
->vertex_elems_state
.individual
.p
= r
->pipe
->create_vertex_elements_state(r
->pipe
, 6, vertex_elems
);
706 r
->vertex_elems_state
.individual
.b
= r
->pipe
->create_vertex_elements_state(r
->pipe
, 8, vertex_elems
);
708 r
->vs_const_buf
= pipe_buffer_create
711 PIPE_BIND_CONSTANT_BUFFER
,
712 sizeof(struct vertex_shader_consts
)
719 cleanup_buffers(struct vl_mpeg12_mc_renderer
*r
)
725 pipe_resource_reference(&r
->vs_const_buf
, NULL
);
727 for (i
= 0; i
< 3; ++i
) {
728 pipe_sampler_view_reference(&r
->sampler_views
.all
[i
], NULL
);
729 r
->pipe
->delete_vertex_elements_state(r
->pipe
, r
->vertex_elems_state
.all
[i
]);
730 pipe_resource_reference(&r
->vertex_bufs
.all
[i
].buffer
, NULL
);
731 pipe_resource_reference(&r
->textures
.all
[i
], NULL
);
734 FREE(r
->macroblock_buf
);
737 static enum MACROBLOCK_TYPE
738 get_macroblock_type(struct pipe_mpeg12_macroblock
*mb
)
742 switch (mb
->mb_type
) {
743 case PIPE_MPEG12_MACROBLOCK_TYPE_INTRA
:
744 return MACROBLOCK_TYPE_INTRA
;
745 case PIPE_MPEG12_MACROBLOCK_TYPE_FWD
:
746 return mb
->mo_type
== PIPE_MPEG12_MOTION_TYPE_FRAME
?
747 MACROBLOCK_TYPE_FWD_FRAME_PRED
: MACROBLOCK_TYPE_FWD_FIELD_PRED
;
748 case PIPE_MPEG12_MACROBLOCK_TYPE_BKWD
:
749 return mb
->mo_type
== PIPE_MPEG12_MOTION_TYPE_FRAME
?
750 MACROBLOCK_TYPE_BKWD_FRAME_PRED
: MACROBLOCK_TYPE_BKWD_FIELD_PRED
;
751 case PIPE_MPEG12_MACROBLOCK_TYPE_BI
:
752 return mb
->mo_type
== PIPE_MPEG12_MOTION_TYPE_FRAME
?
753 MACROBLOCK_TYPE_BI_FRAME_PRED
: MACROBLOCK_TYPE_BI_FIELD_PRED
;
763 gen_block_verts(struct vert_stream_0
*vb
, struct pipe_mpeg12_macroblock
*mb
,
764 const struct vertex2f
*offset
,
765 unsigned luma_mask
, unsigned cb_mask
, unsigned cr_mask
,
766 bool use_zeroblocks
, struct vertex2f
*zero_blocks
)
768 unsigned cbp
= mb
->cbp
;
769 unsigned mbx
= mb
->mbx
;
770 unsigned mby
= mb
->mby
;
772 const struct vertex2f half
=
781 assert(zero_blocks
|| !use_zeroblocks
);
783 /* Generate vertices for two triangles covering a block */
784 v
.x
= mbx
+ offset
->x
;
785 v
.y
= mby
+ offset
->y
;
790 vb
[1].pos
.y
= v
.y
+ half
.y
;
791 vb
[2].pos
.x
= v
.x
+ half
.x
;
793 vb
[3].pos
.x
= v
.x
+ half
.x
;
796 vb
[4].pos
.y
= v
.y
+ half
.y
;
797 vb
[5].pos
.x
= v
.x
+ half
.x
;
798 vb
[5].pos
.y
= v
.y
+ half
.y
;
800 /* Generate texcoords for the triangles, either pointing to the correct area on the luma/chroma texture
801 or if zero blocks are being used, to the zero block if the appropriate CBP bits aren't set (i.e. no data
802 for this channel is defined for this block) */
804 if (!use_zeroblocks
|| cbp
& luma_mask
|| mb
->dct_type
== PIPE_MPEG12_DCT_TYPE_FIELD
) {
805 v
.x
= mbx
+ offset
->x
;
806 v
.y
= mby
+ offset
->y
;
809 v
.x
= zero_blocks
[0].x
;
810 v
.y
= zero_blocks
[0].y
;
813 vb
[0].luma_tc
.x
= v
.x
;
814 vb
[0].luma_tc
.y
= v
.y
;
815 vb
[1].luma_tc
.x
= v
.x
;
816 vb
[1].luma_tc
.y
= v
.y
+ half
.y
;
817 vb
[2].luma_tc
.x
= v
.x
+ half
.x
;
818 vb
[2].luma_tc
.y
= v
.y
;
819 vb
[3].luma_tc
.x
= v
.x
+ half
.x
;
820 vb
[3].luma_tc
.y
= v
.y
;
821 vb
[4].luma_tc
.x
= v
.x
;
822 vb
[4].luma_tc
.y
= v
.y
+ half
.y
;
823 vb
[5].luma_tc
.x
= v
.x
+ half
.x
;
824 vb
[5].luma_tc
.y
= v
.y
+ half
.y
;
826 if (!use_zeroblocks
|| cbp
& cb_mask
) {
827 v
.x
= mbx
+ offset
->x
;
828 v
.y
= mby
+ offset
->y
;
831 v
.x
= zero_blocks
[1].x
;
832 v
.y
= zero_blocks
[1].y
;
838 vb
[1].cb_tc
.y
= v
.y
+ half
.y
;
839 vb
[2].cb_tc
.x
= v
.x
+ half
.x
;
841 vb
[3].cb_tc
.x
= v
.x
+ half
.x
;
844 vb
[4].cb_tc
.y
= v
.y
+ half
.y
;
845 vb
[5].cb_tc
.x
= v
.x
+ half
.x
;
846 vb
[5].cb_tc
.y
= v
.y
+ half
.y
;
848 if (!use_zeroblocks
|| cbp
& cr_mask
) {
849 v
.x
= mbx
+ offset
->x
;
850 v
.y
= mby
+ offset
->y
;
853 v
.x
= zero_blocks
[2].x
;
854 v
.y
= zero_blocks
[2].y
;
860 vb
[1].cr_tc
.y
= v
.y
+ half
.y
;
861 vb
[2].cr_tc
.x
= v
.x
+ half
.x
;
863 vb
[3].cr_tc
.x
= v
.x
+ half
.x
;
866 vb
[4].cr_tc
.y
= v
.y
+ half
.y
;
867 vb
[5].cr_tc
.x
= v
.x
+ half
.x
;
868 vb
[5].cr_tc
.y
= v
.y
+ half
.y
;
872 gen_macroblock_verts(struct vl_mpeg12_mc_renderer
*r
,
873 struct pipe_mpeg12_macroblock
*mb
, unsigned pos
,
874 struct vert_stream_0
*ycbcr_vb
, struct vertex2f
**ref_vb
)
876 struct vertex2f mo_vec
[2];
883 assert(pos
< r
->macroblocks_per_batch
);
888 switch (mb
->mb_type
) {
889 case PIPE_MPEG12_MACROBLOCK_TYPE_BI
:
893 assert(ref_vb
&& ref_vb
[1]);
895 vb
= ref_vb
[1] + pos
* 2 * 24;
897 mo_vec
[0].x
= mb
->pmv
[0][1][0];
898 mo_vec
[0].y
= mb
->pmv
[0][1][1];
900 if (mb
->mo_type
== PIPE_MPEG12_MOTION_TYPE_FRAME
) {
901 for (i
= 0; i
< 24 * 2; i
+= 2) {
902 vb
[i
].x
= mo_vec
[0].x
;
903 vb
[i
].y
= mo_vec
[0].y
;
907 mo_vec
[1].x
= mb
->pmv
[1][1][0];
908 mo_vec
[1].y
= mb
->pmv
[1][1][1];
910 for (i
= 0; i
< 24 * 2; i
+= 2) {
911 vb
[i
].x
= mo_vec
[0].x
;
912 vb
[i
].y
= mo_vec
[0].y
;
913 vb
[i
+ 1].x
= mo_vec
[1].x
;
914 vb
[i
+ 1].y
= mo_vec
[1].y
;
920 case PIPE_MPEG12_MACROBLOCK_TYPE_FWD
:
921 case PIPE_MPEG12_MACROBLOCK_TYPE_BKWD
:
925 assert(ref_vb
&& ref_vb
[0]);
927 vb
= ref_vb
[0] + pos
* 2 * 24;
929 if (mb
->mb_type
== PIPE_MPEG12_MACROBLOCK_TYPE_BKWD
) {
930 mo_vec
[0].x
= mb
->pmv
[0][1][0];
931 mo_vec
[0].y
= mb
->pmv
[0][1][1];
933 if (mb
->mo_type
== PIPE_MPEG12_MOTION_TYPE_FIELD
) {
934 mo_vec
[1].x
= mb
->pmv
[1][1][0];
935 mo_vec
[1].y
= mb
->pmv
[1][1][1];
939 mo_vec
[0].x
= mb
->pmv
[0][0][0];
940 mo_vec
[0].y
= mb
->pmv
[0][0][1];
942 if (mb
->mo_type
== PIPE_MPEG12_MOTION_TYPE_FIELD
) {
943 mo_vec
[1].x
= mb
->pmv
[1][0][0];
944 mo_vec
[1].y
= mb
->pmv
[1][0][1];
948 if (mb
->mo_type
== PIPE_MPEG12_MOTION_TYPE_FRAME
) {
949 for (i
= 0; i
< 24 * 2; i
+= 2) {
950 vb
[i
].x
= mo_vec
[0].x
;
951 vb
[i
].y
= mo_vec
[0].y
;
955 for (i
= 0; i
< 24 * 2; i
+= 2) {
956 vb
[i
].x
= mo_vec
[0].x
;
957 vb
[i
].y
= mo_vec
[0].y
;
958 vb
[i
+ 1].x
= mo_vec
[1].x
;
959 vb
[i
+ 1].y
= mo_vec
[1].y
;
965 case PIPE_MPEG12_MACROBLOCK_TYPE_INTRA
:
967 const struct vertex2f offsets
[2][2] =
973 {0.5f
, 0}, {0.5f
, 0.5f
}
976 const bool use_zb
= r
->eb_handling
== VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_ONE
;
978 struct vert_stream_0
*vb
= ycbcr_vb
+ pos
* 24;
980 gen_block_verts(vb
, mb
, &offsets
[0][0],
981 32, 2, 1, use_zb
, r
->zero_block
);
983 gen_block_verts(vb
+ 6, mb
, &offsets
[1][0],
984 16, 2, 1, use_zb
, r
->zero_block
);
986 gen_block_verts(vb
+ 12, mb
, &offsets
[0][1],
987 8, 2, 1, use_zb
, r
->zero_block
);
989 gen_block_verts(vb
+ 18, mb
, &offsets
[1][1],
990 4, 2, 1, use_zb
, r
->zero_block
);
1000 gen_macroblock_stream(struct vl_mpeg12_mc_renderer
*r
,
1001 unsigned *num_macroblocks
)
1003 unsigned offset
[NUM_MACROBLOCK_TYPES
];
1004 struct vert_stream_0
*ycbcr_vb
;
1005 struct vertex2f
*ref_vb
[2];
1006 struct pipe_transfer
*buf_transfer
[3];
1010 assert(num_macroblocks
);
1012 for (i
= 0; i
< r
->num_macroblocks
; ++i
) {
1013 enum MACROBLOCK_TYPE mb_type
= get_macroblock_type(&r
->macroblock_buf
[i
]);
1014 ++num_macroblocks
[mb_type
];
1019 for (i
= 1; i
< NUM_MACROBLOCK_TYPES
; ++i
)
1020 offset
[i
] = offset
[i
- 1] + num_macroblocks
[i
- 1];
1022 ycbcr_vb
= (struct vert_stream_0
*)pipe_buffer_map
1025 r
->vertex_bufs
.individual
.ycbcr
.buffer
,
1026 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD
,
1030 for (i
= 0; i
< 2; ++i
)
1031 ref_vb
[i
] = (struct vertex2f
*)pipe_buffer_map
1034 r
->vertex_bufs
.individual
.ref
[i
].buffer
,
1035 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD
,
1036 &buf_transfer
[i
+ 1]
1039 for (i
= 0; i
< r
->num_macroblocks
; ++i
) {
1040 enum MACROBLOCK_TYPE mb_type
= get_macroblock_type(&r
->macroblock_buf
[i
]);
1042 gen_macroblock_verts(r
, &r
->macroblock_buf
[i
], offset
[mb_type
],
1048 pipe_buffer_unmap(r
->pipe
, r
->vertex_bufs
.individual
.ycbcr
.buffer
, buf_transfer
[0]);
1049 for (i
= 0; i
< 2; ++i
)
1050 pipe_buffer_unmap(r
->pipe
, r
->vertex_bufs
.individual
.ref
[i
].buffer
, buf_transfer
[i
+ 1]);
1053 static struct pipe_sampler_view
1054 *find_or_create_sampler_view(struct vl_mpeg12_mc_renderer
*r
, struct pipe_surface
*surface
)
1056 struct pipe_sampler_view
*sampler_view
;
1060 sampler_view
= (struct pipe_sampler_view
*)util_keymap_lookup(r
->texview_map
, &surface
);
1061 if (!sampler_view
) {
1062 struct pipe_sampler_view templat
;
1063 boolean added_to_map
;
1065 u_sampler_view_default_template(&templat
, surface
->texture
,
1066 surface
->texture
->format
);
1067 sampler_view
= r
->pipe
->create_sampler_view(r
->pipe
, surface
->texture
,
1072 added_to_map
= util_keymap_insert(r
->texview_map
, &surface
,
1073 sampler_view
, r
->pipe
);
1074 assert(added_to_map
);
1077 return sampler_view
;
1081 flush(struct vl_mpeg12_mc_renderer
*r
)
1083 unsigned num_macroblocks
[NUM_MACROBLOCK_TYPES
] = { 0 };
1084 unsigned vb_start
= 0;
1085 struct vertex_shader_consts
*vs_consts
;
1086 struct pipe_transfer
*buf_transfer
;
1090 assert(r
->num_macroblocks
== r
->macroblocks_per_batch
);
1092 gen_macroblock_stream(r
, num_macroblocks
);
1094 r
->fb_state
.cbufs
[0] = r
->surface
;
1096 r
->pipe
->set_framebuffer_state(r
->pipe
, &r
->fb_state
);
1097 r
->pipe
->set_viewport_state(r
->pipe
, &r
->viewport
);
1099 vs_consts
= pipe_buffer_map
1101 r
->pipe
, r
->vs_const_buf
,
1102 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD
,
1106 vs_consts
->norm
.x
= 1.0f
/ r
->surface
->width
;
1107 vs_consts
->norm
.y
= 1.0f
/ r
->surface
->height
;
1109 pipe_buffer_unmap(r
->pipe
, r
->vs_const_buf
, buf_transfer
);
1111 r
->pipe
->set_constant_buffer(r
->pipe
, PIPE_SHADER_VERTEX
, 0,
1114 if (num_macroblocks
[MACROBLOCK_TYPE_INTRA
] > 0) {
1115 r
->pipe
->set_vertex_buffers(r
->pipe
, 1, r
->vertex_bufs
.all
);
1116 r
->pipe
->bind_vertex_elements_state(r
->pipe
, r
->vertex_elems_state
.individual
.i
);
1117 r
->pipe
->set_fragment_sampler_views(r
->pipe
, 3, r
->sampler_views
.all
);
1118 r
->pipe
->bind_fragment_sampler_states(r
->pipe
, 3, r
->samplers
.all
);
1119 r
->pipe
->bind_vs_state(r
->pipe
, r
->i_vs
);
1120 r
->pipe
->bind_fs_state(r
->pipe
, r
->i_fs
);
1122 util_draw_arrays(r
->pipe
, PIPE_PRIM_TRIANGLES
, vb_start
,
1123 num_macroblocks
[MACROBLOCK_TYPE_INTRA
] * 24);
1124 vb_start
+= num_macroblocks
[MACROBLOCK_TYPE_INTRA
] * 24;
1127 if (num_macroblocks
[MACROBLOCK_TYPE_FWD_FRAME_PRED
] > 0) {
1128 r
->pipe
->set_vertex_buffers(r
->pipe
, 2, r
->vertex_bufs
.all
);
1129 r
->pipe
->bind_vertex_elements_state(r
->pipe
, r
->vertex_elems_state
.individual
.p
);
1130 r
->textures
.individual
.ref
[0] = r
->past
->texture
;
1131 r
->sampler_views
.individual
.ref
[0] = find_or_create_sampler_view(r
, r
->past
);
1132 r
->pipe
->set_fragment_sampler_views(r
->pipe
, 4, r
->sampler_views
.all
);
1133 r
->pipe
->bind_fragment_sampler_states(r
->pipe
, 4, r
->samplers
.all
);
1134 r
->pipe
->bind_vs_state(r
->pipe
, r
->p_vs
[0]);
1135 r
->pipe
->bind_fs_state(r
->pipe
, r
->p_fs
[0]);
1137 util_draw_arrays(r
->pipe
, PIPE_PRIM_TRIANGLES
, vb_start
,
1138 num_macroblocks
[MACROBLOCK_TYPE_FWD_FRAME_PRED
] * 24);
1139 vb_start
+= num_macroblocks
[MACROBLOCK_TYPE_FWD_FRAME_PRED
] * 24;
1142 if (num_macroblocks
[MACROBLOCK_TYPE_FWD_FIELD_PRED
] > 0) {
1143 r
->pipe
->set_vertex_buffers(r
->pipe
, 2, r
->vertex_bufs
.all
);
1144 r
->pipe
->bind_vertex_elements_state(r
->pipe
, r
->vertex_elems_state
.individual
.p
);
1145 r
->textures
.individual
.ref
[0] = r
->past
->texture
;
1146 r
->sampler_views
.individual
.ref
[0] = find_or_create_sampler_view(r
, r
->past
);
1147 r
->pipe
->set_fragment_sampler_views(r
->pipe
, 4, r
->sampler_views
.all
);
1148 r
->pipe
->bind_fragment_sampler_states(r
->pipe
, 4, r
->samplers
.all
);
1149 r
->pipe
->bind_vs_state(r
->pipe
, r
->p_vs
[1]);
1150 r
->pipe
->bind_fs_state(r
->pipe
, r
->p_fs
[1]);
1152 util_draw_arrays(r
->pipe
, PIPE_PRIM_TRIANGLES
, vb_start
,
1153 num_macroblocks
[MACROBLOCK_TYPE_FWD_FIELD_PRED
] * 24);
1154 vb_start
+= num_macroblocks
[MACROBLOCK_TYPE_FWD_FIELD_PRED
] * 24;
1157 if (num_macroblocks
[MACROBLOCK_TYPE_BKWD_FRAME_PRED
] > 0) {
1158 r
->pipe
->set_vertex_buffers(r
->pipe
, 2, r
->vertex_bufs
.all
);
1159 r
->pipe
->bind_vertex_elements_state(r
->pipe
, r
->vertex_elems_state
.individual
.p
);
1160 r
->textures
.individual
.ref
[0] = r
->future
->texture
;
1161 r
->sampler_views
.individual
.ref
[0] = find_or_create_sampler_view(r
, r
->future
);
1162 r
->pipe
->set_fragment_sampler_views(r
->pipe
, 4, r
->sampler_views
.all
);
1163 r
->pipe
->bind_fragment_sampler_states(r
->pipe
, 4, r
->samplers
.all
);
1164 r
->pipe
->bind_vs_state(r
->pipe
, r
->p_vs
[0]);
1165 r
->pipe
->bind_fs_state(r
->pipe
, r
->p_fs
[0]);
1167 util_draw_arrays(r
->pipe
, PIPE_PRIM_TRIANGLES
, vb_start
,
1168 num_macroblocks
[MACROBLOCK_TYPE_BKWD_FRAME_PRED
] * 24);
1169 vb_start
+= num_macroblocks
[MACROBLOCK_TYPE_BKWD_FRAME_PRED
] * 24;
1172 if (num_macroblocks
[MACROBLOCK_TYPE_BKWD_FIELD_PRED
] > 0) {
1173 r
->pipe
->set_vertex_buffers(r
->pipe
, 2, r
->vertex_bufs
.all
);
1174 r
->pipe
->bind_vertex_elements_state(r
->pipe
, r
->vertex_elems_state
.individual
.p
);
1175 r
->textures
.individual
.ref
[0] = r
->future
->texture
;
1176 r
->sampler_views
.individual
.ref
[0] = find_or_create_sampler_view(r
, r
->future
);
1177 r
->pipe
->set_fragment_sampler_views(r
->pipe
, 4, r
->sampler_views
.all
);
1178 r
->pipe
->bind_fragment_sampler_states(r
->pipe
, 4, r
->samplers
.all
);
1179 r
->pipe
->bind_vs_state(r
->pipe
, r
->p_vs
[1]);
1180 r
->pipe
->bind_fs_state(r
->pipe
, r
->p_fs
[1]);
1182 util_draw_arrays(r
->pipe
, PIPE_PRIM_TRIANGLES
, vb_start
,
1183 num_macroblocks
[MACROBLOCK_TYPE_BKWD_FIELD_PRED
] * 24);
1184 vb_start
+= num_macroblocks
[MACROBLOCK_TYPE_BKWD_FIELD_PRED
] * 24;
1187 if (num_macroblocks
[MACROBLOCK_TYPE_BI_FRAME_PRED
] > 0) {
1188 r
->pipe
->set_vertex_buffers(r
->pipe
, 3, r
->vertex_bufs
.all
);
1189 r
->pipe
->bind_vertex_elements_state(r
->pipe
, r
->vertex_elems_state
.individual
.b
);
1190 r
->textures
.individual
.ref
[0] = r
->past
->texture
;
1191 r
->textures
.individual
.ref
[1] = r
->future
->texture
;
1192 r
->sampler_views
.individual
.ref
[0] = find_or_create_sampler_view(r
, r
->past
);
1193 r
->sampler_views
.individual
.ref
[1] = find_or_create_sampler_view(r
, r
->future
);
1194 r
->pipe
->set_fragment_sampler_views(r
->pipe
, 5, r
->sampler_views
.all
);
1195 r
->pipe
->bind_fragment_sampler_states(r
->pipe
, 5, r
->samplers
.all
);
1196 r
->pipe
->bind_vs_state(r
->pipe
, r
->b_vs
[0]);
1197 r
->pipe
->bind_fs_state(r
->pipe
, r
->b_fs
[0]);
1199 util_draw_arrays(r
->pipe
, PIPE_PRIM_TRIANGLES
, vb_start
,
1200 num_macroblocks
[MACROBLOCK_TYPE_BI_FRAME_PRED
] * 24);
1201 vb_start
+= num_macroblocks
[MACROBLOCK_TYPE_BI_FRAME_PRED
] * 24;
1204 if (num_macroblocks
[MACROBLOCK_TYPE_BI_FIELD_PRED
] > 0) {
1205 r
->pipe
->set_vertex_buffers(r
->pipe
, 3, r
->vertex_bufs
.all
);
1206 r
->pipe
->bind_vertex_elements_state(r
->pipe
, r
->vertex_elems_state
.individual
.b
);
1207 r
->textures
.individual
.ref
[0] = r
->past
->texture
;
1208 r
->textures
.individual
.ref
[1] = r
->future
->texture
;
1209 r
->sampler_views
.individual
.ref
[0] = find_or_create_sampler_view(r
, r
->past
);
1210 r
->sampler_views
.individual
.ref
[1] = find_or_create_sampler_view(r
, r
->future
);
1211 r
->pipe
->set_fragment_sampler_views(r
->pipe
, 5, r
->sampler_views
.all
);
1212 r
->pipe
->bind_fragment_sampler_states(r
->pipe
, 5, r
->samplers
.all
);
1213 r
->pipe
->bind_vs_state(r
->pipe
, r
->b_vs
[1]);
1214 r
->pipe
->bind_fs_state(r
->pipe
, r
->b_fs
[1]);
1216 util_draw_arrays(r
->pipe
, PIPE_PRIM_TRIANGLES
, vb_start
,
1217 num_macroblocks
[MACROBLOCK_TYPE_BI_FIELD_PRED
] * 24);
1218 vb_start
+= num_macroblocks
[MACROBLOCK_TYPE_BI_FIELD_PRED
] * 24;
1221 r
->pipe
->flush(r
->pipe
, PIPE_FLUSH_RENDER_CACHE
, r
->fence
);
1223 if (r
->eb_handling
== VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_ONE
)
1224 for (i
= 0; i
< 3; ++i
)
1225 r
->zero_block
[i
].x
= ZERO_BLOCK_NIL
;
1227 r
->num_macroblocks
= 0;
1231 grab_frame_coded_block(short *src
, short *dst
, unsigned dst_pitch
)
1238 for (y
= 0; y
< BLOCK_HEIGHT
; ++y
)
1239 memcpy(dst
+ y
* dst_pitch
, src
+ y
* BLOCK_WIDTH
, BLOCK_WIDTH
* 2);
1243 grab_field_coded_block(short *src
, short *dst
, unsigned dst_pitch
)
1250 for (y
= 0; y
< BLOCK_HEIGHT
; ++y
)
1251 memcpy(dst
+ y
* dst_pitch
* 2, src
+ y
* BLOCK_WIDTH
, BLOCK_WIDTH
* 2);
1255 fill_frame_zero_block(short *dst
, unsigned dst_pitch
)
1261 for (y
= 0; y
< BLOCK_HEIGHT
; ++y
)
1262 memset(dst
+ y
* dst_pitch
, 0, BLOCK_WIDTH
* 2);
1266 fill_field_zero_block(short *dst
, unsigned dst_pitch
)
1272 for (y
= 0; y
< BLOCK_HEIGHT
; ++y
)
1273 memset(dst
+ y
* dst_pitch
* 2, 0, BLOCK_WIDTH
* 2);
1277 grab_blocks(struct vl_mpeg12_mc_renderer
*r
, unsigned mbx
, unsigned mby
,
1278 enum pipe_mpeg12_dct_type dct_type
, unsigned cbp
, short *blocks
)
1282 unsigned tb
= 0, sb
= 0;
1283 unsigned mbpx
= mbx
* MACROBLOCK_WIDTH
, mbpy
= mby
* MACROBLOCK_HEIGHT
;
1289 tex_pitch
= r
->tex_transfer
[0]->stride
/ util_format_get_blocksize(r
->tex_transfer
[0]->resource
->format
);
1290 texels
= r
->texels
[0] + mbpy
* tex_pitch
+ mbpx
;
1292 for (y
= 0; y
< 2; ++y
) {
1293 for (x
= 0; x
< 2; ++x
, ++tb
) {
1294 if ((cbp
>> (5 - tb
)) & 1) {
1295 if (dct_type
== PIPE_MPEG12_DCT_TYPE_FRAME
) {
1296 grab_frame_coded_block(blocks
+ sb
* BLOCK_WIDTH
* BLOCK_HEIGHT
,
1297 texels
+ y
* tex_pitch
* BLOCK_HEIGHT
+
1298 x
* BLOCK_WIDTH
, tex_pitch
);
1301 grab_field_coded_block(blocks
+ sb
* BLOCK_WIDTH
* BLOCK_HEIGHT
,
1302 texels
+ y
* tex_pitch
+ x
* BLOCK_WIDTH
,
1308 else if (r
->eb_handling
!= VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_NONE
) {
1309 if(dct_type
== PIPE_MPEG12_DCT_TYPE_FRAME
) {
1311 if (r
->eb_handling
== VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_ALL
||
1312 ZERO_BLOCK_IS_NIL(r
->zero_block
[0])) {
1314 fill_frame_zero_block(texels
+ y
* tex_pitch
* BLOCK_WIDTH
+ x
* BLOCK_WIDTH
, tex_pitch
);
1315 if (r
->eb_handling
== VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_ONE
) {
1316 r
->zero_block
[0].x
= (mbx
+ x
* 0.5f
);
1317 r
->zero_block
[0].y
= (mby
+ y
* 0.5f
);
1323 fill_field_zero_block(texels
+ y
* tex_pitch
+ x
* BLOCK_WIDTH
, tex_pitch
);
1329 /* TODO: Implement 422, 444 */
1330 assert(r
->chroma_format
== PIPE_VIDEO_CHROMA_FORMAT_420
);
1335 for (tb
= 0; tb
< 2; ++tb
) {
1336 tex_pitch
= r
->tex_transfer
[tb
+ 1]->stride
/ util_format_get_blocksize(r
->tex_transfer
[tb
+ 1]->resource
->format
);
1337 texels
= r
->texels
[tb
+ 1] + mbpy
* tex_pitch
+ mbpx
;
1339 if ((cbp
>> (1 - tb
)) & 1) {
1340 grab_frame_coded_block(blocks
+ sb
* BLOCK_WIDTH
* BLOCK_HEIGHT
, texels
, tex_pitch
);
1343 else if (r
->eb_handling
!= VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_NONE
) {
1344 if (r
->eb_handling
== VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_ALL
||
1345 ZERO_BLOCK_IS_NIL(r
->zero_block
[tb
+ 1])) {
1346 fill_frame_zero_block(texels
, tex_pitch
);
1347 if (r
->eb_handling
== VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_ONE
) {
1348 r
->zero_block
[tb
+ 1].x
= mbx
;
1349 r
->zero_block
[tb
+ 1].y
= mby
;
1357 grab_macroblock(struct vl_mpeg12_mc_renderer
*r
,
1358 struct pipe_mpeg12_macroblock
*mb
)
1363 assert(r
->num_macroblocks
< r
->macroblocks_per_batch
);
1365 memcpy(&r
->macroblock_buf
[r
->num_macroblocks
], mb
,
1366 sizeof(struct pipe_mpeg12_macroblock
));
1368 grab_blocks(r
, mb
->mbx
, mb
->mby
, mb
->dct_type
, mb
->cbp
, mb
->blocks
);
1370 ++r
->num_macroblocks
;
1374 texview_map_delete(const struct keymap
*map
,
1375 const void *key
, void *data
,
1378 struct pipe_sampler_view
*sv
= (struct pipe_sampler_view
*)data
;
1385 pipe_sampler_view_reference(&sv
, NULL
);
1389 vl_mpeg12_mc_renderer_init(struct vl_mpeg12_mc_renderer
*renderer
,
1390 struct pipe_context
*pipe
,
1391 unsigned picture_width
,
1392 unsigned picture_height
,
1393 enum pipe_video_chroma_format chroma_format
,
1394 enum VL_MPEG12_MC_RENDERER_BUFFER_MODE bufmode
,
1395 enum VL_MPEG12_MC_RENDERER_EMPTY_BLOCK eb_handling
,
1402 /* TODO: Implement other policies */
1403 assert(bufmode
== VL_MPEG12_MC_RENDERER_BUFFER_PICTURE
);
1404 /* TODO: Implement this */
1405 /* XXX: XFER_ALL sampling issue at block edges when using bilinear filtering */
1406 assert(eb_handling
!= VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_NONE
);
1407 /* TODO: Non-pot buffers untested, probably doesn't work without changes to texcoord generation, vert shader, etc */
1408 assert(pot_buffers
);
1410 memset(renderer
, 0, sizeof(struct vl_mpeg12_mc_renderer
));
1412 renderer
->pipe
= pipe
;
1413 renderer
->picture_width
= picture_width
;
1414 renderer
->picture_height
= picture_height
;
1415 renderer
->chroma_format
= chroma_format
;
1416 renderer
->bufmode
= bufmode
;
1417 renderer
->eb_handling
= eb_handling
;
1418 renderer
->pot_buffers
= pot_buffers
;
1420 renderer
->texview_map
= util_new_keymap(sizeof(struct pipe_surface
*), -1,
1421 texview_map_delete
);
1422 if (!renderer
->texview_map
)
1425 if (!init_pipe_state(renderer
)) {
1426 util_delete_keymap(renderer
->texview_map
, renderer
->pipe
);
1429 if (!init_shaders(renderer
)) {
1430 util_delete_keymap(renderer
->texview_map
, renderer
->pipe
);
1431 cleanup_pipe_state(renderer
);
1434 if (!init_buffers(renderer
)) {
1435 util_delete_keymap(renderer
->texview_map
, renderer
->pipe
);
1436 cleanup_shaders(renderer
);
1437 cleanup_pipe_state(renderer
);
1441 renderer
->surface
= NULL
;
1442 renderer
->past
= NULL
;
1443 renderer
->future
= NULL
;
1444 for (i
= 0; i
< 3; ++i
)
1445 renderer
->zero_block
[i
].x
= ZERO_BLOCK_NIL
;
1446 renderer
->num_macroblocks
= 0;
1448 xfer_buffers_map(renderer
);
1454 vl_mpeg12_mc_renderer_cleanup(struct vl_mpeg12_mc_renderer
*renderer
)
1458 xfer_buffers_unmap(renderer
);
1460 util_delete_keymap(renderer
->texview_map
, renderer
->pipe
);
1461 cleanup_pipe_state(renderer
);
1462 cleanup_shaders(renderer
);
1463 cleanup_buffers(renderer
);
1465 pipe_surface_reference(&renderer
->surface
, NULL
);
1466 pipe_surface_reference(&renderer
->past
, NULL
);
1467 pipe_surface_reference(&renderer
->future
, NULL
);
1471 vl_mpeg12_mc_renderer_render_macroblocks(struct vl_mpeg12_mc_renderer
1473 struct pipe_surface
*surface
,
1474 struct pipe_surface
*past
,
1475 struct pipe_surface
*future
,
1476 unsigned num_macroblocks
,
1477 struct pipe_mpeg12_macroblock
1478 *mpeg12_macroblocks
,
1479 struct pipe_fence_handle
**fence
)
1481 bool new_surface
= false;
1485 assert(num_macroblocks
);
1486 assert(mpeg12_macroblocks
);
1488 if (renderer
->surface
) {
1489 if (surface
!= renderer
->surface
) {
1490 if (renderer
->num_macroblocks
> 0) {
1491 xfer_buffers_unmap(renderer
);
1498 /* If the surface we're rendering hasn't changed the ref frames shouldn't change. */
1499 assert(surface
!= renderer
->surface
|| renderer
->past
== past
);
1500 assert(surface
!= renderer
->surface
|| renderer
->future
== future
);
1506 pipe_surface_reference(&renderer
->surface
, surface
);
1507 pipe_surface_reference(&renderer
->past
, past
);
1508 pipe_surface_reference(&renderer
->future
, future
);
1509 renderer
->fence
= fence
;
1512 while (num_macroblocks
) {
1513 unsigned left_in_batch
= renderer
->macroblocks_per_batch
- renderer
->num_macroblocks
;
1514 unsigned num_to_submit
= MIN2(num_macroblocks
, left_in_batch
);
1517 for (i
= 0; i
< num_to_submit
; ++i
) {
1518 assert(mpeg12_macroblocks
[i
].base
.codec
== PIPE_VIDEO_CODEC_MPEG12
);
1519 grab_macroblock(renderer
, &mpeg12_macroblocks
[i
]);
1522 num_macroblocks
-= num_to_submit
;
1524 if (renderer
->num_macroblocks
== renderer
->macroblocks_per_batch
) {
1525 xfer_buffers_unmap(renderer
);
1527 xfer_buffers_map(renderer
);
1528 /* Next time we get this surface it may have new ref frames */
1529 pipe_surface_reference(&renderer
->surface
, NULL
);
1530 pipe_surface_reference(&renderer
->past
, NULL
);
1531 pipe_surface_reference(&renderer
->future
, NULL
);