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 SCALE_FACTOR_16_TO_9 (32768.0f / 256.0f)
47 struct vertex_shader_consts
52 struct fragment_shader_consts
54 struct vertex4f multiplier
;
108 MACROBLOCK_TYPE_INTRA
,
109 MACROBLOCK_TYPE_FWD_FRAME_PRED
,
110 MACROBLOCK_TYPE_FWD_FIELD_PRED
,
111 MACROBLOCK_TYPE_BKWD_FRAME_PRED
,
112 MACROBLOCK_TYPE_BKWD_FIELD_PRED
,
113 MACROBLOCK_TYPE_BI_FRAME_PRED
,
114 MACROBLOCK_TYPE_BI_FIELD_PRED
,
119 /* vertices for four quads covering the blocks */
120 static const struct vertex2f const_quad
[4] = {
121 {0.0f
, 0.0f
}, {1.0f
, 0.0f
}, {1.0f
, 1.0f
}, {0.0f
, 1.0f
}
125 create_vert_shader(struct vl_mpeg12_mc_renderer
*r
, unsigned ref_frames
, unsigned mv_per_frame
)
127 struct ureg_program
*shader
;
128 struct ureg_src norm
, mbs
;
129 struct ureg_src vrect
, vpos
, eb
[2][2], interlaced
, vmv
[4];
130 struct ureg_dst scale
, t_vpos
, t_vtex
;
131 struct ureg_dst o_vpos
, o_line
, o_vtex
[3], o_eb
[2][2], o_interlaced
, o_vmv
[4];
132 unsigned i
, j
, count
, label
;
134 shader
= ureg_create(TGSI_PROCESSOR_VERTEX
);
138 norm
= ureg_DECL_constant(shader
, 0);
139 mbs
= ureg_imm2f(shader
, MACROBLOCK_WIDTH
, MACROBLOCK_HEIGHT
);
141 scale
= ureg_DECL_temporary(shader
);
142 t_vpos
= ureg_DECL_temporary(shader
);
143 t_vtex
= ureg_DECL_temporary(shader
);
145 vrect
= ureg_DECL_vs_input(shader
, VS_I_RECT
);
146 vpos
= ureg_DECL_vs_input(shader
, VS_I_VPOS
);
147 eb
[0][0] = ureg_DECL_vs_input(shader
, VS_I_EB_0_0
);
148 eb
[1][0] = ureg_DECL_vs_input(shader
, VS_I_EB_1_0
);
149 eb
[0][1] = ureg_DECL_vs_input(shader
, VS_I_EB_0_1
);
150 eb
[1][1] = ureg_DECL_vs_input(shader
, VS_I_EB_1_1
);
151 interlaced
= ureg_DECL_vs_input(shader
, VS_I_INTERLACED
);
153 o_vpos
= ureg_DECL_output(shader
, TGSI_SEMANTIC_POSITION
, VS_O_VPOS
);
154 o_line
= ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_LINE
);
155 o_vtex
[0] = ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_TEX0
);
156 o_vtex
[1] = ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_TEX1
);
157 o_vtex
[2] = ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_TEX2
);
158 o_eb
[0][0] = ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_EB_0_0
);
159 o_eb
[0][1] = ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_EB_0_1
);
160 o_eb
[1][0] = ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_EB_1_0
);
161 o_eb
[1][1] = ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_EB_1_1
);
162 o_interlaced
= ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_INTERLACED
);
165 for (i
= 0; i
< ref_frames
; ++i
) {
166 for (j
= 0; j
< 2; ++j
) {
167 if(j
< mv_per_frame
) {
168 vmv
[count
] = ureg_DECL_vs_input(shader
, VS_I_MV0
+ i
* 2 + j
);
169 o_vmv
[count
] = ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_MV0
+ count
);
172 /* workaround for r600g */
173 else if(ref_frames
== 2)
174 ureg_DECL_vs_input(shader
, VS_I_MV0
+ i
* 2 + j
);
179 * scale = norm * mbs;
181 * t_vpos = (vpos + vrect) * scale
189 * t_vtex.y = vrect.y * 0.5
192 * o_vtex[0].xy = t_vtex * scale
195 * o_vtex[1].xy = t_vtex * scale
197 * o_vtex[0..1].xy = t_vpos
199 * o_vtex[2].xy = t_vpos
201 * if(count > 0) { // Apply motion vectors
202 * scale = norm * 0.5;
203 * o_vmv[0..count] = t_vpos + vmv[0..4] * scale
207 ureg_MUL(shader
, ureg_writemask(scale
, TGSI_WRITEMASK_XY
), norm
, mbs
);
209 ureg_ADD(shader
, ureg_writemask(t_vpos
, TGSI_WRITEMASK_XY
), vpos
, vrect
);
210 ureg_MUL(shader
, ureg_writemask(t_vpos
, TGSI_WRITEMASK_XY
), ureg_src(t_vpos
), ureg_src(scale
));
211 ureg_MOV(shader
, ureg_writemask(o_vpos
, TGSI_WRITEMASK_XY
), ureg_src(t_vpos
));
212 ureg_MOV(shader
, ureg_writemask(o_vpos
, TGSI_WRITEMASK_ZW
), vpos
);
214 ureg_MUL(shader
, ureg_writemask(o_line
, TGSI_WRITEMASK_XY
), vrect
,
215 ureg_imm2f(shader
, MACROBLOCK_WIDTH
/ 2, MACROBLOCK_HEIGHT
/ 2));
217 ureg_IF(shader
, interlaced
, &label
);
219 ureg_MOV(shader
, ureg_writemask(t_vtex
, TGSI_WRITEMASK_X
), vrect
);
220 ureg_MUL(shader
, ureg_writemask(t_vtex
, TGSI_WRITEMASK_Y
), vrect
, ureg_imm1f(shader
, 0.5f
));
221 ureg_ADD(shader
, ureg_writemask(t_vtex
, TGSI_WRITEMASK_XY
), vpos
, ureg_src(t_vtex
));
222 ureg_MUL(shader
, ureg_writemask(o_vtex
[0], TGSI_WRITEMASK_XY
), ureg_src(t_vtex
), ureg_src(scale
));
223 ureg_ADD(shader
, ureg_writemask(t_vtex
, TGSI_WRITEMASK_Y
), ureg_src(t_vtex
), ureg_imm1f(shader
, 0.5f
));
224 ureg_MUL(shader
, ureg_writemask(o_vtex
[1], TGSI_WRITEMASK_XY
), ureg_src(t_vtex
), ureg_src(scale
));
226 ureg_ELSE(shader
, &label
);
228 ureg_MOV(shader
, ureg_writemask(o_vtex
[0], TGSI_WRITEMASK_XY
), ureg_src(t_vpos
));
229 ureg_MOV(shader
, ureg_writemask(o_vtex
[1], TGSI_WRITEMASK_XY
), ureg_src(t_vpos
));
232 ureg_MOV(shader
, ureg_writemask(o_vtex
[2], TGSI_WRITEMASK_XY
), ureg_src(t_vpos
));
234 ureg_MOV(shader
, o_eb
[0][0], eb
[0][0]);
235 ureg_MOV(shader
, o_eb
[0][1], eb
[0][1]);
236 ureg_MOV(shader
, o_eb
[1][0], eb
[1][0]);
237 ureg_MOV(shader
, o_eb
[1][1], eb
[1][1]);
239 ureg_MOV(shader
, o_interlaced
, interlaced
);
242 ureg_MUL(shader
, ureg_writemask(scale
, TGSI_WRITEMASK_XY
), norm
, ureg_imm1f(shader
, 0.5f
));
243 for (i
= 0; i
< count
; ++i
)
244 ureg_MAD(shader
, ureg_writemask(o_vmv
[i
], TGSI_WRITEMASK_XY
), ureg_src(scale
), vmv
[i
], ureg_src(t_vpos
));
247 ureg_release_temporary(shader
, t_vtex
);
248 ureg_release_temporary(shader
, t_vpos
);
249 ureg_release_temporary(shader
, scale
);
253 return ureg_create_shader_and_destroy(shader
, r
->pipe
);
256 static struct ureg_dst
257 calc_field(struct ureg_program
*shader
)
260 struct ureg_src line
;
262 tmp
= ureg_DECL_temporary(shader
);
263 line
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_LINE
, TGSI_INTERPOLATE_LINEAR
);
266 * line going from 0 to 8 in steps of 0.5
268 * tmp.z = fraction(line.y)
269 * tmp.z = tmp.z >= 0.5 ? 1 : 0
270 * tmp.xy = line > 4 ? 1 : 0
272 ureg_FRC(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_Z
), ureg_scalar(line
, TGSI_SWIZZLE_Y
));
273 ureg_SGE(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_Z
), ureg_src(tmp
), ureg_imm1f(shader
, 0.5f
));
274 ureg_SGE(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_XY
), line
, ureg_imm2f(shader
, BLOCK_WIDTH
/ 2, BLOCK_HEIGHT
/ 2));
279 static struct ureg_dst
280 fetch_ycbcr(struct vl_mpeg12_mc_renderer
*r
, struct ureg_program
*shader
, struct ureg_dst field
)
282 struct ureg_src tc
[3], eb
[2][2], interlaced
;
283 struct ureg_src sampler
[3];
284 struct ureg_dst texel
, t_tc
, t_field
, tmp
;
285 unsigned i
, l_interlaced
, l_y
, l_x
;
287 texel
= ureg_DECL_temporary(shader
);
288 t_tc
= ureg_DECL_temporary(shader
);
289 t_field
= ureg_DECL_temporary(shader
);
290 tmp
= ureg_DECL_temporary(shader
);
292 tc
[0] = ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_TEX0
, TGSI_INTERPOLATE_LINEAR
);
293 tc
[1] = ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_TEX1
, TGSI_INTERPOLATE_LINEAR
);
294 tc
[2] = ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_TEX2
, TGSI_INTERPOLATE_LINEAR
);
296 eb
[0][0] = ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_EB_0_0
, TGSI_INTERPOLATE_CONSTANT
);
297 eb
[0][1] = ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_EB_0_1
, TGSI_INTERPOLATE_CONSTANT
);
298 eb
[1][0] = ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_EB_1_0
, TGSI_INTERPOLATE_CONSTANT
);
299 eb
[1][1] = ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_EB_1_1
, TGSI_INTERPOLATE_CONSTANT
);
301 interlaced
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_INTERLACED
, TGSI_INTERPOLATE_CONSTANT
);
303 for (i
= 0; i
< 3; ++i
) {
304 sampler
[i
] = ureg_DECL_sampler(shader
, i
);
308 * texel.y = tex(field ? tc[1] : tc[0], sampler[0])
309 * texel.cb = tex(tc[2], sampler[1])
310 * texel.cr = tex(tc[2], sampler[2])
312 ureg_MOV(shader
, ureg_writemask(t_field
, TGSI_WRITEMASK_XY
), ureg_src(field
));
313 ureg_IF(shader
, interlaced
, &l_interlaced
);
314 ureg_MOV(shader
, ureg_writemask(t_field
, TGSI_WRITEMASK_Y
), ureg_scalar(ureg_src(field
), TGSI_SWIZZLE_Z
));
317 for (i
= 0; i
< 3; ++i
) {
318 if(i
==0 || r
->chroma_format
== PIPE_VIDEO_CHROMA_FORMAT_444
) {
319 ureg_IF(shader
, ureg_scalar(ureg_src(t_field
), TGSI_SWIZZLE_Y
), &l_y
);
320 ureg_MOV(shader
, ureg_writemask(t_tc
, TGSI_WRITEMASK_XY
), tc
[1]);
322 ureg_IF(shader
, ureg_scalar(ureg_src(t_field
), TGSI_SWIZZLE_X
), &l_x
);
323 ureg_MOV(shader
, ureg_writemask(t_tc
, TGSI_WRITEMASK_Z
), ureg_scalar(eb
[1][1], TGSI_SWIZZLE_X
+ i
));
324 ureg_ELSE(shader
, &l_x
);
325 ureg_MOV(shader
, ureg_writemask(t_tc
, TGSI_WRITEMASK_Z
), ureg_scalar(eb
[1][0], TGSI_SWIZZLE_X
+ i
));
328 ureg_ELSE(shader
, &l_y
);
329 ureg_MOV(shader
, ureg_writemask(t_tc
, TGSI_WRITEMASK_XY
), tc
[0]);
331 ureg_IF(shader
, ureg_scalar(ureg_src(t_field
), TGSI_SWIZZLE_X
), &l_x
);
332 ureg_MOV(shader
, ureg_writemask(t_tc
, TGSI_WRITEMASK_Z
), ureg_scalar(eb
[0][1], TGSI_SWIZZLE_X
+ i
));
333 ureg_ELSE(shader
, &l_x
);
334 ureg_MOV(shader
, ureg_writemask(t_tc
, TGSI_WRITEMASK_Z
), ureg_scalar(eb
[0][0], TGSI_SWIZZLE_X
+ i
));
340 ureg_MOV(shader
, ureg_writemask(t_tc
, TGSI_WRITEMASK_XY
), tc
[2]);
341 ureg_MOV(shader
, ureg_writemask(t_tc
, TGSI_WRITEMASK_Z
), ureg_scalar(eb
[0][0], TGSI_SWIZZLE_X
+ i
));
344 /* Nouveau can't writemask tex dst regs (yet?), do in two steps */
345 ureg_TEX(shader
, tmp
, TGSI_TEXTURE_3D
, ureg_src(t_tc
), sampler
[i
]);
346 ureg_MOV(shader
, ureg_writemask(texel
, TGSI_WRITEMASK_X
<< i
), ureg_scalar(ureg_src(tmp
), TGSI_SWIZZLE_X
));
349 ureg_release_temporary(shader
, t_field
);
350 ureg_release_temporary(shader
, t_tc
);
351 ureg_release_temporary(shader
, tmp
);
357 create_intra_frag_shader(struct vl_mpeg12_mc_renderer
*r
)
359 struct ureg_program
*shader
;
360 struct ureg_dst field
, texel
;
361 struct ureg_dst fragment
;
363 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
367 fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
370 * texel = fetch_ycbcr()
371 * fragment = texel * scale
373 field
= calc_field(shader
);
374 texel
= fetch_ycbcr(r
, shader
, field
);
375 ureg_MUL(shader
, fragment
, ureg_src(texel
), ureg_scalar(ureg_imm1f(shader
, SCALE_FACTOR_16_TO_9
), TGSI_SWIZZLE_X
));
377 ureg_release_temporary(shader
, field
);
378 ureg_release_temporary(shader
, texel
);
381 return ureg_create_shader_and_destroy(shader
, r
->pipe
);
385 create_frame_pred_frag_shader(struct vl_mpeg12_mc_renderer
*r
)
387 struct ureg_program
*shader
;
389 struct ureg_src sampler
;
390 struct ureg_dst field
, texel
, ref
;
391 struct ureg_dst fragment
;
393 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
397 tc
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_MV0
, TGSI_INTERPOLATE_LINEAR
);
398 sampler
= ureg_DECL_sampler(shader
, 3);
400 ref
= ureg_DECL_temporary(shader
);
401 fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
404 * texel = fetch_ycbcr()
405 * ref = tex(tc, sampler)
406 * fragment = texel * scale + ref
408 field
= calc_field(shader
);
409 texel
= fetch_ycbcr(r
, shader
, field
);
410 ureg_TEX(shader
, ref
, TGSI_TEXTURE_2D
, tc
, sampler
);
411 ureg_MAD(shader
, fragment
, ureg_src(texel
), ureg_scalar(ureg_imm1f(shader
, SCALE_FACTOR_16_TO_9
), TGSI_SWIZZLE_X
), ureg_src(ref
));
413 ureg_release_temporary(shader
, field
);
414 ureg_release_temporary(shader
, texel
);
415 ureg_release_temporary(shader
, ref
);
418 return ureg_create_shader_and_destroy(shader
, r
->pipe
);
422 create_field_pred_frag_shader(struct vl_mpeg12_mc_renderer
*r
)
424 struct ureg_program
*shader
;
425 struct ureg_src tc
[2];
426 struct ureg_src sampler
;
427 struct ureg_dst texel
, ref
, field
;
428 struct ureg_dst fragment
;
431 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
435 for (i
= 0; i
< 2; ++i
)
436 tc
[i
] = ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_MV0
+ i
, TGSI_INTERPOLATE_LINEAR
);
437 sampler
= ureg_DECL_sampler(shader
, 3);
439 ref
= ureg_DECL_temporary(shader
);
440 fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
443 * texel = fetch_ycbcr()
444 * field = calc_field();
446 * ref = tex(tc[1], sampler)
448 * ref = tex(tc[0], sampler)
449 * fragment = texel * scale + ref
451 field
= calc_field(shader
);
452 texel
= fetch_ycbcr(r
, shader
, field
);
454 ureg_IF(shader
, ureg_scalar(ureg_src(field
), TGSI_SWIZZLE_Z
), &label
);
455 ureg_TEX(shader
, ref
, TGSI_TEXTURE_2D
, tc
[1], sampler
);
456 ureg_ELSE(shader
, &label
);
457 ureg_TEX(shader
, ref
, TGSI_TEXTURE_2D
, tc
[0], sampler
);
460 ureg_MAD(shader
, fragment
, ureg_src(texel
), ureg_scalar(ureg_imm1f(shader
, SCALE_FACTOR_16_TO_9
), TGSI_SWIZZLE_X
), ureg_src(ref
));
462 ureg_release_temporary(shader
, field
);
463 ureg_release_temporary(shader
, texel
);
464 ureg_release_temporary(shader
, ref
);
467 return ureg_create_shader_and_destroy(shader
, r
->pipe
);
471 create_frame_bi_pred_frag_shader(struct vl_mpeg12_mc_renderer
*r
)
473 struct ureg_program
*shader
;
474 struct ureg_src tc
[2];
475 struct ureg_src sampler
[2];
476 struct ureg_dst field
, texel
, ref
[2];
477 struct ureg_dst fragment
;
480 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
484 for (i
= 0; i
< 2; ++i
) {
485 tc
[i
] = ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_MV0
+ i
, TGSI_INTERPOLATE_LINEAR
);
486 sampler
[i
] = ureg_DECL_sampler(shader
, i
+ 3);
489 ref
[0] = ureg_DECL_temporary(shader
);
490 ref
[1] = ureg_DECL_temporary(shader
);
491 fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
494 * texel = fetch_ycbcr()
495 * ref[0..1 = tex(tc[3..4], sampler[3..4])
496 * ref[0] = lerp(ref[0], ref[1], 0.5)
497 * fragment = texel * scale + ref[0]
499 field
= calc_field(shader
);
500 texel
= fetch_ycbcr(r
, shader
, field
);
501 ureg_TEX(shader
, ref
[0], TGSI_TEXTURE_2D
, tc
[0], sampler
[0]);
502 ureg_TEX(shader
, ref
[1], TGSI_TEXTURE_2D
, tc
[1], sampler
[1]);
503 ureg_LRP(shader
, ref
[0], ureg_scalar(ureg_imm1f(shader
, 0.5f
), TGSI_SWIZZLE_X
), ureg_src(ref
[0]), ureg_src(ref
[1]));
505 ureg_MAD(shader
, fragment
, ureg_src(texel
), ureg_scalar(ureg_imm1f(shader
, SCALE_FACTOR_16_TO_9
), TGSI_SWIZZLE_X
), ureg_src(ref
[0]));
507 ureg_release_temporary(shader
, field
);
508 ureg_release_temporary(shader
, texel
);
509 ureg_release_temporary(shader
, ref
[0]);
510 ureg_release_temporary(shader
, ref
[1]);
513 return ureg_create_shader_and_destroy(shader
, r
->pipe
);
517 create_field_bi_pred_frag_shader(struct vl_mpeg12_mc_renderer
*r
)
519 struct ureg_program
*shader
;
520 struct ureg_src tc
[4];
521 struct ureg_src sampler
[2];
522 struct ureg_dst texel
, ref
[2], field
;
523 struct ureg_dst fragment
;
526 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
530 for (i
= 0; i
< 4; ++i
)
531 tc
[i
] = ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_MV0
+ i
, TGSI_INTERPOLATE_LINEAR
);
532 for (i
= 0; i
< 2; ++i
)
533 sampler
[i
] = ureg_DECL_sampler(shader
, i
+ 3);
535 texel
= ureg_DECL_temporary(shader
);
536 ref
[0] = ureg_DECL_temporary(shader
);
537 ref
[1] = ureg_DECL_temporary(shader
);
538 fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
541 * texel = fetch_ycbcr()
543 * ref[0..1] = tex(tc[1|3], sampler[0..1])
545 * ref[0..1] = tex(tc[0|2], sampler[0..1])
546 * ref[0] = lerp(ref[0], ref[1], 0.5)
547 * fragment = texel * scale + ref[0]
549 field
= calc_field(shader
);
550 texel
= fetch_ycbcr(r
, shader
, field
);
552 ureg_IF(shader
, ureg_scalar(ureg_src(field
), TGSI_SWIZZLE_Z
), &label
);
553 ureg_TEX(shader
, ref
[0], TGSI_TEXTURE_2D
, tc
[1], sampler
[0]);
554 ureg_TEX(shader
, ref
[1], TGSI_TEXTURE_2D
, tc
[3], sampler
[1]);
555 ureg_ELSE(shader
, &label
);
556 ureg_TEX(shader
, ref
[0], TGSI_TEXTURE_2D
, tc
[0], sampler
[0]);
557 ureg_TEX(shader
, ref
[1], TGSI_TEXTURE_2D
, tc
[2], sampler
[1]);
560 ureg_LRP(shader
, ref
[0], ureg_scalar(ureg_imm1f(shader
, 0.5f
), TGSI_SWIZZLE_X
), ureg_src(ref
[0]), ureg_src(ref
[1]));
562 ureg_MAD(shader
, fragment
, ureg_src(texel
), ureg_scalar(ureg_imm1f(shader
, SCALE_FACTOR_16_TO_9
), TGSI_SWIZZLE_X
), ureg_src(ref
[0]));
564 ureg_release_temporary(shader
, field
);
565 ureg_release_temporary(shader
, texel
);
566 ureg_release_temporary(shader
, ref
[0]);
567 ureg_release_temporary(shader
, ref
[1]);
570 return ureg_create_shader_and_destroy(shader
, r
->pipe
);
574 xfer_buffers_map(struct vl_mpeg12_mc_renderer
*r
)
580 for (i
= 0; i
< 3; ++i
) {
581 struct pipe_box rect
=
584 r
->textures
.all
[i
]->width0
,
585 r
->textures
.all
[i
]->height0
,
589 r
->tex_transfer
[i
] = r
->pipe
->get_transfer
591 r
->pipe
, r
->textures
.all
[i
],
593 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD
,
597 r
->texels
[i
] = r
->pipe
->transfer_map(r
->pipe
, r
->tex_transfer
[i
]);
602 xfer_buffers_unmap(struct vl_mpeg12_mc_renderer
*r
)
608 for (i
= 0; i
< 3; ++i
) {
609 r
->pipe
->transfer_unmap(r
->pipe
, r
->tex_transfer
[i
]);
610 r
->pipe
->transfer_destroy(r
->pipe
, r
->tex_transfer
[i
]);
615 init_pipe_state(struct vl_mpeg12_mc_renderer
*r
)
617 struct pipe_sampler_state sampler
;
623 r
->viewport
.scale
[0] = r
->pot_buffers
?
624 util_next_power_of_two(r
->picture_width
) : r
->picture_width
;
625 r
->viewport
.scale
[1] = r
->pot_buffers
?
626 util_next_power_of_two(r
->picture_height
) : r
->picture_height
;
627 r
->viewport
.scale
[2] = 1;
628 r
->viewport
.scale
[3] = 1;
629 r
->viewport
.translate
[0] = 0;
630 r
->viewport
.translate
[1] = 0;
631 r
->viewport
.translate
[2] = 0;
632 r
->viewport
.translate
[3] = 0;
634 r
->fb_state
.width
= r
->pot_buffers
?
635 util_next_power_of_two(r
->picture_width
) : r
->picture_width
;
636 r
->fb_state
.height
= r
->pot_buffers
?
637 util_next_power_of_two(r
->picture_height
) : r
->picture_height
;
638 r
->fb_state
.nr_cbufs
= 1;
639 r
->fb_state
.zsbuf
= NULL
;
642 filters
[0] = PIPE_TEX_FILTER_NEAREST
;
644 if (r
->chroma_format
== PIPE_VIDEO_CHROMA_FORMAT_444
|| true) { //TODO
645 filters
[1] = PIPE_TEX_FILTER_NEAREST
;
646 filters
[2] = PIPE_TEX_FILTER_NEAREST
;
649 filters
[1] = PIPE_TEX_FILTER_LINEAR
;
650 filters
[2] = PIPE_TEX_FILTER_LINEAR
;
652 /* Fwd, bkwd ref filters */
653 filters
[3] = PIPE_TEX_FILTER_LINEAR
;
654 filters
[4] = PIPE_TEX_FILTER_LINEAR
;
656 for (i
= 0; i
< 5; ++i
) {
657 memset(&sampler
, 0, sizeof(sampler
));
658 sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
659 sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
660 sampler
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_BORDER
;
661 sampler
.min_img_filter
= filters
[i
];
662 sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
663 sampler
.mag_img_filter
= filters
[i
];
664 sampler
.compare_mode
= PIPE_TEX_COMPARE_NONE
;
665 sampler
.compare_func
= PIPE_FUNC_ALWAYS
;
666 sampler
.normalized_coords
= 1;
667 /*sampler.shadow_ambient = ; */
668 /*sampler.lod_bias = ; */
670 /*sampler.max_lod = ; */
671 sampler
.border_color
[0] = 0.0f
;
672 sampler
.border_color
[1] = 0.0f
;
673 sampler
.border_color
[2] = 0.0f
;
674 sampler
.border_color
[3] = 0.0f
;
675 /*sampler.max_anisotropy = ; */
676 r
->samplers
.all
[i
] = r
->pipe
->create_sampler_state(r
->pipe
, &sampler
);
683 cleanup_pipe_state(struct vl_mpeg12_mc_renderer
*r
)
689 for (i
= 0; i
< 5; ++i
)
690 r
->pipe
->delete_sampler_state(r
->pipe
, r
->samplers
.all
[i
]);
694 init_shaders(struct vl_mpeg12_mc_renderer
*r
)
698 assert(r
->i_vs
= create_vert_shader(r
, 0, 0));
699 assert(r
->i_fs
= create_intra_frag_shader(r
));
701 assert(r
->p_vs
[0] = create_vert_shader(r
, 1, 1));
702 assert(r
->p_vs
[1] = create_vert_shader(r
, 1, 2));
703 assert(r
->p_fs
[0] = create_frame_pred_frag_shader(r
));
704 assert(r
->p_fs
[1] = create_field_pred_frag_shader(r
));
706 assert(r
->b_vs
[0] = create_vert_shader(r
, 2, 1));
707 assert(r
->b_vs
[1] = create_vert_shader(r
, 2, 2));
708 assert(r
->b_fs
[0] = create_frame_bi_pred_frag_shader(r
));
709 assert(r
->b_fs
[1] = create_field_bi_pred_frag_shader(r
));
715 cleanup_shaders(struct vl_mpeg12_mc_renderer
*r
)
719 r
->pipe
->delete_vs_state(r
->pipe
, r
->i_vs
);
720 r
->pipe
->delete_fs_state(r
->pipe
, r
->i_fs
);
721 r
->pipe
->delete_vs_state(r
->pipe
, r
->p_vs
[0]);
722 r
->pipe
->delete_vs_state(r
->pipe
, r
->p_vs
[1]);
723 r
->pipe
->delete_fs_state(r
->pipe
, r
->p_fs
[0]);
724 r
->pipe
->delete_fs_state(r
->pipe
, r
->p_fs
[1]);
725 r
->pipe
->delete_vs_state(r
->pipe
, r
->b_vs
[0]);
726 r
->pipe
->delete_vs_state(r
->pipe
, r
->b_vs
[1]);
727 r
->pipe
->delete_fs_state(r
->pipe
, r
->b_fs
[0]);
728 r
->pipe
->delete_fs_state(r
->pipe
, r
->b_fs
[1]);
732 init_buffers(struct vl_mpeg12_mc_renderer
*r
)
734 struct pipe_resource
template;
735 struct pipe_vertex_element vertex_elems
[NUM_VS_INPUTS
];
736 struct pipe_sampler_view sampler_view
;
739 align(r
->picture_width
, MACROBLOCK_WIDTH
) / MACROBLOCK_WIDTH
;
741 align(r
->picture_height
, MACROBLOCK_HEIGHT
) / MACROBLOCK_HEIGHT
;
747 r
->macroblocks_per_batch
=
748 mbw
* (r
->bufmode
== VL_MPEG12_MC_RENDERER_BUFFER_PICTURE
? mbh
: 1);
749 r
->num_macroblocks
= 0;
750 r
->macroblock_buf
= MALLOC(r
->macroblocks_per_batch
* sizeof(struct pipe_mpeg12_macroblock
));
752 memset(&template, 0, sizeof(struct pipe_resource
));
753 template.target
= PIPE_TEXTURE_3D
;
754 /* TODO: Accomodate HW that can't do this and also for cases when this isn't precise enough */
755 template.format
= PIPE_FORMAT_R16_SNORM
;
756 template.last_level
= 0;
757 template.width0
= r
->pot_buffers
?
758 util_next_power_of_two(r
->picture_width
) : r
->picture_width
;
759 template.height0
= r
->pot_buffers
?
760 util_next_power_of_two(r
->picture_height
) : r
->picture_height
;
762 template.usage
= PIPE_USAGE_DYNAMIC
;
763 template.bind
= PIPE_BIND_SAMPLER_VIEW
;
766 r
->textures
.individual
.y
= r
->pipe
->screen
->resource_create(r
->pipe
->screen
, &template);
768 if (r
->chroma_format
== PIPE_VIDEO_CHROMA_FORMAT_420
) {
769 template.width0
= r
->pot_buffers
?
770 util_next_power_of_two(r
->picture_width
/ 2) :
771 r
->picture_width
/ 2;
772 template.height0
= r
->pot_buffers
?
773 util_next_power_of_two(r
->picture_height
/ 2) :
774 r
->picture_height
/ 2;
776 else if (r
->chroma_format
== PIPE_VIDEO_CHROMA_FORMAT_422
)
777 template.height0
= r
->pot_buffers
?
778 util_next_power_of_two(r
->picture_height
/ 2) :
779 r
->picture_height
/ 2;
781 r
->textures
.individual
.cb
=
782 r
->pipe
->screen
->resource_create(r
->pipe
->screen
, &template);
783 r
->textures
.individual
.cr
=
784 r
->pipe
->screen
->resource_create(r
->pipe
->screen
, &template);
786 for (i
= 0; i
< 3; ++i
) {
787 u_sampler_view_default_template(&sampler_view
,
789 r
->textures
.all
[i
]->format
);
790 r
->sampler_views
.all
[i
] = r
->pipe
->create_sampler_view(r
->pipe
, r
->textures
.all
[i
], &sampler_view
);
793 r
->vertex_bufs
.individual
.rect
.stride
= sizeof(struct vertex2f
);
794 r
->vertex_bufs
.individual
.rect
.max_index
= 4 * r
->macroblocks_per_batch
- 1;
795 r
->vertex_bufs
.individual
.rect
.buffer_offset
= 0;
796 r
->vertex_bufs
.individual
.rect
.buffer
= pipe_buffer_create
799 PIPE_BIND_VERTEX_BUFFER
,
800 sizeof(struct vertex2f
) * 4 * r
->macroblocks_per_batch
803 r
->vertex_bufs
.individual
.ycbcr
.stride
= sizeof(struct vert_stream_0
);
804 r
->vertex_bufs
.individual
.ycbcr
.max_index
= 4 * r
->macroblocks_per_batch
- 1;
805 r
->vertex_bufs
.individual
.ycbcr
.buffer_offset
= 0;
806 /* XXX: Create with usage DYNAMIC or STREAM */
807 r
->vertex_bufs
.individual
.ycbcr
.buffer
= pipe_buffer_create
810 PIPE_BIND_VERTEX_BUFFER
,
811 sizeof(struct vert_stream_0
) * 4 * r
->macroblocks_per_batch
814 for (i
= 0; i
< 2; ++i
) {
815 r
->vertex_bufs
.individual
.ref
[i
].stride
= sizeof(struct vertex2f
) * 2;
816 r
->vertex_bufs
.individual
.ref
[i
].max_index
= 4 * r
->macroblocks_per_batch
- 1;
817 r
->vertex_bufs
.individual
.ref
[i
].buffer_offset
= 0;
818 /* XXX: Create with usage DYNAMIC or STREAM */
819 r
->vertex_bufs
.individual
.ref
[i
].buffer
= pipe_buffer_create
822 PIPE_BIND_VERTEX_BUFFER
,
823 sizeof(struct vertex2f
) * 2 * 4 * r
->macroblocks_per_batch
827 memset(&vertex_elems
, 0, sizeof(vertex_elems
));
829 /* Rectangle element */
830 vertex_elems
[VS_I_RECT
].src_offset
= 0;
831 vertex_elems
[VS_I_RECT
].instance_divisor
= 0;
832 vertex_elems
[VS_I_RECT
].vertex_buffer_index
= 0;
833 vertex_elems
[VS_I_RECT
].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
835 /* Position element */
836 vertex_elems
[VS_I_VPOS
].src_offset
= 0;
837 vertex_elems
[VS_I_VPOS
].instance_divisor
= 0;
838 vertex_elems
[VS_I_VPOS
].vertex_buffer_index
= 1;
839 vertex_elems
[VS_I_VPOS
].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
841 /* y, cr, cb z-coordinate element top left block */
842 vertex_elems
[VS_I_EB_0_0
].src_offset
= sizeof(struct vertex2f
);
843 vertex_elems
[VS_I_EB_0_0
].instance_divisor
= 0;
844 vertex_elems
[VS_I_EB_0_0
].vertex_buffer_index
= 1;
845 vertex_elems
[VS_I_EB_0_0
].src_format
= PIPE_FORMAT_R32G32B32_FLOAT
;
847 /* y, cr, cb z-coordinate element top right block */
848 vertex_elems
[VS_I_EB_0_1
].src_offset
= sizeof(struct vertex2f
) + sizeof(float) * 3;
849 vertex_elems
[VS_I_EB_0_1
].instance_divisor
= 0;
850 vertex_elems
[VS_I_EB_0_1
].vertex_buffer_index
= 1;
851 vertex_elems
[VS_I_EB_0_1
].src_format
= PIPE_FORMAT_R32G32B32_FLOAT
;
853 /* y, cr, cb z-coordinate element bottom left block */
854 vertex_elems
[VS_I_EB_1_0
].src_offset
= sizeof(struct vertex2f
) + sizeof(float) * 6;
855 vertex_elems
[VS_I_EB_1_0
].instance_divisor
= 0;
856 vertex_elems
[VS_I_EB_1_0
].vertex_buffer_index
= 1;
857 vertex_elems
[VS_I_EB_1_0
].src_format
= PIPE_FORMAT_R32G32B32_FLOAT
;
859 /* y, cr, cb z-coordinate element bottom right block */
860 vertex_elems
[VS_I_EB_1_1
].src_offset
= sizeof(struct vertex2f
) + sizeof(float) * 9;
861 vertex_elems
[VS_I_EB_1_1
].instance_divisor
= 0;
862 vertex_elems
[VS_I_EB_1_1
].vertex_buffer_index
= 1;
863 vertex_elems
[VS_I_EB_1_1
].src_format
= PIPE_FORMAT_R32G32B32_FLOAT
;
865 /* progressive=1.0f interlaced=0.0f */
866 vertex_elems
[VS_I_INTERLACED
].src_offset
= sizeof(struct vertex2f
) + sizeof(float) * 12;
867 vertex_elems
[VS_I_INTERLACED
].instance_divisor
= 0;
868 vertex_elems
[VS_I_INTERLACED
].vertex_buffer_index
= 1;
869 vertex_elems
[VS_I_INTERLACED
].src_format
= PIPE_FORMAT_R32_FLOAT
;
871 /* First ref surface top field texcoord element */
872 vertex_elems
[VS_I_MV0
].src_offset
= 0;
873 vertex_elems
[VS_I_MV0
].instance_divisor
= 0;
874 vertex_elems
[VS_I_MV0
].vertex_buffer_index
= 2;
875 vertex_elems
[VS_I_MV0
].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
877 /* First ref surface bottom field texcoord element */
878 vertex_elems
[VS_I_MV1
].src_offset
= sizeof(struct vertex2f
);
879 vertex_elems
[VS_I_MV1
].instance_divisor
= 0;
880 vertex_elems
[VS_I_MV1
].vertex_buffer_index
= 2;
881 vertex_elems
[VS_I_MV1
].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
883 /* Second ref surface top field texcoord element */
884 vertex_elems
[VS_I_MV2
].src_offset
= 0;
885 vertex_elems
[VS_I_MV2
].instance_divisor
= 0;
886 vertex_elems
[VS_I_MV2
].vertex_buffer_index
= 3;
887 vertex_elems
[VS_I_MV2
].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
889 /* Second ref surface bottom field texcoord element */
890 vertex_elems
[VS_I_MV3
].src_offset
= sizeof(struct vertex2f
);
891 vertex_elems
[VS_I_MV3
].instance_divisor
= 0;
892 vertex_elems
[VS_I_MV3
].vertex_buffer_index
= 3;
893 vertex_elems
[VS_I_MV3
].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
895 r
->vertex_elems_state
.individual
.i
= r
->pipe
->create_vertex_elements_state(r
->pipe
, 7, vertex_elems
);
896 r
->vertex_elems_state
.individual
.p
= r
->pipe
->create_vertex_elements_state(r
->pipe
, 9, vertex_elems
);
897 r
->vertex_elems_state
.individual
.b
= r
->pipe
->create_vertex_elements_state(r
->pipe
, 11, vertex_elems
);
899 r
->vs_const_buf
= pipe_buffer_create
902 PIPE_BIND_CONSTANT_BUFFER
,
903 sizeof(struct vertex_shader_consts
)
910 init_const_buffers(struct vl_mpeg12_mc_renderer
*r
)
912 struct pipe_transfer
*buf_transfer
;
913 struct vertex2f
*rect
;
916 rect
= pipe_buffer_map
919 r
->vertex_bufs
.individual
.rect
.buffer
,
920 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD
,
924 for ( i
= 0; i
< r
->macroblocks_per_batch
; ++i
)
925 memcpy(rect
+ i
* 4, &const_quad
, sizeof(const_quad
));
927 pipe_buffer_unmap(r
->pipe
, r
->vertex_bufs
.individual
.rect
.buffer
, buf_transfer
);
933 cleanup_buffers(struct vl_mpeg12_mc_renderer
*r
)
939 pipe_resource_reference(&r
->vs_const_buf
, NULL
);
941 for (i
= 0; i
< 3; ++i
) {
942 pipe_sampler_view_reference(&r
->sampler_views
.all
[i
], NULL
);
943 r
->pipe
->delete_vertex_elements_state(r
->pipe
, r
->vertex_elems_state
.all
[i
]);
944 pipe_resource_reference(&r
->vertex_bufs
.all
[i
].buffer
, NULL
);
945 pipe_resource_reference(&r
->textures
.all
[i
], NULL
);
948 FREE(r
->macroblock_buf
);
951 static enum MACROBLOCK_TYPE
952 get_macroblock_type(struct pipe_mpeg12_macroblock
*mb
)
956 switch (mb
->mb_type
) {
957 case PIPE_MPEG12_MACROBLOCK_TYPE_INTRA
:
958 return MACROBLOCK_TYPE_INTRA
;
959 case PIPE_MPEG12_MACROBLOCK_TYPE_FWD
:
960 return mb
->mo_type
== PIPE_MPEG12_MOTION_TYPE_FRAME
?
961 MACROBLOCK_TYPE_FWD_FRAME_PRED
: MACROBLOCK_TYPE_FWD_FIELD_PRED
;
962 case PIPE_MPEG12_MACROBLOCK_TYPE_BKWD
:
963 return mb
->mo_type
== PIPE_MPEG12_MOTION_TYPE_FRAME
?
964 MACROBLOCK_TYPE_BKWD_FRAME_PRED
: MACROBLOCK_TYPE_BKWD_FIELD_PRED
;
965 case PIPE_MPEG12_MACROBLOCK_TYPE_BI
:
966 return mb
->mo_type
== PIPE_MPEG12_MOTION_TYPE_FRAME
?
967 MACROBLOCK_TYPE_BI_FRAME_PRED
: MACROBLOCK_TYPE_BI_FIELD_PRED
;
977 gen_macroblock_verts(struct vl_mpeg12_mc_renderer
*r
,
978 struct pipe_mpeg12_macroblock
*mb
, unsigned pos
,
979 struct vert_stream_0
*ycbcr_vb
, struct vertex2f
**ref_vb
)
981 struct vertex2f mo_vec
[2];
988 assert(pos
< r
->macroblocks_per_batch
);
993 switch (mb
->mb_type
) {
994 case PIPE_MPEG12_MACROBLOCK_TYPE_BI
:
998 assert(ref_vb
&& ref_vb
[1]);
1000 vb
= ref_vb
[1] + pos
* 2 * 4;
1002 mo_vec
[0].x
= mb
->pmv
[0][1][0];
1003 mo_vec
[0].y
= mb
->pmv
[0][1][1];
1005 if (mb
->mo_type
== PIPE_MPEG12_MOTION_TYPE_FRAME
) {
1006 for (i
= 0; i
< 4 * 2; i
+= 2) {
1007 vb
[i
].x
= mo_vec
[0].x
;
1008 vb
[i
].y
= mo_vec
[0].y
;
1012 mo_vec
[0].y
= mb
->pmv
[0][1][1] - (mb
->pmv
[0][1][1] % 4);
1014 mo_vec
[1].x
= mb
->pmv
[1][1][0];
1015 mo_vec
[1].y
= mb
->pmv
[1][1][1] - (mb
->pmv
[1][1][1] % 4);
1017 if(mb
->mvfs
[0][1]) mo_vec
[0].y
+= 2;
1018 if(!mb
->mvfs
[1][1]) mo_vec
[1].y
-= 2;
1020 for (i
= 0; i
< 4 * 2; i
+= 2) {
1021 vb
[i
].x
= mo_vec
[0].x
;
1022 vb
[i
].y
= mo_vec
[0].y
;
1023 vb
[i
+ 1].x
= mo_vec
[1].x
;
1024 vb
[i
+ 1].y
= mo_vec
[1].y
;
1030 case PIPE_MPEG12_MACROBLOCK_TYPE_FWD
:
1031 case PIPE_MPEG12_MACROBLOCK_TYPE_BKWD
:
1033 struct vertex2f
*vb
;
1035 assert(ref_vb
&& ref_vb
[0]);
1037 vb
= ref_vb
[0] + pos
* 2 * 4;
1039 if (mb
->mb_type
== PIPE_MPEG12_MACROBLOCK_TYPE_BKWD
) {
1040 mo_vec
[0].x
= mb
->pmv
[0][1][0];
1041 mo_vec
[0].y
= mb
->pmv
[0][1][1];
1043 if (mb
->mo_type
== PIPE_MPEG12_MOTION_TYPE_FIELD
) {
1044 mo_vec
[0].y
= mb
->pmv
[0][1][1] - (mb
->pmv
[0][1][1] % 4);
1046 mo_vec
[1].x
= mb
->pmv
[1][1][0];
1047 mo_vec
[1].y
= mb
->pmv
[1][1][1] - (mb
->pmv
[1][1][1] % 4);
1049 if(mb
->mvfs
[0][1]) mo_vec
[0].y
+= 2;
1050 if(!mb
->mvfs
[1][1]) mo_vec
[1].y
-= 2;
1054 mo_vec
[0].x
= mb
->pmv
[0][0][0];
1055 mo_vec
[0].y
= mb
->pmv
[0][0][1];
1057 if (mb
->mo_type
== PIPE_MPEG12_MOTION_TYPE_FIELD
) {
1058 mo_vec
[0].y
= mb
->pmv
[0][0][1] - (mb
->pmv
[0][0][1] % 4);
1060 mo_vec
[1].x
= mb
->pmv
[1][0][0];
1061 mo_vec
[1].y
= mb
->pmv
[1][0][1] - (mb
->pmv
[1][0][1] % 4);
1063 if(mb
->mvfs
[0][0]) mo_vec
[0].y
+= 2;
1064 if(!mb
->mvfs
[1][0]) mo_vec
[1].y
-= 2;
1068 if (mb
->mo_type
== PIPE_MPEG12_MOTION_TYPE_FRAME
) {
1069 for (i
= 0; i
< 4 * 2; i
+= 2) {
1070 vb
[i
].x
= mo_vec
[0].x
;
1071 vb
[i
].y
= mo_vec
[0].y
;
1075 for (i
= 0; i
< 4 * 2; i
+= 2) {
1076 vb
[i
].x
= mo_vec
[0].x
;
1077 vb
[i
].y
= mo_vec
[0].y
;
1078 vb
[i
+ 1].x
= mo_vec
[1].x
;
1079 vb
[i
+ 1].y
= mo_vec
[1].y
;
1085 case PIPE_MPEG12_MACROBLOCK_TYPE_INTRA
:
1087 struct vert_stream_0
*vb
= ycbcr_vb
+ pos
* 4;
1088 struct vert_stream_0 v
;
1093 v
.field
[0][0].luma_eb
= mb
->cbp
& 32 ? 0.0f
: -1.0f
;
1094 v
.field
[0][1].luma_eb
= mb
->cbp
& 16 ? 0.0f
: -1.0f
;
1095 v
.field
[1][0].luma_eb
= mb
->cbp
& 8 ? 0.0f
: -1.0f
;
1096 v
.field
[1][1].luma_eb
= mb
->cbp
& 4 ? 0.0f
: -1.0f
;
1098 v
.field
[0][0].cb_eb
= mb
->cbp
& 2 ? 0.0f
: -1.0f
;
1099 v
.field
[0][1].cb_eb
= mb
->cbp
& 2 ? 0.0f
: -1.0f
;
1100 v
.field
[1][0].cb_eb
= mb
->cbp
& 2 ? 0.0f
: -1.0f
;
1101 v
.field
[1][1].cb_eb
= mb
->cbp
& 2 ? 0.0f
: -1.0f
;
1103 v
.field
[0][0].cr_eb
= mb
->cbp
& 1 ? 0.0f
: -1.0f
;
1104 v
.field
[0][1].cr_eb
= mb
->cbp
& 1 ? 0.0f
: -1.0f
;
1105 v
.field
[1][0].cr_eb
= mb
->cbp
& 1 ? 0.0f
: -1.0f
;
1106 v
.field
[1][1].cr_eb
= mb
->cbp
& 1 ? 0.0f
: -1.0f
;
1108 v
.interlaced
= mb
->dct_type
== PIPE_MPEG12_DCT_TYPE_FIELD
? 1.0f
: 0.0f
;
1110 for ( i
= 0; i
< 4; ++i
)
1111 memcpy(vb
+ i
, &v
, sizeof(v
));
1121 gen_macroblock_stream(struct vl_mpeg12_mc_renderer
*r
,
1122 unsigned *num_macroblocks
)
1124 unsigned offset
[NUM_MACROBLOCK_TYPES
];
1125 struct vert_stream_0
*ycbcr_vb
;
1126 struct vertex2f
*ref_vb
[2];
1127 struct pipe_transfer
*buf_transfer
[3];
1131 assert(num_macroblocks
);
1133 for (i
= 0; i
< r
->num_macroblocks
; ++i
) {
1134 enum MACROBLOCK_TYPE mb_type
= get_macroblock_type(&r
->macroblock_buf
[i
]);
1135 ++num_macroblocks
[mb_type
];
1140 for (i
= 1; i
< NUM_MACROBLOCK_TYPES
; ++i
)
1141 offset
[i
] = offset
[i
- 1] + num_macroblocks
[i
- 1];
1143 ycbcr_vb
= (struct vert_stream_0
*)pipe_buffer_map
1146 r
->vertex_bufs
.individual
.ycbcr
.buffer
,
1147 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD
,
1151 for (i
= 0; i
< 2; ++i
)
1152 ref_vb
[i
] = (struct vertex2f
*)pipe_buffer_map
1155 r
->vertex_bufs
.individual
.ref
[i
].buffer
,
1156 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD
,
1157 &buf_transfer
[i
+ 1]
1160 for (i
= 0; i
< r
->num_macroblocks
; ++i
) {
1161 enum MACROBLOCK_TYPE mb_type
= get_macroblock_type(&r
->macroblock_buf
[i
]);
1163 gen_macroblock_verts(r
, &r
->macroblock_buf
[i
], offset
[mb_type
],
1169 pipe_buffer_unmap(r
->pipe
, r
->vertex_bufs
.individual
.ycbcr
.buffer
, buf_transfer
[0]);
1170 for (i
= 0; i
< 2; ++i
)
1171 pipe_buffer_unmap(r
->pipe
, r
->vertex_bufs
.individual
.ref
[i
].buffer
, buf_transfer
[i
+ 1]);
1174 static struct pipe_sampler_view
1175 *find_or_create_sampler_view(struct vl_mpeg12_mc_renderer
*r
, struct pipe_surface
*surface
)
1177 struct pipe_sampler_view
*sampler_view
;
1181 sampler_view
= (struct pipe_sampler_view
*)util_keymap_lookup(r
->texview_map
, &surface
);
1182 if (!sampler_view
) {
1183 struct pipe_sampler_view templat
;
1184 boolean added_to_map
;
1186 u_sampler_view_default_template(&templat
, surface
->texture
,
1187 surface
->texture
->format
);
1188 sampler_view
= r
->pipe
->create_sampler_view(r
->pipe
, surface
->texture
,
1193 added_to_map
= util_keymap_insert(r
->texview_map
, &surface
,
1194 sampler_view
, r
->pipe
);
1195 assert(added_to_map
);
1198 return sampler_view
;
1202 flush(struct vl_mpeg12_mc_renderer
*r
)
1204 unsigned num_macroblocks
[NUM_MACROBLOCK_TYPES
] = { 0 };
1205 unsigned vb_start
= 0;
1208 assert(r
->num_macroblocks
== r
->macroblocks_per_batch
);
1210 xfer_buffers_unmap(r
);
1211 gen_macroblock_stream(r
, num_macroblocks
);
1213 if (num_macroblocks
[MACROBLOCK_TYPE_INTRA
] > 0) {
1214 r
->pipe
->set_vertex_buffers(r
->pipe
, 2, r
->vertex_bufs
.all
);
1215 r
->pipe
->bind_vertex_elements_state(r
->pipe
, r
->vertex_elems_state
.individual
.i
);
1216 r
->pipe
->set_fragment_sampler_views(r
->pipe
, 3, r
->sampler_views
.all
);
1217 r
->pipe
->bind_fragment_sampler_states(r
->pipe
, 3, r
->samplers
.all
);
1218 r
->pipe
->bind_vs_state(r
->pipe
, r
->i_vs
);
1219 r
->pipe
->bind_fs_state(r
->pipe
, r
->i_fs
);
1221 util_draw_arrays(r
->pipe
, PIPE_PRIM_QUADS
, vb_start
,
1222 num_macroblocks
[MACROBLOCK_TYPE_INTRA
] * 4);
1223 vb_start
+= num_macroblocks
[MACROBLOCK_TYPE_INTRA
] * 4;
1226 if (num_macroblocks
[MACROBLOCK_TYPE_FWD_FRAME_PRED
] > 0) {
1227 r
->pipe
->set_vertex_buffers(r
->pipe
, 3, r
->vertex_bufs
.all
);
1228 r
->pipe
->bind_vertex_elements_state(r
->pipe
, r
->vertex_elems_state
.individual
.p
);
1229 r
->textures
.individual
.ref
[0] = r
->past
->texture
;
1230 r
->sampler_views
.individual
.ref
[0] = find_or_create_sampler_view(r
, r
->past
);
1231 r
->pipe
->set_fragment_sampler_views(r
->pipe
, 4, r
->sampler_views
.all
);
1232 r
->pipe
->bind_fragment_sampler_states(r
->pipe
, 4, r
->samplers
.all
);
1233 r
->pipe
->bind_vs_state(r
->pipe
, r
->p_vs
[0]);
1234 r
->pipe
->bind_fs_state(r
->pipe
, r
->p_fs
[0]);
1236 util_draw_arrays(r
->pipe
, PIPE_PRIM_QUADS
, vb_start
,
1237 num_macroblocks
[MACROBLOCK_TYPE_FWD_FRAME_PRED
] * 4);
1238 vb_start
+= num_macroblocks
[MACROBLOCK_TYPE_FWD_FRAME_PRED
] * 4;
1241 if (num_macroblocks
[MACROBLOCK_TYPE_FWD_FIELD_PRED
] > 0) {
1242 r
->pipe
->set_vertex_buffers(r
->pipe
, 3, r
->vertex_bufs
.all
);
1243 r
->pipe
->bind_vertex_elements_state(r
->pipe
, r
->vertex_elems_state
.individual
.p
);
1244 r
->textures
.individual
.ref
[0] = r
->past
->texture
;
1245 r
->sampler_views
.individual
.ref
[0] = find_or_create_sampler_view(r
, r
->past
);
1246 r
->pipe
->set_fragment_sampler_views(r
->pipe
, 4, r
->sampler_views
.all
);
1247 r
->pipe
->bind_fragment_sampler_states(r
->pipe
, 4, r
->samplers
.all
);
1248 r
->pipe
->bind_vs_state(r
->pipe
, r
->p_vs
[1]);
1249 r
->pipe
->bind_fs_state(r
->pipe
, r
->p_fs
[1]);
1251 util_draw_arrays(r
->pipe
, PIPE_PRIM_QUADS
, vb_start
,
1252 num_macroblocks
[MACROBLOCK_TYPE_FWD_FIELD_PRED
] * 4);
1253 vb_start
+= num_macroblocks
[MACROBLOCK_TYPE_FWD_FIELD_PRED
] * 4;
1256 if (num_macroblocks
[MACROBLOCK_TYPE_BKWD_FRAME_PRED
] > 0) {
1257 r
->pipe
->set_vertex_buffers(r
->pipe
, 3, r
->vertex_bufs
.all
);
1258 r
->pipe
->bind_vertex_elements_state(r
->pipe
, r
->vertex_elems_state
.individual
.p
);
1259 r
->textures
.individual
.ref
[0] = r
->future
->texture
;
1260 r
->sampler_views
.individual
.ref
[0] = find_or_create_sampler_view(r
, r
->future
);
1261 r
->pipe
->set_fragment_sampler_views(r
->pipe
, 4, r
->sampler_views
.all
);
1262 r
->pipe
->bind_fragment_sampler_states(r
->pipe
, 4, r
->samplers
.all
);
1263 r
->pipe
->bind_vs_state(r
->pipe
, r
->p_vs
[0]);
1264 r
->pipe
->bind_fs_state(r
->pipe
, r
->p_fs
[0]);
1266 util_draw_arrays(r
->pipe
, PIPE_PRIM_QUADS
, vb_start
,
1267 num_macroblocks
[MACROBLOCK_TYPE_BKWD_FRAME_PRED
] * 4);
1268 vb_start
+= num_macroblocks
[MACROBLOCK_TYPE_BKWD_FRAME_PRED
] * 4;
1271 if (num_macroblocks
[MACROBLOCK_TYPE_BKWD_FIELD_PRED
] > 0) {
1272 r
->pipe
->set_vertex_buffers(r
->pipe
, 3, r
->vertex_bufs
.all
);
1273 r
->pipe
->bind_vertex_elements_state(r
->pipe
, r
->vertex_elems_state
.individual
.p
);
1274 r
->textures
.individual
.ref
[0] = r
->future
->texture
;
1275 r
->sampler_views
.individual
.ref
[0] = find_or_create_sampler_view(r
, r
->future
);
1276 r
->pipe
->set_fragment_sampler_views(r
->pipe
, 4, r
->sampler_views
.all
);
1277 r
->pipe
->bind_fragment_sampler_states(r
->pipe
, 4, r
->samplers
.all
);
1278 r
->pipe
->bind_vs_state(r
->pipe
, r
->p_vs
[1]);
1279 r
->pipe
->bind_fs_state(r
->pipe
, r
->p_fs
[1]);
1281 util_draw_arrays(r
->pipe
, PIPE_PRIM_QUADS
, vb_start
,
1282 num_macroblocks
[MACROBLOCK_TYPE_BKWD_FIELD_PRED
] * 4);
1283 vb_start
+= num_macroblocks
[MACROBLOCK_TYPE_BKWD_FIELD_PRED
] * 4;
1286 if (num_macroblocks
[MACROBLOCK_TYPE_BI_FRAME_PRED
] > 0) {
1287 r
->pipe
->set_vertex_buffers(r
->pipe
, 4, r
->vertex_bufs
.all
);
1288 r
->pipe
->bind_vertex_elements_state(r
->pipe
, r
->vertex_elems_state
.individual
.b
);
1289 r
->textures
.individual
.ref
[0] = r
->past
->texture
;
1290 r
->textures
.individual
.ref
[1] = r
->future
->texture
;
1291 r
->sampler_views
.individual
.ref
[0] = find_or_create_sampler_view(r
, r
->past
);
1292 r
->sampler_views
.individual
.ref
[1] = find_or_create_sampler_view(r
, r
->future
);
1293 r
->pipe
->set_fragment_sampler_views(r
->pipe
, 5, r
->sampler_views
.all
);
1294 r
->pipe
->bind_fragment_sampler_states(r
->pipe
, 5, r
->samplers
.all
);
1295 r
->pipe
->bind_vs_state(r
->pipe
, r
->b_vs
[0]);
1296 r
->pipe
->bind_fs_state(r
->pipe
, r
->b_fs
[0]);
1298 util_draw_arrays(r
->pipe
, PIPE_PRIM_QUADS
, vb_start
,
1299 num_macroblocks
[MACROBLOCK_TYPE_BI_FRAME_PRED
] * 4);
1300 vb_start
+= num_macroblocks
[MACROBLOCK_TYPE_BI_FRAME_PRED
] * 4;
1303 if (num_macroblocks
[MACROBLOCK_TYPE_BI_FIELD_PRED
] > 0) {
1304 r
->pipe
->set_vertex_buffers(r
->pipe
, 4, r
->vertex_bufs
.all
);
1305 r
->pipe
->bind_vertex_elements_state(r
->pipe
, r
->vertex_elems_state
.individual
.b
);
1306 r
->textures
.individual
.ref
[0] = r
->past
->texture
;
1307 r
->textures
.individual
.ref
[1] = r
->future
->texture
;
1308 r
->sampler_views
.individual
.ref
[0] = find_or_create_sampler_view(r
, r
->past
);
1309 r
->sampler_views
.individual
.ref
[1] = find_or_create_sampler_view(r
, r
->future
);
1310 r
->pipe
->set_fragment_sampler_views(r
->pipe
, 5, r
->sampler_views
.all
);
1311 r
->pipe
->bind_fragment_sampler_states(r
->pipe
, 5, r
->samplers
.all
);
1312 r
->pipe
->bind_vs_state(r
->pipe
, r
->b_vs
[1]);
1313 r
->pipe
->bind_fs_state(r
->pipe
, r
->b_fs
[1]);
1315 util_draw_arrays(r
->pipe
, PIPE_PRIM_QUADS
, vb_start
,
1316 num_macroblocks
[MACROBLOCK_TYPE_BI_FIELD_PRED
] * 4);
1317 vb_start
+= num_macroblocks
[MACROBLOCK_TYPE_BI_FIELD_PRED
] * 4;
1320 r
->pipe
->flush(r
->pipe
, PIPE_FLUSH_RENDER_CACHE
, r
->fence
);
1322 r
->num_macroblocks
= 0;
1323 xfer_buffers_map(r
);
1327 update_render_target(struct vl_mpeg12_mc_renderer
*r
)
1329 struct pipe_transfer
*buf_transfer
;
1330 struct vertex_shader_consts
*vs_consts
;
1332 vs_consts
= pipe_buffer_map
1334 r
->pipe
, r
->vs_const_buf
,
1335 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD
,
1339 vs_consts
->norm
.x
= 1.0f
/ r
->surface
->width
;
1340 vs_consts
->norm
.y
= 1.0f
/ r
->surface
->height
;
1342 pipe_buffer_unmap(r
->pipe
, r
->vs_const_buf
, buf_transfer
);
1344 r
->pipe
->set_constant_buffer(r
->pipe
, PIPE_SHADER_VERTEX
, 0,
1347 r
->fb_state
.cbufs
[0] = r
->surface
;
1349 r
->pipe
->set_framebuffer_state(r
->pipe
, &r
->fb_state
);
1350 r
->pipe
->set_viewport_state(r
->pipe
, &r
->viewport
);
1354 grab_coded_block(short *src
, short *dst
, unsigned dst_pitch
)
1361 for (y
= 0; y
< BLOCK_HEIGHT
; ++y
)
1362 memcpy(dst
+ y
* dst_pitch
, src
+ y
* BLOCK_WIDTH
, BLOCK_WIDTH
* 2);
1366 grab_blocks(struct vl_mpeg12_mc_renderer
*r
, unsigned mbx
, unsigned mby
,
1367 enum pipe_mpeg12_dct_type dct_type
, unsigned cbp
, short *blocks
)
1371 unsigned tb
= 0, sb
= 0;
1372 unsigned mbpx
= mbx
* MACROBLOCK_WIDTH
, mbpy
= mby
* MACROBLOCK_HEIGHT
;
1378 tex_pitch
= r
->tex_transfer
[0]->stride
/ util_format_get_blocksize(r
->tex_transfer
[0]->resource
->format
);
1379 texels
= r
->texels
[0] + mbpy
* tex_pitch
+ mbpx
;
1381 for (y
= 0; y
< 2; ++y
) {
1382 for (x
= 0; x
< 2; ++x
, ++tb
) {
1383 if ((cbp
>> (5 - tb
)) & 1) {
1384 grab_coded_block(blocks
+ sb
* BLOCK_WIDTH
* BLOCK_HEIGHT
,
1385 texels
+ y
* tex_pitch
* BLOCK_HEIGHT
+
1386 x
* BLOCK_WIDTH
, tex_pitch
);
1392 /* TODO: Implement 422, 444 */
1393 assert(r
->chroma_format
== PIPE_VIDEO_CHROMA_FORMAT_420
);
1398 for (tb
= 0; tb
< 2; ++tb
) {
1399 tex_pitch
= r
->tex_transfer
[tb
+ 1]->stride
/ util_format_get_blocksize(r
->tex_transfer
[tb
+ 1]->resource
->format
);
1400 texels
= r
->texels
[tb
+ 1] + mbpy
* tex_pitch
+ mbpx
;
1402 if ((cbp
>> (1 - tb
)) & 1) {
1403 grab_coded_block(blocks
+ sb
* BLOCK_WIDTH
* BLOCK_HEIGHT
, texels
, tex_pitch
);
1410 grab_macroblock(struct vl_mpeg12_mc_renderer
*r
,
1411 struct pipe_mpeg12_macroblock
*mb
)
1416 assert(r
->num_macroblocks
< r
->macroblocks_per_batch
);
1418 memcpy(&r
->macroblock_buf
[r
->num_macroblocks
], mb
,
1419 sizeof(struct pipe_mpeg12_macroblock
));
1421 grab_blocks(r
, mb
->mbx
, mb
->mby
, mb
->dct_type
, mb
->cbp
, mb
->blocks
);
1423 ++r
->num_macroblocks
;
1427 texview_map_delete(const struct keymap
*map
,
1428 const void *key
, void *data
,
1431 struct pipe_sampler_view
*sv
= (struct pipe_sampler_view
*)data
;
1438 pipe_sampler_view_reference(&sv
, NULL
);
1442 vl_mpeg12_mc_renderer_init(struct vl_mpeg12_mc_renderer
*renderer
,
1443 struct pipe_context
*pipe
,
1444 unsigned picture_width
,
1445 unsigned picture_height
,
1446 enum pipe_video_chroma_format chroma_format
,
1447 enum VL_MPEG12_MC_RENDERER_BUFFER_MODE bufmode
,
1452 /* TODO: Implement other policies */
1453 assert(bufmode
== VL_MPEG12_MC_RENDERER_BUFFER_PICTURE
);
1454 /* TODO: Non-pot buffers untested, probably doesn't work without changes to texcoord generation, vert shader, etc */
1455 assert(pot_buffers
);
1457 memset(renderer
, 0, sizeof(struct vl_mpeg12_mc_renderer
));
1459 renderer
->pipe
= pipe
;
1460 renderer
->picture_width
= picture_width
;
1461 renderer
->picture_height
= picture_height
;
1462 renderer
->chroma_format
= chroma_format
;
1463 renderer
->bufmode
= bufmode
;
1464 renderer
->pot_buffers
= pot_buffers
;
1466 renderer
->texview_map
= util_new_keymap(sizeof(struct pipe_surface
*), -1,
1467 texview_map_delete
);
1468 if (!renderer
->texview_map
)
1471 if (!init_pipe_state(renderer
)) {
1472 util_delete_keymap(renderer
->texview_map
, renderer
->pipe
);
1475 if (!init_shaders(renderer
)) {
1476 util_delete_keymap(renderer
->texview_map
, renderer
->pipe
);
1477 cleanup_pipe_state(renderer
);
1480 if (!init_buffers(renderer
)) {
1481 util_delete_keymap(renderer
->texview_map
, renderer
->pipe
);
1482 cleanup_shaders(renderer
);
1483 cleanup_pipe_state(renderer
);
1487 if (!init_const_buffers(renderer
)) {
1488 util_delete_keymap(renderer
->texview_map
, renderer
->pipe
);
1489 cleanup_pipe_state(renderer
);
1490 cleanup_shaders(renderer
);
1491 cleanup_buffers(renderer
);
1495 renderer
->surface
= NULL
;
1496 renderer
->past
= NULL
;
1497 renderer
->future
= NULL
;
1498 renderer
->num_macroblocks
= 0;
1500 xfer_buffers_map(renderer
);
1506 vl_mpeg12_mc_renderer_cleanup(struct vl_mpeg12_mc_renderer
*renderer
)
1510 xfer_buffers_unmap(renderer
);
1512 util_delete_keymap(renderer
->texview_map
, renderer
->pipe
);
1513 cleanup_pipe_state(renderer
);
1514 cleanup_shaders(renderer
);
1515 cleanup_buffers(renderer
);
1517 pipe_surface_reference(&renderer
->surface
, NULL
);
1518 pipe_surface_reference(&renderer
->past
, NULL
);
1519 pipe_surface_reference(&renderer
->future
, NULL
);
1523 vl_mpeg12_mc_renderer_render_macroblocks(struct vl_mpeg12_mc_renderer
1525 struct pipe_surface
*surface
,
1526 struct pipe_surface
*past
,
1527 struct pipe_surface
*future
,
1528 unsigned num_macroblocks
,
1529 struct pipe_mpeg12_macroblock
1530 *mpeg12_macroblocks
,
1531 struct pipe_fence_handle
**fence
)
1533 bool new_surface
= false;
1537 assert(num_macroblocks
);
1538 assert(mpeg12_macroblocks
);
1540 if (renderer
->surface
) {
1541 if (surface
!= renderer
->surface
) {
1542 if (renderer
->num_macroblocks
> 0) {
1549 /* If the surface we're rendering hasn't changed the ref frames shouldn't change. */
1550 assert(surface
!= renderer
->surface
|| renderer
->past
== past
);
1551 assert(surface
!= renderer
->surface
|| renderer
->future
== future
);
1557 pipe_surface_reference(&renderer
->surface
, surface
);
1558 pipe_surface_reference(&renderer
->past
, past
);
1559 pipe_surface_reference(&renderer
->future
, future
);
1560 renderer
->fence
= fence
;
1561 update_render_target(renderer
);
1564 while (num_macroblocks
) {
1565 unsigned left_in_batch
= renderer
->macroblocks_per_batch
- renderer
->num_macroblocks
;
1566 unsigned num_to_submit
= MIN2(num_macroblocks
, left_in_batch
);
1569 for (i
= 0; i
< num_to_submit
; ++i
) {
1570 assert(mpeg12_macroblocks
[i
].base
.codec
== PIPE_VIDEO_CODEC_MPEG12
);
1571 grab_macroblock(renderer
, &mpeg12_macroblocks
[i
]);
1574 num_macroblocks
-= num_to_submit
;
1576 if (renderer
->num_macroblocks
== renderer
->macroblocks_per_batch
) {
1578 /* Next time we get this surface it may have new ref frames */
1579 pipe_surface_reference(&renderer
->surface
, NULL
);
1580 pipe_surface_reference(&renderer
->past
, NULL
);
1581 pipe_surface_reference(&renderer
->future
, NULL
);