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
46 struct vertex_stream_0
89 static const unsigned const_mbtype_config
[VL_NUM_MACROBLOCK_TYPES
][2] = {
90 [VL_MACROBLOCK_TYPE_INTRA
] = { 0, 0 },
91 [VL_MACROBLOCK_TYPE_FWD_FRAME_PRED
] = { 1, 1 },
92 [VL_MACROBLOCK_TYPE_FWD_FIELD_PRED
] = { 1, 2 },
93 [VL_MACROBLOCK_TYPE_BKWD_FRAME_PRED
] = { 1, 1 },
94 [VL_MACROBLOCK_TYPE_BKWD_FIELD_PRED
] = { 1, 2 },
95 [VL_MACROBLOCK_TYPE_BI_FRAME_PRED
] = { 2, 1 },
96 [VL_MACROBLOCK_TYPE_BI_FIELD_PRED
] = { 2, 2 }
100 create_vert_shader(struct vl_mpeg12_mc_renderer
*r
, unsigned ref_frames
, unsigned mv_per_frame
)
102 struct ureg_program
*shader
;
103 struct ureg_src scale
;
104 struct ureg_src vrect
, vpos
, eb
[2][2], interlaced
, vmv
[4];
105 struct ureg_dst t_vpos
, t_vtex
;
106 struct ureg_dst o_vpos
, o_line
, o_vtex
[3], o_eb
[2], o_vmv
[4];
107 unsigned i
, j
, count
, label
;
109 shader
= ureg_create(TGSI_PROCESSOR_VERTEX
);
113 t_vpos
= ureg_DECL_temporary(shader
);
114 t_vtex
= ureg_DECL_temporary(shader
);
116 vrect
= ureg_DECL_vs_input(shader
, VS_I_RECT
);
117 vpos
= ureg_DECL_vs_input(shader
, VS_I_VPOS
);
118 eb
[0][0] = ureg_DECL_vs_input(shader
, VS_I_EB_0_0
);
119 eb
[1][0] = ureg_DECL_vs_input(shader
, VS_I_EB_1_0
);
120 eb
[0][1] = ureg_DECL_vs_input(shader
, VS_I_EB_0_1
);
121 eb
[1][1] = ureg_DECL_vs_input(shader
, VS_I_EB_1_1
);
122 interlaced
= ureg_DECL_vs_input(shader
, VS_I_INTERLACED
);
124 o_vpos
= ureg_DECL_output(shader
, TGSI_SEMANTIC_POSITION
, VS_O_VPOS
);
125 o_line
= ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_LINE
);
126 o_vtex
[0] = ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_TEX0
);
127 o_vtex
[1] = ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_TEX1
);
128 o_vtex
[2] = ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_TEX2
);
129 o_eb
[0] = ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_EB_0
);
130 o_eb
[1] = ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_EB_1
);
133 for (i
= 0; i
< ref_frames
; ++i
) {
134 for (j
= 0; j
< 2; ++j
) {
135 if(j
< mv_per_frame
) {
136 vmv
[count
] = ureg_DECL_vs_input(shader
, VS_I_MV0
+ count
);
137 o_vmv
[count
] = ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_MV0
+ count
);
144 * scale = (MACROBLOCK_WIDTH, MACROBLOCK_HEIGHT) / (dst.width, dst.height)
146 * t_vpos = (vpos + vrect) * scale
150 * o_line.xy = vrect * 8
151 * o_line.z = interlaced
155 * t_vtex.y = vrect.y * 0.5
158 * o_vtex[0].xy = t_vtex * scale
161 * o_vtex[1].xy = t_vtex * scale
163 * o_vtex[0..1].xy = t_vpos
165 * o_vtex[2].xy = t_vpos
167 * o_eb[0..1] = vrect.x ? eb[0..1][1] : eb[0..1][0]
169 * if(count > 0) { // Apply motion vectors
170 * scale = 0.5 / (dst.width, dst.height);
171 * o_vmv[0..count] = t_vpos + vmv[0..count] * scale
175 scale
= ureg_imm2f(shader
,
176 (float)MACROBLOCK_WIDTH
/ r
->buffer_width
,
177 (float)MACROBLOCK_HEIGHT
/ r
->buffer_height
);
179 ureg_ADD(shader
, ureg_writemask(t_vpos
, TGSI_WRITEMASK_XY
), vpos
, vrect
);
180 ureg_MUL(shader
, ureg_writemask(t_vpos
, TGSI_WRITEMASK_XY
), ureg_src(t_vpos
), scale
);
181 ureg_MOV(shader
, ureg_writemask(o_vpos
, TGSI_WRITEMASK_XY
), ureg_src(t_vpos
));
182 ureg_MOV(shader
, ureg_writemask(o_vpos
, TGSI_WRITEMASK_ZW
), vpos
);
184 ureg_MUL(shader
, ureg_writemask(o_line
, TGSI_WRITEMASK_XY
), vrect
,
185 ureg_imm2f(shader
, MACROBLOCK_WIDTH
/ 2, MACROBLOCK_HEIGHT
/ 2));
186 ureg_MOV(shader
, ureg_writemask(o_line
, TGSI_WRITEMASK_Z
),
187 ureg_scalar(interlaced
, TGSI_SWIZZLE_X
));
189 ureg_IF(shader
, interlaced
, &label
);
191 ureg_MOV(shader
, ureg_writemask(t_vtex
, TGSI_WRITEMASK_X
), vrect
);
192 ureg_MUL(shader
, ureg_writemask(t_vtex
, TGSI_WRITEMASK_Y
), vrect
, ureg_imm1f(shader
, 0.5f
));
193 ureg_ADD(shader
, ureg_writemask(t_vtex
, TGSI_WRITEMASK_XY
), vpos
, ureg_src(t_vtex
));
194 ureg_MUL(shader
, ureg_writemask(o_vtex
[0], TGSI_WRITEMASK_XY
), ureg_src(t_vtex
), scale
);
195 ureg_ADD(shader
, ureg_writemask(t_vtex
, TGSI_WRITEMASK_Y
), ureg_src(t_vtex
), ureg_imm1f(shader
, 0.5f
));
196 ureg_MUL(shader
, ureg_writemask(o_vtex
[1], TGSI_WRITEMASK_XY
), ureg_src(t_vtex
), scale
);
198 ureg_ELSE(shader
, &label
);
200 ureg_MOV(shader
, ureg_writemask(o_vtex
[0], TGSI_WRITEMASK_XY
), ureg_src(t_vpos
));
201 ureg_MOV(shader
, ureg_writemask(o_vtex
[1], TGSI_WRITEMASK_XY
), ureg_src(t_vpos
));
204 ureg_MOV(shader
, ureg_writemask(o_vtex
[2], TGSI_WRITEMASK_XY
), ureg_src(t_vpos
));
206 ureg_CMP(shader
, ureg_writemask(o_eb
[0], TGSI_WRITEMASK_XYZ
),
207 ureg_negate(ureg_scalar(vrect
, TGSI_SWIZZLE_X
)),
209 ureg_CMP(shader
, ureg_writemask(o_eb
[1], TGSI_WRITEMASK_XYZ
),
210 ureg_negate(ureg_scalar(vrect
, TGSI_SWIZZLE_X
)),
214 scale
= ureg_imm2f(shader
,
215 0.5f
/ r
->buffer_width
,
216 0.5f
/ r
->buffer_height
);
218 for (i
= 0; i
< count
; ++i
)
219 ureg_MAD(shader
, ureg_writemask(o_vmv
[i
], TGSI_WRITEMASK_XY
), scale
, vmv
[i
], ureg_src(t_vpos
));
222 ureg_release_temporary(shader
, t_vtex
);
223 ureg_release_temporary(shader
, t_vpos
);
227 return ureg_create_shader_and_destroy(shader
, r
->pipe
);
230 static struct ureg_dst
231 calc_field(struct ureg_program
*shader
)
234 struct ureg_src line
;
236 tmp
= ureg_DECL_temporary(shader
);
237 line
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_LINE
, TGSI_INTERPOLATE_LINEAR
);
240 * line.xy going from 0 to 8 in steps of 0.5
241 * line.z flag that controls interlacing
243 * tmp.z = fraction(line.y)
244 * tmp.z = tmp.z >= 0.5 ? 1 : 0
245 * tmp.xy = line >= 4 ? 1 : 0
246 * tmp.w = line.z ? tmp.z : tmp.y
248 ureg_FRC(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_Z
), ureg_scalar(line
, TGSI_SWIZZLE_Y
));
249 ureg_SGE(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_Z
), ureg_src(tmp
), ureg_imm1f(shader
, 0.5f
));
250 ureg_SGE(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_XY
), line
, ureg_imm2f(shader
, BLOCK_WIDTH
/ 2, BLOCK_HEIGHT
/ 2));
251 ureg_CMP(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_W
),
252 ureg_negate(ureg_scalar(line
, TGSI_SWIZZLE_Z
)),
253 ureg_scalar(ureg_src(tmp
), TGSI_SWIZZLE_Z
),
254 ureg_scalar(ureg_src(tmp
), TGSI_SWIZZLE_Y
));
259 static struct ureg_dst
260 fetch_ycbcr(struct vl_mpeg12_mc_renderer
*r
, struct ureg_program
*shader
, struct ureg_dst field
)
262 struct ureg_src tc
[3], sampler
[3], eb
[2];
263 struct ureg_dst texel
, t_tc
, t_eb_info
, tmp
;
266 texel
= ureg_DECL_temporary(shader
);
267 t_tc
= ureg_DECL_temporary(shader
);
268 t_eb_info
= ureg_DECL_temporary(shader
);
269 tmp
= ureg_DECL_temporary(shader
);
271 tc
[0] = ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_TEX0
, TGSI_INTERPOLATE_LINEAR
);
272 tc
[1] = ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_TEX1
, TGSI_INTERPOLATE_LINEAR
);
273 tc
[2] = ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_TEX2
, TGSI_INTERPOLATE_LINEAR
);
275 eb
[0] = ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_EB_0
, TGSI_INTERPOLATE_CONSTANT
);
276 eb
[1] = ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_EB_1
, TGSI_INTERPOLATE_CONSTANT
);
278 for (i
= 0; i
< 3; ++i
) {
279 sampler
[i
] = ureg_DECL_sampler(shader
, i
);
283 * texel.y = tex(field.y ? tc[1] : tc[0], sampler[0])
284 * texel.cb = tex(tc[2], sampler[1])
285 * texel.cr = tex(tc[2], sampler[2])
288 ureg_CMP(shader
, ureg_writemask(t_tc
, TGSI_WRITEMASK_XY
),
289 ureg_negate(ureg_scalar(ureg_src(field
), TGSI_SWIZZLE_W
)),
292 ureg_CMP(shader
, ureg_writemask(t_eb_info
, TGSI_WRITEMASK_XYZ
),
293 ureg_negate(ureg_scalar(ureg_src(field
), TGSI_SWIZZLE_W
)),
296 /* r600g is ignoring TGSI_INTERPOLATE_CONSTANT, just workaround this */
297 ureg_SGE(shader
, ureg_writemask(t_eb_info
, TGSI_WRITEMASK_XYZ
), ureg_src(t_eb_info
), ureg_imm1f(shader
, 0.5f
));
299 for (i
= 0; i
< 3; ++i
) {
300 ureg_IF(shader
, ureg_scalar(ureg_src(t_eb_info
), TGSI_SWIZZLE_X
+ i
), &label
);
301 ureg_MOV(shader
, ureg_writemask(texel
, TGSI_WRITEMASK_X
<< i
), ureg_imm1f(shader
, 0.0f
));
302 ureg_ELSE(shader
, &label
);
304 /* Nouveau and r600g can't writemask tex dst regs (yet?), do in two steps */
305 if(i
==0 || r
->chroma_format
== PIPE_VIDEO_CHROMA_FORMAT_444
) {
306 ureg_TEX(shader
, tmp
, TGSI_TEXTURE_3D
, ureg_src(t_tc
), sampler
[i
]);
308 ureg_TEX(shader
, tmp
, TGSI_TEXTURE_3D
, tc
[2], sampler
[i
]);
311 ureg_MOV(shader
, ureg_writemask(texel
, TGSI_WRITEMASK_X
<< i
), ureg_scalar(ureg_src(tmp
), TGSI_SWIZZLE_X
));
316 ureg_release_temporary(shader
, t_tc
);
317 ureg_release_temporary(shader
, t_eb_info
);
318 ureg_release_temporary(shader
, tmp
);
323 static struct ureg_dst
324 fetch_ref(struct ureg_program
*shader
, struct ureg_dst field
, unsigned ref_frames
, unsigned mv_per_frame
)
326 struct ureg_src tc
[ref_frames
* mv_per_frame
], sampler
[ref_frames
];
327 struct ureg_dst ref
[ref_frames
], t_tc
, result
;
330 for (i
= 0; i
< ref_frames
* mv_per_frame
; ++i
)
331 tc
[i
] = ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_MV0
+ i
, TGSI_INTERPOLATE_LINEAR
);
333 for (i
= 0; i
< ref_frames
; ++i
) {
334 sampler
[i
] = ureg_DECL_sampler(shader
, i
+ 3);
335 ref
[i
] = ureg_DECL_temporary(shader
);
338 result
= ureg_DECL_temporary(shader
);
340 if (ref_frames
== 1) {
341 if(mv_per_frame
== 1)
343 * result = tex(tc[0], sampler[0])
345 ureg_TEX(shader
, result
, TGSI_TEXTURE_2D
, tc
[0], sampler
[0]);
347 t_tc
= ureg_DECL_temporary(shader
);
349 * result = tex(field.y ? tc[1] : tc[0], sampler[0])
351 ureg_CMP(shader
, ureg_writemask(t_tc
, TGSI_WRITEMASK_XY
),
352 ureg_negate(ureg_scalar(ureg_src(field
), TGSI_SWIZZLE_Z
)),
354 ureg_TEX(shader
, result
, TGSI_TEXTURE_2D
, ureg_src(t_tc
), sampler
[0]);
356 ureg_release_temporary(shader
, t_tc
);
359 } else if (ref_frames
== 2) {
360 if(mv_per_frame
== 1) {
362 * ref[0..1] = tex(tc[0..1], sampler[0..1])
364 ureg_TEX(shader
, ref
[0], TGSI_TEXTURE_2D
, tc
[0], sampler
[0]);
365 ureg_TEX(shader
, ref
[1], TGSI_TEXTURE_2D
, tc
[1], sampler
[1]);
367 t_tc
= ureg_DECL_temporary(shader
);
371 * ref[0..1] = tex(tc[0..1], sampler[0..1])
373 * ref[0..1] = tex(tc[2..3], sampler[0..1])
375 ureg_CMP(shader
, ureg_writemask(t_tc
, TGSI_WRITEMASK_XY
),
376 ureg_negate(ureg_scalar(ureg_src(field
), TGSI_SWIZZLE_Z
)),
378 ureg_TEX(shader
, ref
[0], TGSI_TEXTURE_2D
, ureg_src(t_tc
), sampler
[0]);
380 ureg_CMP(shader
, ureg_writemask(t_tc
, TGSI_WRITEMASK_XY
),
381 ureg_negate(ureg_scalar(ureg_src(field
), TGSI_SWIZZLE_Z
)),
383 ureg_TEX(shader
, ref
[1], TGSI_TEXTURE_2D
, ureg_src(t_tc
), sampler
[1]);
385 ureg_release_temporary(shader
, t_tc
);
388 ureg_LRP(shader
, result
, ureg_scalar(ureg_imm1f(shader
, 0.5f
), TGSI_SWIZZLE_X
), ureg_src(ref
[0]), ureg_src(ref
[1]));
391 for (i
= 0; i
< ref_frames
; ++i
)
392 ureg_release_temporary(shader
, ref
[i
]);
398 create_frag_shader(struct vl_mpeg12_mc_renderer
*r
, unsigned ref_frames
, unsigned mv_per_frame
)
400 struct ureg_program
*shader
;
401 struct ureg_src result
;
402 struct ureg_dst field
, texel
;
403 struct ureg_dst fragment
;
405 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
409 fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
411 field
= calc_field(shader
);
412 texel
= fetch_ycbcr(r
, shader
, field
);
415 result
= ureg_imm1f(shader
, 0.5f
);
417 result
= ureg_src(fetch_ref(shader
, field
, ref_frames
, mv_per_frame
));
419 ureg_ADD(shader
, fragment
, ureg_src(texel
), result
);
421 ureg_release_temporary(shader
, field
);
422 ureg_release_temporary(shader
, texel
);
425 return ureg_create_shader_and_destroy(shader
, r
->pipe
);
429 init_mbtype_handler(struct vl_mpeg12_mc_renderer
*r
, enum VL_MACROBLOCK_TYPE type
,
430 struct pipe_vertex_element vertex_elems
[NUM_VS_INPUTS
])
432 unsigned ref_frames
, mv_per_frame
;
433 struct vl_mc_mbtype_handler
*handler
;
438 ref_frames
= const_mbtype_config
[type
][0];
439 mv_per_frame
= const_mbtype_config
[type
][1];
441 handler
= &r
->mbtype_handlers
[type
];
443 handler
->vs
= create_vert_shader(r
, ref_frames
, mv_per_frame
);
444 handler
->fs
= create_frag_shader(r
, ref_frames
, mv_per_frame
);
446 if (handler
->vs
== NULL
|| handler
->fs
== NULL
)
449 handler
->vertex_elems_state
= r
->pipe
->create_vertex_elements_state(
450 r
->pipe
, 7 + ref_frames
* mv_per_frame
, vertex_elems
);
452 if (handler
->vertex_elems_state
== NULL
)
455 if (!vl_vb_init(&handler
->pos
, r
->macroblocks_per_batch
, sizeof(struct vertex_stream_0
) / sizeof(float)))
458 for (i
= 0; i
< ref_frames
* mv_per_frame
; ++i
) {
459 if (!vl_vb_init(&handler
->mv
[i
], r
->macroblocks_per_batch
, sizeof(struct vertex2f
) / sizeof(float)))
467 cleanup_mbtype_handler(struct vl_mpeg12_mc_renderer
*r
, enum VL_MACROBLOCK_TYPE type
)
469 unsigned ref_frames
, mv_per_frame
;
470 struct vl_mc_mbtype_handler
*handler
;
475 ref_frames
= const_mbtype_config
[type
][0];
476 mv_per_frame
= const_mbtype_config
[type
][1];
478 handler
= &r
->mbtype_handlers
[type
];
480 r
->pipe
->delete_vs_state(r
->pipe
, handler
->vs
);
481 r
->pipe
->delete_fs_state(r
->pipe
, handler
->fs
);
482 r
->pipe
->delete_vertex_elements_state(r
->pipe
, handler
->vertex_elems_state
);
484 vl_vb_cleanup(&handler
->pos
);
486 for (i
= 0; i
< ref_frames
* mv_per_frame
; ++i
)
487 vl_vb_cleanup(&handler
->mv
[i
]);
492 init_pipe_state(struct vl_mpeg12_mc_renderer
*r
)
494 struct pipe_sampler_state sampler
;
495 struct pipe_rasterizer_state rs_state
;
501 r
->viewport
.scale
[0] = r
->buffer_width
;
502 r
->viewport
.scale
[1] = r
->buffer_height
;
503 r
->viewport
.scale
[2] = 1;
504 r
->viewport
.scale
[3] = 1;
505 r
->viewport
.translate
[0] = 0;
506 r
->viewport
.translate
[1] = 0;
507 r
->viewport
.translate
[2] = 0;
508 r
->viewport
.translate
[3] = 0;
510 r
->fb_state
.width
= r
->buffer_width
;
511 r
->fb_state
.height
= r
->buffer_height
;
512 r
->fb_state
.nr_cbufs
= 1;
513 r
->fb_state
.zsbuf
= NULL
;
516 filters
[0] = PIPE_TEX_FILTER_NEAREST
;
518 if (r
->chroma_format
== PIPE_VIDEO_CHROMA_FORMAT_444
|| true) { //TODO
519 filters
[1] = PIPE_TEX_FILTER_NEAREST
;
520 filters
[2] = PIPE_TEX_FILTER_NEAREST
;
523 filters
[1] = PIPE_TEX_FILTER_LINEAR
;
524 filters
[2] = PIPE_TEX_FILTER_LINEAR
;
526 /* Fwd, bkwd ref filters */
527 filters
[3] = PIPE_TEX_FILTER_LINEAR
;
528 filters
[4] = PIPE_TEX_FILTER_LINEAR
;
530 for (i
= 0; i
< 5; ++i
) {
531 memset(&sampler
, 0, sizeof(sampler
));
532 sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
533 sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
534 sampler
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_BORDER
;
535 sampler
.min_img_filter
= filters
[i
];
536 sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
537 sampler
.mag_img_filter
= filters
[i
];
538 sampler
.compare_mode
= PIPE_TEX_COMPARE_NONE
;
539 sampler
.compare_func
= PIPE_FUNC_ALWAYS
;
540 sampler
.normalized_coords
= 1;
541 /*sampler.shadow_ambient = ; */
542 /*sampler.lod_bias = ; */
544 /*sampler.max_lod = ; */
545 sampler
.border_color
[0] = 0.0f
;
546 sampler
.border_color
[1] = 0.0f
;
547 sampler
.border_color
[2] = 0.0f
;
548 sampler
.border_color
[3] = 0.0f
;
549 /*sampler.max_anisotropy = ; */
550 r
->samplers
.all
[i
] = r
->pipe
->create_sampler_state(r
->pipe
, &sampler
);
553 memset(&rs_state
, 0, sizeof(rs_state
));
554 /*rs_state.sprite_coord_enable */
555 rs_state
.sprite_coord_mode
= PIPE_SPRITE_COORD_UPPER_LEFT
;
556 rs_state
.point_quad_rasterization
= true;
557 rs_state
.point_size
= BLOCK_WIDTH
;
558 rs_state
.gl_rasterization_rules
= true;
559 r
->rs_state
= r
->pipe
->create_rasterizer_state(r
->pipe
, &rs_state
);
565 cleanup_pipe_state(struct vl_mpeg12_mc_renderer
*r
)
571 for (i
= 0; i
< 5; ++i
)
572 r
->pipe
->delete_sampler_state(r
->pipe
, r
->samplers
.all
[i
]);
574 r
->pipe
->delete_rasterizer_state(r
->pipe
, r
->rs_state
);
578 init_buffers(struct vl_mpeg12_mc_renderer
*r
)
580 struct pipe_resource
*idct_matrix
;
581 struct pipe_resource
template;
582 struct pipe_vertex_element vertex_elems
[NUM_VS_INPUTS
];
583 struct pipe_sampler_view sampler_view
;
586 align(r
->buffer_width
, MACROBLOCK_WIDTH
) / MACROBLOCK_WIDTH
;
588 align(r
->buffer_height
, MACROBLOCK_HEIGHT
) / MACROBLOCK_HEIGHT
;
594 r
->macroblocks_per_batch
=
595 mbw
* (r
->bufmode
== VL_MPEG12_MC_RENDERER_BUFFER_PICTURE
? mbh
: 1);
596 r
->num_macroblocks
= 0;
598 memset(&template, 0, sizeof(struct pipe_resource
));
599 template.target
= PIPE_TEXTURE_2D
;
600 /* TODO: Accomodate HW that can't do this and also for cases when this isn't precise enough */
601 template.format
= PIPE_FORMAT_R16_SNORM
;
602 template.last_level
= 0;
603 template.width0
= r
->buffer_width
;
604 template.height0
= r
->buffer_height
;
606 template.usage
= PIPE_USAGE_DYNAMIC
;
607 template.bind
= PIPE_BIND_SAMPLER_VIEW
;
610 r
->textures
.individual
.y
= r
->pipe
->screen
->resource_create(r
->pipe
->screen
, &template);
612 if (!(idct_matrix
= vl_idct_upload_matrix(r
->pipe
)))
615 if (!vl_idct_init(&r
->idct_luma
, r
->pipe
, r
->buffer_width
, r
->buffer_height
, idct_matrix
))
618 if (!vl_idct_init_buffer(&r
->idct_luma
, &r
->idct_y
, r
->textures
.individual
.y
))
621 vl_idct_map_buffers(&r
->idct_luma
, &r
->idct_y
);
623 if (r
->chroma_format
== PIPE_VIDEO_CHROMA_FORMAT_420
) {
624 template.width0
= r
->buffer_width
/ 2;
625 template.height0
= r
->buffer_height
/ 2;
627 else if (r
->chroma_format
== PIPE_VIDEO_CHROMA_FORMAT_422
)
628 template.height0
= r
->buffer_height
/ 2;
630 r
->textures
.individual
.cb
=
631 r
->pipe
->screen
->resource_create(r
->pipe
->screen
, &template);
632 r
->textures
.individual
.cr
=
633 r
->pipe
->screen
->resource_create(r
->pipe
->screen
, &template);
635 if(!vl_idct_init(&r
->idct_chroma
, r
->pipe
, template.width0
, template.height0
, idct_matrix
))
638 if (!vl_idct_init_buffer(&r
->idct_chroma
, &r
->idct_cb
, r
->textures
.individual
.cb
))
641 vl_idct_map_buffers(&r
->idct_chroma
, &r
->idct_cb
);
643 if (!vl_idct_init_buffer(&r
->idct_chroma
, &r
->idct_cr
, r
->textures
.individual
.cr
))
646 vl_idct_map_buffers(&r
->idct_chroma
, &r
->idct_cr
);
648 for (i
= 0; i
< 3; ++i
) {
649 u_sampler_view_default_template(&sampler_view
,
651 r
->textures
.all
[i
]->format
);
652 r
->sampler_views
.all
[i
] = r
->pipe
->create_sampler_view(r
->pipe
, r
->textures
.all
[i
], &sampler_view
);
655 memset(&vertex_elems
, 0, sizeof(vertex_elems
));
657 vertex_elems
[VS_I_RECT
] = vl_vb_get_quad_vertex_element();
658 r
->vertex_bufs
.individual
.quad
= vl_vb_upload_quads(r
->pipe
, r
->macroblocks_per_batch
);
660 /* Position element */
661 vertex_elems
[VS_I_VPOS
].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
663 /* y, cr, cb empty block element top left block */
664 vertex_elems
[VS_I_EB_0_0
].src_format
= PIPE_FORMAT_R32G32B32_FLOAT
;
666 /* y, cr, cb empty block element top right block */
667 vertex_elems
[VS_I_EB_0_1
].src_format
= PIPE_FORMAT_R32G32B32_FLOAT
;
669 /* y, cr, cb empty block element bottom left block */
670 vertex_elems
[VS_I_EB_1_0
].src_format
= PIPE_FORMAT_R32G32B32_FLOAT
;
672 /* y, cr, cb empty block element bottom right block */
673 vertex_elems
[VS_I_EB_1_1
].src_format
= PIPE_FORMAT_R32G32B32_FLOAT
;
675 /* progressive=0.0f interlaced=1.0f */
676 vertex_elems
[VS_I_INTERLACED
].src_format
= PIPE_FORMAT_R32_FLOAT
;
678 stride
= vl_vb_element_helper(&vertex_elems
[VS_I_VPOS
], 6, 1);
680 r
->vertex_bufs
.individual
.pos
= vl_vb_create_buffer(
681 r
->pipe
, r
->macroblocks_per_batch
, stride
);
683 for (i
= 0; i
< 4; ++i
) {
684 /* motion vector 0..4 element */
685 vertex_elems
[VS_I_MV0
+ i
].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
686 stride
= vl_vb_element_helper(&vertex_elems
[VS_I_MV0
+ i
], 1, i
+ 2);
687 r
->vertex_bufs
.individual
.mv
[i
] = vl_vb_create_buffer(
688 r
->pipe
, r
->macroblocks_per_batch
, stride
);
691 for(i
= 0; i
< VL_NUM_MACROBLOCK_TYPES
; ++i
)
692 init_mbtype_handler(r
, i
, vertex_elems
);
698 cleanup_buffers(struct vl_mpeg12_mc_renderer
*r
)
704 for (i
= 0; i
< 3; ++i
) {
705 pipe_sampler_view_reference(&r
->sampler_views
.all
[i
], NULL
);
706 pipe_resource_reference(&r
->vertex_bufs
.all
[i
].buffer
, NULL
);
707 pipe_resource_reference(&r
->textures
.all
[i
], NULL
);
710 for(i
= 0; i
<VL_NUM_MACROBLOCK_TYPES
; ++i
)
711 cleanup_mbtype_handler(r
, i
);
713 vl_idct_unmap_buffers(&r
->idct_luma
, &r
->idct_y
);
714 vl_idct_unmap_buffers(&r
->idct_chroma
, &r
->idct_cb
);
715 vl_idct_unmap_buffers(&r
->idct_chroma
, &r
->idct_cr
);
717 vl_idct_cleanup_buffer(&r
->idct_luma
, &r
->idct_y
);
718 vl_idct_cleanup_buffer(&r
->idct_chroma
, &r
->idct_cb
);
719 vl_idct_cleanup_buffer(&r
->idct_chroma
, &r
->idct_cr
);
721 vl_idct_cleanup(&r
->idct_luma
);
722 vl_idct_cleanup(&r
->idct_chroma
);
725 static enum VL_MACROBLOCK_TYPE
726 get_macroblock_type(struct pipe_mpeg12_macroblock
*mb
)
730 switch (mb
->mb_type
) {
731 case PIPE_MPEG12_MACROBLOCK_TYPE_INTRA
:
732 return VL_MACROBLOCK_TYPE_INTRA
;
733 case PIPE_MPEG12_MACROBLOCK_TYPE_FWD
:
734 return mb
->mo_type
== PIPE_MPEG12_MOTION_TYPE_FRAME
?
735 VL_MACROBLOCK_TYPE_FWD_FRAME_PRED
: VL_MACROBLOCK_TYPE_FWD_FIELD_PRED
;
736 case PIPE_MPEG12_MACROBLOCK_TYPE_BKWD
:
737 return mb
->mo_type
== PIPE_MPEG12_MOTION_TYPE_FRAME
?
738 VL_MACROBLOCK_TYPE_BKWD_FRAME_PRED
: VL_MACROBLOCK_TYPE_BKWD_FIELD_PRED
;
739 case PIPE_MPEG12_MACROBLOCK_TYPE_BI
:
740 return mb
->mo_type
== PIPE_MPEG12_MOTION_TYPE_FRAME
?
741 VL_MACROBLOCK_TYPE_BI_FRAME_PRED
: VL_MACROBLOCK_TYPE_BI_FIELD_PRED
;
751 upload_vertex_stream(struct vl_mpeg12_mc_renderer
*r
,
752 unsigned num_macroblocks
[VL_NUM_MACROBLOCK_TYPES
])
754 struct vertex_stream_0
*pos
;
755 struct vertex2f
*mv
[4];
757 struct pipe_transfer
*buf_transfer
[5];
762 assert(num_macroblocks
);
764 pos
= (struct vertex_stream_0
*)pipe_buffer_map
767 r
->vertex_bufs
.individual
.pos
.buffer
,
768 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD
,
772 for (i
= 0; i
< 4; ++i
)
773 mv
[i
] = (struct vertex2f
*)pipe_buffer_map
776 r
->vertex_bufs
.individual
.mv
[i
].buffer
,
777 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD
,
781 for (i
= 0; i
< VL_NUM_MACROBLOCK_TYPES
; ++i
) {
782 struct vl_mc_mbtype_handler
*handler
= &r
->mbtype_handlers
[i
];
783 unsigned count
= vl_vb_upload(&handler
->pos
, pos
);
787 unsigned ref_frames
, mv_per_frame
;
789 ref_frames
= const_mbtype_config
[i
][0];
790 mv_per_frame
= const_mbtype_config
[i
][1];
792 for (j
= 0; j
< ref_frames
* mv_per_frame
; ++j
)
793 vl_vb_upload(&handler
->mv
[j
], mv
[j
]);
795 for (j
= 0; j
< 4; ++j
)
798 num_macroblocks
[i
] = count
;
801 pipe_buffer_unmap(r
->pipe
, r
->vertex_bufs
.individual
.pos
.buffer
, buf_transfer
[0]);
802 for (i
= 0; i
< 4; ++i
)
803 pipe_buffer_unmap(r
->pipe
, r
->vertex_bufs
.individual
.mv
[i
].buffer
, buf_transfer
[i
+ 1]);
806 static struct pipe_sampler_view
807 *find_or_create_sampler_view(struct vl_mpeg12_mc_renderer
*r
, struct pipe_surface
*surface
)
809 struct pipe_sampler_view
*sampler_view
;
813 sampler_view
= (struct pipe_sampler_view
*)util_keymap_lookup(r
->texview_map
, &surface
);
815 struct pipe_sampler_view templat
;
816 boolean added_to_map
;
818 u_sampler_view_default_template(&templat
, surface
->texture
,
819 surface
->texture
->format
);
820 sampler_view
= r
->pipe
->create_sampler_view(r
->pipe
, surface
->texture
,
825 added_to_map
= util_keymap_insert(r
->texview_map
, &surface
,
826 sampler_view
, r
->pipe
);
827 assert(added_to_map
);
834 flush_mbtype_handler(struct vl_mpeg12_mc_renderer
*r
, enum VL_MACROBLOCK_TYPE type
,
835 unsigned vb_start
, unsigned num_macroblocks
)
837 unsigned ref_frames
, mv_per_frame
;
838 struct vl_mc_mbtype_handler
*handler
;
842 ref_frames
= const_mbtype_config
[type
][0];
843 mv_per_frame
= const_mbtype_config
[type
][1];
845 handler
= &r
->mbtype_handlers
[type
];
847 r
->pipe
->set_vertex_buffers(r
->pipe
, 2 + ref_frames
* mv_per_frame
, r
->vertex_bufs
.all
);
848 r
->pipe
->bind_vertex_elements_state(r
->pipe
, handler
->vertex_elems_state
);
850 if(ref_frames
== 2) {
852 r
->textures
.individual
.ref
[0] = r
->past
->texture
;
853 r
->textures
.individual
.ref
[1] = r
->future
->texture
;
854 r
->sampler_views
.individual
.ref
[0] = find_or_create_sampler_view(r
, r
->past
);
855 r
->sampler_views
.individual
.ref
[1] = find_or_create_sampler_view(r
, r
->future
);
857 } else if(ref_frames
== 1) {
859 struct pipe_surface
*ref
;
861 if(type
== VL_MACROBLOCK_TYPE_BKWD_FRAME_PRED
||
862 type
== VL_MACROBLOCK_TYPE_BKWD_FIELD_PRED
)
867 r
->textures
.individual
.ref
[0] = ref
->texture
;
868 r
->sampler_views
.individual
.ref
[0] = find_or_create_sampler_view(r
, ref
);
871 r
->pipe
->set_fragment_sampler_views(r
->pipe
, 3 + ref_frames
, r
->sampler_views
.all
);
872 r
->pipe
->bind_fragment_sampler_states(r
->pipe
, 3 + ref_frames
, r
->samplers
.all
);
873 r
->pipe
->bind_vs_state(r
->pipe
, handler
->vs
);
874 r
->pipe
->bind_fs_state(r
->pipe
, handler
->fs
);
876 util_draw_arrays(r
->pipe
, PIPE_PRIM_QUADS
, vb_start
, num_macroblocks
);
877 return num_macroblocks
;
881 get_motion_vectors(struct pipe_mpeg12_macroblock
*mb
, struct vertex2f mv
[4])
883 switch (mb
->mb_type
) {
884 case PIPE_MPEG12_MACROBLOCK_TYPE_BI
:
886 if (mb
->mo_type
== PIPE_MPEG12_MOTION_TYPE_FRAME
) {
888 mv
[1].x
= mb
->pmv
[0][1][0];
889 mv
[1].y
= mb
->pmv
[0][1][1];
892 mv
[2].x
= mb
->pmv
[0][1][0];
893 mv
[2].y
= mb
->pmv
[0][1][1] - (mb
->pmv
[0][1][1] % 4);
895 mv
[3].x
= mb
->pmv
[1][1][0];
896 mv
[3].y
= mb
->pmv
[1][1][1] - (mb
->pmv
[1][1][1] % 4);
898 if(mb
->mvfs
[0][1]) mv
[2].y
+= 2;
899 if(!mb
->mvfs
[1][1]) mv
[3].y
-= 2;
904 case PIPE_MPEG12_MACROBLOCK_TYPE_FWD
:
905 case PIPE_MPEG12_MACROBLOCK_TYPE_BKWD
:
907 if (mb
->mb_type
== PIPE_MPEG12_MACROBLOCK_TYPE_BKWD
) {
909 if (mb
->mo_type
== PIPE_MPEG12_MOTION_TYPE_FRAME
) {
910 mv
[0].x
= mb
->pmv
[0][1][0];
911 mv
[0].y
= mb
->pmv
[0][1][1];
914 mv
[0].x
= mb
->pmv
[0][1][0];
915 mv
[0].y
= mb
->pmv
[0][1][1] - (mb
->pmv
[0][1][1] % 4);
917 mv
[1].x
= mb
->pmv
[1][1][0];
918 mv
[1].y
= mb
->pmv
[1][1][1] - (mb
->pmv
[1][1][1] % 4);
920 if(mb
->mvfs
[0][1]) mv
[0].y
+= 2;
921 if(!mb
->mvfs
[1][1]) mv
[1].y
-= 2;
926 if (mb
->mo_type
== PIPE_MPEG12_MOTION_TYPE_FRAME
) {
927 mv
[0].x
= mb
->pmv
[0][0][0];
928 mv
[0].y
= mb
->pmv
[0][0][1];
931 mv
[0].x
= mb
->pmv
[0][0][0];
932 mv
[0].y
= mb
->pmv
[0][0][1] - (mb
->pmv
[0][0][1] % 4);
934 mv
[1].x
= mb
->pmv
[1][0][0];
935 mv
[1].y
= mb
->pmv
[1][0][1] - (mb
->pmv
[1][0][1] % 4);
937 if(mb
->mvfs
[0][0]) mv
[0].y
+= 2;
938 if(!mb
->mvfs
[1][0]) mv
[1].y
-= 2;
948 empty_block(enum pipe_video_chroma_format chroma_format
,
949 unsigned cbp
, unsigned component
,
950 unsigned x
, unsigned y
)
952 /* TODO: Implement 422, 444 */
953 assert(chroma_format
== PIPE_VIDEO_CHROMA_FORMAT_420
);
955 if(component
== 0) /*luma*/
956 return !(cbp
& (1 << (5 - (x
+ y
* 2))));
958 return !(cbp
& (1 << (2 - component
)));
962 grab_vectors(struct vl_mpeg12_mc_renderer
*r
,
963 struct pipe_mpeg12_macroblock
*mb
)
965 enum VL_MACROBLOCK_TYPE type
;
966 struct vl_mc_mbtype_handler
*handler
;
967 struct vertex2f mv
[4];
968 struct vertex_stream_0 info
;
970 unsigned ref_frames
, mv_per_frame
;
976 type
= get_macroblock_type(mb
);
978 ref_frames
= const_mbtype_config
[type
][0];
979 mv_per_frame
= const_mbtype_config
[type
][1];
981 handler
= &r
->mbtype_handlers
[type
];
983 pos
= handler
->pos
.num_verts
;
985 info
.pos
.x
= mb
->mbx
;
986 info
.pos
.y
= mb
->mby
;
987 for ( i
= 0; i
< 2; ++i
) {
988 for ( j
= 0; j
< 2; ++j
) {
989 info
.eb
[i
][j
].y
= empty_block(r
->chroma_format
, mb
->cbp
, 0, j
, i
);
990 info
.eb
[i
][j
].cr
= empty_block(r
->chroma_format
, mb
->cbp
, 1, j
, i
);
991 info
.eb
[i
][j
].cb
= empty_block(r
->chroma_format
, mb
->cbp
, 2, j
, i
);
994 info
.interlaced
= mb
->dct_type
== PIPE_MPEG12_DCT_TYPE_FIELD
? 1.0f
: 0.0f
;
995 vl_vb_add_block(&handler
->pos
, (float*)&info
);
997 get_motion_vectors(mb
, mv
);
998 for ( j
= 0; j
< ref_frames
* mv_per_frame
; ++j
)
999 vl_vb_add_block(&handler
->mv
[j
], (float*)&mv
[j
]);
1003 grab_blocks(struct vl_mpeg12_mc_renderer
*r
, unsigned mbx
, unsigned mby
,
1004 enum pipe_mpeg12_dct_type dct_type
, unsigned cbp
, short *blocks
)
1012 for (y
= 0; y
< 2; ++y
) {
1013 for (x
= 0; x
< 2; ++x
, ++tb
) {
1014 if (!empty_block(r
->chroma_format
, cbp
, 0, x
, y
)) {
1015 vl_idct_add_block(&r
->idct_y
, mbx
* 2 + x
, mby
* 2 + y
, blocks
);
1016 blocks
+= BLOCK_WIDTH
* BLOCK_HEIGHT
;
1021 /* TODO: Implement 422, 444 */
1022 assert(r
->chroma_format
== PIPE_VIDEO_CHROMA_FORMAT_420
);
1024 for (tb
= 1; tb
< 3; ++tb
) {
1025 if (!empty_block(r
->chroma_format
, cbp
, tb
, 0, 0)) {
1027 vl_idct_add_block(&r
->idct_cb
, mbx
, mby
, blocks
);
1029 vl_idct_add_block(&r
->idct_cr
, mbx
, mby
, blocks
);
1030 blocks
+= BLOCK_WIDTH
* BLOCK_HEIGHT
;
1036 grab_macroblock(struct vl_mpeg12_mc_renderer
*r
,
1037 struct pipe_mpeg12_macroblock
*mb
)
1042 assert(r
->num_macroblocks
< r
->macroblocks_per_batch
);
1044 grab_vectors(r
, mb
);
1045 grab_blocks(r
, mb
->mbx
, mb
->mby
, mb
->dct_type
, mb
->cbp
, mb
->blocks
);
1047 ++r
->num_macroblocks
;
1051 texview_map_delete(const struct keymap
*map
,
1052 const void *key
, void *data
,
1055 struct pipe_sampler_view
*sv
= (struct pipe_sampler_view
*)data
;
1062 pipe_sampler_view_reference(&sv
, NULL
);
1066 vl_mpeg12_mc_renderer_init(struct vl_mpeg12_mc_renderer
*renderer
,
1067 struct pipe_context
*pipe
,
1068 unsigned buffer_width
,
1069 unsigned buffer_height
,
1070 enum pipe_video_chroma_format chroma_format
,
1071 enum VL_MPEG12_MC_RENDERER_BUFFER_MODE bufmode
)
1076 /* TODO: Implement other policies */
1077 assert(bufmode
== VL_MPEG12_MC_RENDERER_BUFFER_PICTURE
);
1079 memset(renderer
, 0, sizeof(struct vl_mpeg12_mc_renderer
));
1081 renderer
->pipe
= pipe
;
1082 renderer
->buffer_width
= buffer_width
;
1083 renderer
->buffer_height
= buffer_height
;
1084 renderer
->chroma_format
= chroma_format
;
1085 renderer
->bufmode
= bufmode
;
1087 renderer
->texview_map
= util_new_keymap(sizeof(struct pipe_surface
*), -1,
1088 texview_map_delete
);
1089 if (!renderer
->texview_map
)
1092 if (!init_pipe_state(renderer
))
1093 goto error_pipe_state
;
1095 if (!init_buffers(renderer
))
1098 renderer
->surface
= NULL
;
1099 renderer
->past
= NULL
;
1100 renderer
->future
= NULL
;
1101 renderer
->num_macroblocks
= 0;
1106 cleanup_pipe_state(renderer
);
1109 util_delete_keymap(renderer
->texview_map
, renderer
->pipe
);
1114 vl_mpeg12_mc_renderer_cleanup(struct vl_mpeg12_mc_renderer
*renderer
)
1118 util_delete_keymap(renderer
->texview_map
, renderer
->pipe
);
1119 cleanup_pipe_state(renderer
);
1120 cleanup_buffers(renderer
);
1122 pipe_surface_reference(&renderer
->surface
, NULL
);
1123 pipe_surface_reference(&renderer
->past
, NULL
);
1124 pipe_surface_reference(&renderer
->future
, NULL
);
1128 vl_mpeg12_mc_renderer_render_macroblocks(struct vl_mpeg12_mc_renderer
1130 struct pipe_surface
*surface
,
1131 struct pipe_surface
*past
,
1132 struct pipe_surface
*future
,
1133 unsigned num_macroblocks
,
1134 struct pipe_mpeg12_macroblock
1135 *mpeg12_macroblocks
,
1136 struct pipe_fence_handle
**fence
)
1140 assert(num_macroblocks
);
1141 assert(mpeg12_macroblocks
);
1143 if (surface
!= renderer
->surface
) {
1144 pipe_surface_reference(&renderer
->surface
, surface
);
1145 pipe_surface_reference(&renderer
->past
, past
);
1146 pipe_surface_reference(&renderer
->future
, future
);
1147 renderer
->fence
= fence
;
1150 while (num_macroblocks
) {
1151 unsigned left_in_batch
= renderer
->macroblocks_per_batch
- renderer
->num_macroblocks
;
1152 unsigned num_to_submit
= MIN2(num_macroblocks
, left_in_batch
);
1155 for (i
= 0; i
< num_to_submit
; ++i
) {
1156 assert(mpeg12_macroblocks
[i
].base
.codec
== PIPE_VIDEO_CODEC_MPEG12
);
1157 grab_macroblock(renderer
, &mpeg12_macroblocks
[i
]);
1160 num_macroblocks
-= num_to_submit
;
1162 if (renderer
->num_macroblocks
== renderer
->macroblocks_per_batch
) {
1163 vl_mpeg12_mc_renderer_flush(renderer
);
1165 /* Next time we get this surface it may have new ref frames */
1166 pipe_surface_reference(&renderer
->surface
, NULL
);
1167 pipe_surface_reference(&renderer
->past
, NULL
);
1168 pipe_surface_reference(&renderer
->future
, NULL
);
1174 vl_mpeg12_mc_renderer_flush(struct vl_mpeg12_mc_renderer
*renderer
)
1176 unsigned num_verts
[VL_NUM_MACROBLOCK_TYPES
] = { 0 };
1177 unsigned vb_start
= 0, i
;
1180 assert(renderer
->num_macroblocks
<= renderer
->macroblocks_per_batch
);
1182 if (renderer
->num_macroblocks
== 0)
1185 vl_idct_unmap_buffers(&renderer
->idct_luma
, &renderer
->idct_y
);
1186 vl_idct_unmap_buffers(&renderer
->idct_chroma
, &renderer
->idct_cr
);
1187 vl_idct_unmap_buffers(&renderer
->idct_chroma
, &renderer
->idct_cb
);
1189 vl_idct_flush(&renderer
->idct_luma
, &renderer
->idct_y
);
1190 vl_idct_flush(&renderer
->idct_chroma
, &renderer
->idct_cr
);
1191 vl_idct_flush(&renderer
->idct_chroma
, &renderer
->idct_cb
);
1193 upload_vertex_stream(renderer
, num_verts
);
1195 renderer
->fb_state
.cbufs
[0] = renderer
->surface
;
1196 renderer
->pipe
->bind_rasterizer_state(renderer
->pipe
, renderer
->rs_state
);
1197 renderer
->pipe
->set_framebuffer_state(renderer
->pipe
, &renderer
->fb_state
);
1198 renderer
->pipe
->set_viewport_state(renderer
->pipe
, &renderer
->viewport
);
1200 for (i
= 0; i
< VL_NUM_MACROBLOCK_TYPES
; ++i
) {
1201 if (num_verts
[i
] > 0)
1202 vb_start
+= flush_mbtype_handler(renderer
, i
, vb_start
, num_verts
[i
]);
1205 renderer
->pipe
->flush(renderer
->pipe
, PIPE_FLUSH_RENDER_CACHE
, renderer
->fence
);
1207 vl_idct_map_buffers(&renderer
->idct_luma
, &renderer
->idct_y
);
1208 vl_idct_map_buffers(&renderer
->idct_chroma
, &renderer
->idct_cr
);
1209 vl_idct_map_buffers(&renderer
->idct_chroma
, &renderer
->idct_cb
);
1211 renderer
->num_macroblocks
= 0;