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_shader_consts
78 static const unsigned const_mbtype_config
[VL_NUM_MACROBLOCK_TYPES
][2] = {
79 [VL_MACROBLOCK_TYPE_INTRA
] = { 0, 0 },
80 [VL_MACROBLOCK_TYPE_FWD_FRAME_PRED
] = { 1, 1 },
81 [VL_MACROBLOCK_TYPE_FWD_FIELD_PRED
] = { 1, 2 },
82 [VL_MACROBLOCK_TYPE_BKWD_FRAME_PRED
] = { 1, 1 },
83 [VL_MACROBLOCK_TYPE_BKWD_FIELD_PRED
] = { 1, 2 },
84 [VL_MACROBLOCK_TYPE_BI_FRAME_PRED
] = { 2, 1 },
85 [VL_MACROBLOCK_TYPE_BI_FIELD_PRED
] = { 2, 2 }
89 create_vert_shader(struct vl_mpeg12_mc_renderer
*r
, unsigned ref_frames
, unsigned mv_per_frame
)
91 struct ureg_program
*shader
;
92 struct ureg_src norm
, mbs
;
93 struct ureg_src vrect
, vpos
, interlaced
, vmv
[4];
94 struct ureg_dst scale
, t_vpos
, t_vtex
;
95 struct ureg_dst o_vpos
, o_line
, o_vtex
[3], o_interlaced
, o_vmv
[4];
96 unsigned i
, j
, count
, label
;
98 shader
= ureg_create(TGSI_PROCESSOR_VERTEX
);
102 norm
= ureg_DECL_constant(shader
, 0);
103 mbs
= ureg_imm2f(shader
, MACROBLOCK_WIDTH
, MACROBLOCK_HEIGHT
);
105 scale
= ureg_DECL_temporary(shader
);
106 t_vpos
= ureg_DECL_temporary(shader
);
107 t_vtex
= ureg_DECL_temporary(shader
);
109 vrect
= ureg_DECL_vs_input(shader
, VS_I_RECT
);
110 vpos
= ureg_DECL_vs_input(shader
, VS_I_VPOS
);
111 interlaced
= ureg_DECL_vs_input(shader
, VS_I_INTERLACED
);
113 o_vpos
= ureg_DECL_output(shader
, TGSI_SEMANTIC_POSITION
, VS_O_VPOS
);
114 o_line
= ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_LINE
);
115 o_vtex
[0] = ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_TEX0
);
116 o_vtex
[1] = ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_TEX1
);
117 o_vtex
[2] = ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_TEX2
);
118 o_interlaced
= ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_INTERLACED
);
121 for (i
= 0; i
< ref_frames
; ++i
) {
122 for (j
= 0; j
< 2; ++j
) {
123 if(j
< mv_per_frame
) {
124 vmv
[count
] = ureg_DECL_vs_input(shader
, VS_I_MV0
+ i
* 2 + j
);
125 o_vmv
[count
] = ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_MV0
+ count
);
128 /* workaround for r600g */
129 else if(ref_frames
== 2)
130 ureg_DECL_vs_input(shader
, VS_I_MV0
+ i
* 2 + j
);
135 * scale = norm * mbs;
137 * t_vpos = (vpos + vrect) * scale
145 * t_vtex.y = vrect.y * 0.5
148 * o_vtex[0].xy = t_vtex * scale
151 * o_vtex[1].xy = t_vtex * scale
153 * o_vtex[0..1].xy = t_vpos
155 * o_vtex[2].xy = t_vpos
157 * if(count > 0) { // Apply motion vectors
158 * scale = norm * 0.5;
159 * o_vmv[0..count] = t_vpos + vmv[0..4] * scale
163 ureg_MUL(shader
, ureg_writemask(scale
, TGSI_WRITEMASK_XY
), norm
, mbs
);
165 ureg_ADD(shader
, ureg_writemask(t_vpos
, TGSI_WRITEMASK_XY
), vpos
, vrect
);
166 ureg_MUL(shader
, ureg_writemask(t_vpos
, TGSI_WRITEMASK_XY
), ureg_src(t_vpos
), ureg_src(scale
));
167 ureg_MOV(shader
, ureg_writemask(o_vpos
, TGSI_WRITEMASK_XY
), ureg_src(t_vpos
));
168 ureg_MOV(shader
, ureg_writemask(o_vpos
, TGSI_WRITEMASK_ZW
), vpos
);
170 ureg_MUL(shader
, ureg_writemask(o_line
, TGSI_WRITEMASK_XY
), vrect
,
171 ureg_imm2f(shader
, MACROBLOCK_WIDTH
/ 2, MACROBLOCK_HEIGHT
/ 2));
173 ureg_IF(shader
, interlaced
, &label
);
175 ureg_MOV(shader
, ureg_writemask(t_vtex
, TGSI_WRITEMASK_X
), vrect
);
176 ureg_MUL(shader
, ureg_writemask(t_vtex
, TGSI_WRITEMASK_Y
), vrect
, ureg_imm1f(shader
, 0.5f
));
177 ureg_ADD(shader
, ureg_writemask(t_vtex
, TGSI_WRITEMASK_XY
), vpos
, ureg_src(t_vtex
));
178 ureg_MUL(shader
, ureg_writemask(o_vtex
[0], TGSI_WRITEMASK_XY
), ureg_src(t_vtex
), ureg_src(scale
));
179 ureg_ADD(shader
, ureg_writemask(t_vtex
, TGSI_WRITEMASK_Y
), ureg_src(t_vtex
), ureg_imm1f(shader
, 0.5f
));
180 ureg_MUL(shader
, ureg_writemask(o_vtex
[1], TGSI_WRITEMASK_XY
), ureg_src(t_vtex
), ureg_src(scale
));
182 ureg_ELSE(shader
, &label
);
184 ureg_MOV(shader
, ureg_writemask(o_vtex
[0], TGSI_WRITEMASK_XY
), ureg_src(t_vpos
));
185 ureg_MOV(shader
, ureg_writemask(o_vtex
[1], TGSI_WRITEMASK_XY
), ureg_src(t_vpos
));
188 ureg_MOV(shader
, ureg_writemask(o_vtex
[2], TGSI_WRITEMASK_XY
), ureg_src(t_vpos
));
190 ureg_MOV(shader
, o_interlaced
, interlaced
);
193 ureg_MUL(shader
, ureg_writemask(scale
, TGSI_WRITEMASK_XY
), norm
, ureg_imm1f(shader
, 0.5f
));
194 for (i
= 0; i
< count
; ++i
)
195 ureg_MAD(shader
, ureg_writemask(o_vmv
[i
], TGSI_WRITEMASK_XY
), ureg_src(scale
), vmv
[i
], ureg_src(t_vpos
));
198 ureg_release_temporary(shader
, t_vtex
);
199 ureg_release_temporary(shader
, t_vpos
);
200 ureg_release_temporary(shader
, scale
);
204 return ureg_create_shader_and_destroy(shader
, r
->pipe
);
207 static struct ureg_dst
208 calc_field(struct ureg_program
*shader
)
211 struct ureg_src line
;
213 tmp
= ureg_DECL_temporary(shader
);
214 line
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_LINE
, TGSI_INTERPOLATE_LINEAR
);
217 * line going from 0 to 8 in steps of 0.5
219 * tmp.z = fraction(line.y)
220 * tmp.z = tmp.z >= 0.5 ? 1 : 0
222 ureg_FRC(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_Y
), line
);
223 ureg_SGE(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_Y
), ureg_src(tmp
), ureg_imm1f(shader
, 0.5f
));
228 static struct ureg_dst
229 fetch_ycbcr(struct vl_mpeg12_mc_renderer
*r
, struct ureg_program
*shader
, struct ureg_dst field
)
231 struct ureg_src tc
[3], interlaced
;
232 struct ureg_src sampler
[3];
233 struct ureg_dst texel
, t_tc
, tmp
;
236 texel
= ureg_DECL_temporary(shader
);
237 t_tc
= ureg_DECL_temporary(shader
);
238 tmp
= ureg_DECL_temporary(shader
);
240 tc
[0] = ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_TEX0
, TGSI_INTERPOLATE_LINEAR
);
241 tc
[1] = ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_TEX1
, TGSI_INTERPOLATE_LINEAR
);
242 tc
[2] = ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_TEX2
, TGSI_INTERPOLATE_LINEAR
);
244 interlaced
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_INTERLACED
, TGSI_INTERPOLATE_CONSTANT
);
246 for (i
= 0; i
< 3; ++i
) {
247 sampler
[i
] = ureg_DECL_sampler(shader
, i
);
251 * texel.y = tex(field ? tc[1] : tc[0], sampler[0])
252 * texel.cb = tex(tc[2], sampler[1])
253 * texel.cr = tex(tc[2], sampler[2])
255 ureg_MUL(shader
, tmp
, interlaced
, ureg_scalar(ureg_src(field
), TGSI_SWIZZLE_Y
));
257 for (i
= 0; i
< 3; ++i
) {
258 if(i
==0 || r
->chroma_format
== PIPE_VIDEO_CHROMA_FORMAT_444
) {
260 ureg_IF(shader
, ureg_scalar(ureg_src(tmp
), TGSI_SWIZZLE_X
), &label
);
261 ureg_MOV(shader
, ureg_writemask(t_tc
, TGSI_WRITEMASK_XY
), tc
[1]);
262 ureg_ELSE(shader
, &label
);
263 ureg_MOV(shader
, ureg_writemask(t_tc
, TGSI_WRITEMASK_XY
), tc
[0]);
267 ureg_MOV(shader
, ureg_writemask(t_tc
, TGSI_WRITEMASK_XY
), tc
[2]);
270 /* Nouveau and r600g can't writemask tex dst regs (yet?), do in two steps */
271 ureg_TEX(shader
, tmp
, TGSI_TEXTURE_3D
, ureg_src(t_tc
), sampler
[i
]);
272 ureg_MOV(shader
, ureg_writemask(texel
, TGSI_WRITEMASK_X
<< i
), ureg_scalar(ureg_src(tmp
), TGSI_SWIZZLE_X
));
275 ureg_release_temporary(shader
, t_tc
);
276 ureg_release_temporary(shader
, tmp
);
282 create_frag_shader(struct vl_mpeg12_mc_renderer
*r
, unsigned ref_frames
, unsigned mv_per_frame
)
284 struct ureg_program
*shader
;
285 struct ureg_src tc
[ref_frames
* mv_per_frame
], sampler
[ref_frames
], result
;
286 struct ureg_dst field
, texel
, ref
[ref_frames
];
287 struct ureg_dst fragment
;
290 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
294 fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
296 for (i
= 0; i
< ref_frames
* mv_per_frame
; ++i
)
297 tc
[i
] = ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_MV0
+ i
, TGSI_INTERPOLATE_LINEAR
);
299 for (i
= 0; i
< ref_frames
; ++i
) {
300 sampler
[i
] = ureg_DECL_sampler(shader
, i
+ 3);
301 ref
[i
] = ureg_DECL_temporary(shader
);
304 field
= calc_field(shader
);
305 texel
= fetch_ycbcr(r
, shader
, field
);
309 result
= ureg_scalar(ureg_imm1f(shader
, 0.5f
), TGSI_SWIZZLE_X
);
313 if(mv_per_frame
== 1)
314 ureg_TEX(shader
, ref
[0], TGSI_TEXTURE_2D
, tc
[0], sampler
[0]);
316 ureg_IF(shader
, ureg_scalar(ureg_src(field
), TGSI_SWIZZLE_Y
), &label
);
317 ureg_TEX(shader
, ref
[0], TGSI_TEXTURE_2D
, tc
[1], sampler
[0]);
318 ureg_ELSE(shader
, &label
);
319 ureg_TEX(shader
, ref
[0], TGSI_TEXTURE_2D
, tc
[0], sampler
[0]);
322 result
= ureg_src(ref
[0]);
326 if(mv_per_frame
== 1) {
327 ureg_TEX(shader
, ref
[0], TGSI_TEXTURE_2D
, tc
[0], sampler
[0]);
328 ureg_TEX(shader
, ref
[1], TGSI_TEXTURE_2D
, tc
[1], sampler
[1]);
330 ureg_IF(shader
, ureg_scalar(ureg_src(field
), TGSI_SWIZZLE_Y
), &label
);
331 ureg_TEX(shader
, ref
[0], TGSI_TEXTURE_2D
, tc
[1], sampler
[0]);
332 ureg_TEX(shader
, ref
[1], TGSI_TEXTURE_2D
, tc
[3], sampler
[1]);
333 ureg_ELSE(shader
, &label
);
334 ureg_TEX(shader
, ref
[0], TGSI_TEXTURE_2D
, tc
[0], sampler
[0]);
335 ureg_TEX(shader
, ref
[1], TGSI_TEXTURE_2D
, tc
[2], sampler
[1]);
339 ureg_LRP(shader
, ref
[0], ureg_scalar(ureg_imm1f(shader
, 0.5f
), TGSI_SWIZZLE_X
), ureg_src(ref
[0]), ureg_src(ref
[1]));
340 result
= ureg_src(ref
[0]);
346 ureg_ADD(shader
, fragment
, ureg_src(texel
), result
);
348 for (i
= 0; i
< ref_frames
; ++i
)
349 ureg_release_temporary(shader
, ref
[i
]);
351 ureg_release_temporary(shader
, field
);
352 ureg_release_temporary(shader
, texel
);
355 return ureg_create_shader_and_destroy(shader
, r
->pipe
);
359 init_mbtype_handler(struct vl_mpeg12_mc_renderer
*r
, enum VL_MACROBLOCK_TYPE type
,
360 struct pipe_vertex_element vertex_elems
[NUM_VS_INPUTS
])
362 unsigned ref_frames
, mv_per_frame
;
363 struct vl_mc_mbtype_handler
*handler
;
368 ref_frames
= const_mbtype_config
[type
][0];
369 mv_per_frame
= const_mbtype_config
[type
][1];
371 handler
= &r
->mbtype_handlers
[type
];
373 handler
->vs
= create_vert_shader(r
, ref_frames
, mv_per_frame
);
374 handler
->fs
= create_frag_shader(r
, ref_frames
, mv_per_frame
);
376 if (handler
->vs
== NULL
|| handler
->fs
== NULL
)
379 handler
->vertex_elems_state
= r
->pipe
->create_vertex_elements_state(
380 r
->pipe
, 3 + ref_frames
* mv_per_frame
, vertex_elems
);
382 if (handler
->vertex_elems_state
== NULL
)
385 if (!vl_vb_init(&handler
->pos
, r
->macroblocks_per_batch
))
388 handler
->interlaced
= MALLOC(sizeof(float) * r
->macroblocks_per_batch
* 4);
389 if (handler
->interlaced
== NULL
)
392 for (i
= 0; i
< 4 /*TODO: ref_frames * mv_per_frame */; ++i
) {
393 handler
->mv
[i
] = MALLOC(sizeof(struct vertex2f
) * r
->macroblocks_per_batch
* 4);
394 if (handler
->mv
[i
] == NULL
)
402 cleanup_mbtype_handler(struct vl_mpeg12_mc_renderer
*r
, enum VL_MACROBLOCK_TYPE type
)
404 unsigned ref_frames
, mv_per_frame
;
405 struct vl_mc_mbtype_handler
*handler
;
410 ref_frames
= const_mbtype_config
[type
][0];
411 mv_per_frame
= const_mbtype_config
[type
][1];
413 handler
= &r
->mbtype_handlers
[type
];
415 r
->pipe
->delete_vs_state(r
->pipe
, handler
->vs
);
416 r
->pipe
->delete_fs_state(r
->pipe
, handler
->fs
);
417 r
->pipe
->delete_vertex_elements_state(r
->pipe
, handler
->vertex_elems_state
);
419 handler
->interlaced
= MALLOC(sizeof(float) * r
->macroblocks_per_batch
* 4);
420 FREE(handler
->interlaced
);
422 for (i
= 0; i
< 4 /*TODO: ref_frames * mv_per_frame */; ++i
)
423 FREE(handler
->mv
[i
]);
428 init_pipe_state(struct vl_mpeg12_mc_renderer
*r
)
430 struct pipe_sampler_state sampler
;
436 r
->viewport
.scale
[0] = r
->pot_buffers
?
437 util_next_power_of_two(r
->picture_width
) : r
->picture_width
;
438 r
->viewport
.scale
[1] = r
->pot_buffers
?
439 util_next_power_of_two(r
->picture_height
) : r
->picture_height
;
440 r
->viewport
.scale
[2] = 1;
441 r
->viewport
.scale
[3] = 1;
442 r
->viewport
.translate
[0] = 0;
443 r
->viewport
.translate
[1] = 0;
444 r
->viewport
.translate
[2] = 0;
445 r
->viewport
.translate
[3] = 0;
447 r
->fb_state
.width
= r
->pot_buffers
?
448 util_next_power_of_two(r
->picture_width
) : r
->picture_width
;
449 r
->fb_state
.height
= r
->pot_buffers
?
450 util_next_power_of_two(r
->picture_height
) : r
->picture_height
;
451 r
->fb_state
.nr_cbufs
= 1;
452 r
->fb_state
.zsbuf
= NULL
;
455 filters
[0] = PIPE_TEX_FILTER_NEAREST
;
457 if (r
->chroma_format
== PIPE_VIDEO_CHROMA_FORMAT_444
|| true) { //TODO
458 filters
[1] = PIPE_TEX_FILTER_NEAREST
;
459 filters
[2] = PIPE_TEX_FILTER_NEAREST
;
462 filters
[1] = PIPE_TEX_FILTER_LINEAR
;
463 filters
[2] = PIPE_TEX_FILTER_LINEAR
;
465 /* Fwd, bkwd ref filters */
466 filters
[3] = PIPE_TEX_FILTER_LINEAR
;
467 filters
[4] = PIPE_TEX_FILTER_LINEAR
;
469 for (i
= 0; i
< 5; ++i
) {
470 memset(&sampler
, 0, sizeof(sampler
));
471 sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
472 sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
473 sampler
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_BORDER
;
474 sampler
.min_img_filter
= filters
[i
];
475 sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
476 sampler
.mag_img_filter
= filters
[i
];
477 sampler
.compare_mode
= PIPE_TEX_COMPARE_NONE
;
478 sampler
.compare_func
= PIPE_FUNC_ALWAYS
;
479 sampler
.normalized_coords
= 1;
480 /*sampler.shadow_ambient = ; */
481 /*sampler.lod_bias = ; */
483 /*sampler.max_lod = ; */
484 sampler
.border_color
[0] = 0.0f
;
485 sampler
.border_color
[1] = 0.0f
;
486 sampler
.border_color
[2] = 0.0f
;
487 sampler
.border_color
[3] = 0.0f
;
488 /*sampler.max_anisotropy = ; */
489 r
->samplers
.all
[i
] = r
->pipe
->create_sampler_state(r
->pipe
, &sampler
);
496 cleanup_pipe_state(struct vl_mpeg12_mc_renderer
*r
)
502 for (i
= 0; i
< 5; ++i
)
503 r
->pipe
->delete_sampler_state(r
->pipe
, r
->samplers
.all
[i
]);
507 init_buffers(struct vl_mpeg12_mc_renderer
*r
)
509 struct pipe_resource
template;
510 struct pipe_vertex_element vertex_elems
[NUM_VS_INPUTS
];
511 struct pipe_sampler_view sampler_view
;
514 align(r
->picture_width
, MACROBLOCK_WIDTH
) / MACROBLOCK_WIDTH
;
516 align(r
->picture_height
, MACROBLOCK_HEIGHT
) / MACROBLOCK_HEIGHT
;
522 r
->macroblocks_per_batch
=
523 mbw
* (r
->bufmode
== VL_MPEG12_MC_RENDERER_BUFFER_PICTURE
? mbh
: 1);
524 r
->num_macroblocks
= 0;
526 memset(&template, 0, sizeof(struct pipe_resource
));
527 template.target
= PIPE_TEXTURE_2D
;
528 /* TODO: Accomodate HW that can't do this and also for cases when this isn't precise enough */
529 template.format
= PIPE_FORMAT_R16_SNORM
;
530 template.last_level
= 0;
531 template.width0
= r
->pot_buffers
?
532 util_next_power_of_two(r
->picture_width
) : r
->picture_width
;
533 template.height0
= r
->pot_buffers
?
534 util_next_power_of_two(r
->picture_height
) : r
->picture_height
;
536 template.usage
= PIPE_USAGE_DYNAMIC
;
537 template.bind
= PIPE_BIND_SAMPLER_VIEW
;
540 r
->textures
.individual
.y
= r
->pipe
->screen
->resource_create(r
->pipe
->screen
, &template);
542 if (r
->chroma_format
== PIPE_VIDEO_CHROMA_FORMAT_420
) {
543 template.width0
= r
->pot_buffers
?
544 util_next_power_of_two(r
->picture_width
/ 2) :
545 r
->picture_width
/ 2;
546 template.height0
= r
->pot_buffers
?
547 util_next_power_of_two(r
->picture_height
/ 2) :
548 r
->picture_height
/ 2;
550 else if (r
->chroma_format
== PIPE_VIDEO_CHROMA_FORMAT_422
)
551 template.height0
= r
->pot_buffers
?
552 util_next_power_of_two(r
->picture_height
/ 2) :
553 r
->picture_height
/ 2;
555 r
->textures
.individual
.cb
=
556 r
->pipe
->screen
->resource_create(r
->pipe
->screen
, &template);
557 r
->textures
.individual
.cr
=
558 r
->pipe
->screen
->resource_create(r
->pipe
->screen
, &template);
560 for (i
= 0; i
< 3; ++i
) {
561 u_sampler_view_default_template(&sampler_view
,
563 r
->textures
.all
[i
]->format
);
564 r
->sampler_views
.all
[i
] = r
->pipe
->create_sampler_view(r
->pipe
, r
->textures
.all
[i
], &sampler_view
);
567 r
->vertex_bufs
.individual
.quad
= vl_vb_upload_quads(r
->pipe
, r
->macroblocks_per_batch
);
569 r
->vertex_bufs
.individual
.ycbcr
.stride
= sizeof(struct vertex2f
);
570 r
->vertex_bufs
.individual
.ycbcr
.max_index
= 4 * r
->macroblocks_per_batch
- 1;
571 r
->vertex_bufs
.individual
.ycbcr
.buffer_offset
= 0;
572 /* XXX: Create with usage DYNAMIC or STREAM */
573 r
->vertex_bufs
.individual
.ycbcr
.buffer
= pipe_buffer_create
576 PIPE_BIND_VERTEX_BUFFER
,
577 sizeof(struct vertex2f
) * 4 * r
->macroblocks_per_batch
580 r
->vertex_bufs
.individual
.interlaced
.stride
= sizeof(float);
581 r
->vertex_bufs
.individual
.interlaced
.max_index
= 4 * r
->macroblocks_per_batch
- 1;
582 r
->vertex_bufs
.individual
.interlaced
.buffer_offset
= 0;
583 /* XXX: Create with usage DYNAMIC or STREAM */
584 r
->vertex_bufs
.individual
.interlaced
.buffer
= pipe_buffer_create
587 PIPE_BIND_VERTEX_BUFFER
,
588 sizeof(float) * 4 * r
->macroblocks_per_batch
591 for (i
= 0; i
< 4; ++i
) {
592 r
->vertex_bufs
.individual
.mv
[i
].stride
= sizeof(struct vertex2f
);
593 r
->vertex_bufs
.individual
.mv
[i
].max_index
= 4 * r
->macroblocks_per_batch
- 1;
594 r
->vertex_bufs
.individual
.mv
[i
].buffer_offset
= 0;
595 /* XXX: Create with usage DYNAMIC or STREAM */
596 r
->vertex_bufs
.individual
.mv
[i
].buffer
= pipe_buffer_create
599 PIPE_BIND_VERTEX_BUFFER
,
600 sizeof(struct vertex2f
) * 4 * r
->macroblocks_per_batch
604 memset(&vertex_elems
, 0, sizeof(vertex_elems
));
606 /* Rectangle element */
607 vertex_elems
[VS_I_RECT
].src_offset
= 0;
608 vertex_elems
[VS_I_RECT
].instance_divisor
= 0;
609 vertex_elems
[VS_I_RECT
].vertex_buffer_index
= 0;
610 vertex_elems
[VS_I_RECT
].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
612 /* Position element */
613 vertex_elems
[VS_I_VPOS
].src_offset
= 0;
614 vertex_elems
[VS_I_VPOS
].instance_divisor
= 0;
615 vertex_elems
[VS_I_VPOS
].vertex_buffer_index
= 1;
616 vertex_elems
[VS_I_VPOS
].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
618 /* progressive=1.0f interlaced=0.0f */
619 vertex_elems
[VS_I_INTERLACED
].src_offset
= 0;
620 vertex_elems
[VS_I_INTERLACED
].instance_divisor
= 0;
621 vertex_elems
[VS_I_INTERLACED
].vertex_buffer_index
= 2;
622 vertex_elems
[VS_I_INTERLACED
].src_format
= PIPE_FORMAT_R32_FLOAT
;
624 /* First ref surface top field texcoord element */
625 vertex_elems
[VS_I_MV0
].src_offset
= 0;
626 vertex_elems
[VS_I_MV0
].instance_divisor
= 0;
627 vertex_elems
[VS_I_MV0
].vertex_buffer_index
= 3;
628 vertex_elems
[VS_I_MV0
].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
630 /* First ref surface bottom field texcoord element */
631 vertex_elems
[VS_I_MV1
].src_offset
= 0;
632 vertex_elems
[VS_I_MV1
].instance_divisor
= 0;
633 vertex_elems
[VS_I_MV1
].vertex_buffer_index
= 4;
634 vertex_elems
[VS_I_MV1
].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
636 /* Second ref surface top field texcoord element */
637 vertex_elems
[VS_I_MV2
].src_offset
= 0;
638 vertex_elems
[VS_I_MV2
].instance_divisor
= 0;
639 vertex_elems
[VS_I_MV2
].vertex_buffer_index
= 5;
640 vertex_elems
[VS_I_MV2
].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
642 /* Second ref surface bottom field texcoord element */
643 vertex_elems
[VS_I_MV3
].src_offset
= 0;
644 vertex_elems
[VS_I_MV3
].instance_divisor
= 0;
645 vertex_elems
[VS_I_MV3
].vertex_buffer_index
= 6;
646 vertex_elems
[VS_I_MV3
].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
648 for(i
= 0; i
< VL_NUM_MACROBLOCK_TYPES
; ++i
)
649 init_mbtype_handler(r
, i
, vertex_elems
);
651 r
->vs_const_buf
= pipe_buffer_create
654 PIPE_BIND_CONSTANT_BUFFER
,
655 sizeof(struct vertex_shader_consts
)
662 cleanup_buffers(struct vl_mpeg12_mc_renderer
*r
)
668 pipe_resource_reference(&r
->vs_const_buf
, NULL
);
670 for (i
= 0; i
< 3; ++i
) {
671 pipe_sampler_view_reference(&r
->sampler_views
.all
[i
], NULL
);
672 pipe_resource_reference(&r
->vertex_bufs
.all
[i
].buffer
, NULL
);
673 pipe_resource_reference(&r
->textures
.all
[i
], NULL
);
676 for(i
= 0; i
<VL_NUM_MACROBLOCK_TYPES
; ++i
)
677 cleanup_mbtype_handler(r
, i
);
680 static enum VL_MACROBLOCK_TYPE
681 get_macroblock_type(struct pipe_mpeg12_macroblock
*mb
)
685 switch (mb
->mb_type
) {
686 case PIPE_MPEG12_MACROBLOCK_TYPE_INTRA
:
687 return VL_MACROBLOCK_TYPE_INTRA
;
688 case PIPE_MPEG12_MACROBLOCK_TYPE_FWD
:
689 return mb
->mo_type
== PIPE_MPEG12_MOTION_TYPE_FRAME
?
690 VL_MACROBLOCK_TYPE_FWD_FRAME_PRED
: VL_MACROBLOCK_TYPE_FWD_FIELD_PRED
;
691 case PIPE_MPEG12_MACROBLOCK_TYPE_BKWD
:
692 return mb
->mo_type
== PIPE_MPEG12_MOTION_TYPE_FRAME
?
693 VL_MACROBLOCK_TYPE_BKWD_FRAME_PRED
: VL_MACROBLOCK_TYPE_BKWD_FIELD_PRED
;
694 case PIPE_MPEG12_MACROBLOCK_TYPE_BI
:
695 return mb
->mo_type
== PIPE_MPEG12_MOTION_TYPE_FRAME
?
696 VL_MACROBLOCK_TYPE_BI_FRAME_PRED
: VL_MACROBLOCK_TYPE_BI_FIELD_PRED
;
706 upload_vertex_stream(struct vl_mpeg12_mc_renderer
*r
,
707 unsigned num_macroblocks
[VL_NUM_MACROBLOCK_TYPES
])
710 struct vertex2f
*mv
[4];
713 struct pipe_transfer
*buf_transfer
[7];
718 assert(num_macroblocks
);
720 pos
= (struct quadf
*)pipe_buffer_map
723 r
->vertex_bufs
.individual
.ycbcr
.buffer
,
724 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD
,
728 interlaced
= (float *)pipe_buffer_map
731 r
->vertex_bufs
.individual
.interlaced
.buffer
,
732 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD
,
736 for (i
= 0; i
< 4; ++i
)
737 mv
[i
] = (struct vertex2f
*)pipe_buffer_map
740 r
->vertex_bufs
.individual
.mv
[i
].buffer
,
741 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD
,
745 for (i
= 0; i
< VL_NUM_MACROBLOCK_TYPES
; ++i
) {
746 struct vl_mc_mbtype_handler
*handler
= &r
->mbtype_handlers
[i
];
747 unsigned count
= vl_vb_upload(&handler
->pos
, pos
);
751 memcpy(interlaced
, handler
->interlaced
, sizeof(float) * count
* 4);
752 interlaced
+= count
* 4;
754 for (j
= 0; j
< 4 /* TODO */; ++j
) {
755 memcpy(mv
[j
], handler
->mv
[j
], sizeof(struct vertex2f
) * count
* 4);
759 num_macroblocks
[i
] = count
;
762 pipe_buffer_unmap(r
->pipe
, r
->vertex_bufs
.individual
.ycbcr
.buffer
, buf_transfer
[0]);
763 pipe_buffer_unmap(r
->pipe
, r
->vertex_bufs
.individual
.interlaced
.buffer
, buf_transfer
[1]);
764 for (i
= 0; i
< 4; ++i
)
765 pipe_buffer_unmap(r
->pipe
, r
->vertex_bufs
.individual
.mv
[i
].buffer
, buf_transfer
[i
+ 2]);
768 static struct pipe_sampler_view
769 *find_or_create_sampler_view(struct vl_mpeg12_mc_renderer
*r
, struct pipe_surface
*surface
)
771 struct pipe_sampler_view
*sampler_view
;
775 sampler_view
= (struct pipe_sampler_view
*)util_keymap_lookup(r
->texview_map
, &surface
);
777 struct pipe_sampler_view templat
;
778 boolean added_to_map
;
780 u_sampler_view_default_template(&templat
, surface
->texture
,
781 surface
->texture
->format
);
782 sampler_view
= r
->pipe
->create_sampler_view(r
->pipe
, surface
->texture
,
787 added_to_map
= util_keymap_insert(r
->texview_map
, &surface
,
788 sampler_view
, r
->pipe
);
789 assert(added_to_map
);
796 flush_mbtype_handler(struct vl_mpeg12_mc_renderer
*r
, enum VL_MACROBLOCK_TYPE type
,
797 unsigned vb_start
, unsigned num_macroblocks
)
799 unsigned ref_frames
, mv_per_frame
;
800 struct vl_mc_mbtype_handler
*handler
;
804 ref_frames
= const_mbtype_config
[type
][0];
805 mv_per_frame
= const_mbtype_config
[type
][1];
807 handler
= &r
->mbtype_handlers
[type
];
809 r
->pipe
->set_vertex_buffers(r
->pipe
, 3 + ref_frames
* mv_per_frame
, r
->vertex_bufs
.all
);
810 r
->pipe
->bind_vertex_elements_state(r
->pipe
, handler
->vertex_elems_state
);
812 if(ref_frames
== 2) {
814 r
->textures
.individual
.ref
[0] = r
->past
->texture
;
815 r
->textures
.individual
.ref
[1] = r
->future
->texture
;
816 r
->sampler_views
.individual
.ref
[0] = find_or_create_sampler_view(r
, r
->past
);
817 r
->sampler_views
.individual
.ref
[1] = find_or_create_sampler_view(r
, r
->future
);
819 } else if(ref_frames
== 1) {
821 struct pipe_surface
*ref
;
823 if(type
== VL_MACROBLOCK_TYPE_BKWD_FRAME_PRED
||
824 type
== VL_MACROBLOCK_TYPE_BKWD_FIELD_PRED
)
829 r
->textures
.individual
.ref
[0] = ref
->texture
;
830 r
->sampler_views
.individual
.ref
[0] = find_or_create_sampler_view(r
, ref
);
833 r
->pipe
->set_fragment_sampler_views(r
->pipe
, 3 + ref_frames
, r
->sampler_views
.all
);
834 r
->pipe
->bind_fragment_sampler_states(r
->pipe
, 3 + ref_frames
, r
->samplers
.all
);
835 r
->pipe
->bind_vs_state(r
->pipe
, handler
->vs
);
836 r
->pipe
->bind_fs_state(r
->pipe
, handler
->fs
);
838 util_draw_arrays(r
->pipe
, PIPE_PRIM_QUADS
, vb_start
, num_macroblocks
* 4);
839 return num_macroblocks
* 4;
843 flush(struct vl_mpeg12_mc_renderer
*r
)
845 unsigned num_macroblocks
[VL_NUM_MACROBLOCK_TYPES
] = { 0 };
846 unsigned vb_start
= 0, i
;
849 assert(r
->num_macroblocks
== r
->macroblocks_per_batch
);
851 vl_idct_flush(&r
->idct_y
);
852 vl_idct_flush(&r
->idct_cr
);
853 vl_idct_flush(&r
->idct_cb
);
855 upload_vertex_stream(r
, num_macroblocks
);
857 r
->pipe
->set_framebuffer_state(r
->pipe
, &r
->fb_state
);
858 r
->pipe
->set_viewport_state(r
->pipe
, &r
->viewport
);
860 for (i
= 0; i
< VL_NUM_MACROBLOCK_TYPES
; ++i
) {
861 if (num_macroblocks
[i
] > 0)
862 vb_start
+= flush_mbtype_handler(r
, i
, vb_start
, num_macroblocks
[i
]);
865 r
->pipe
->flush(r
->pipe
, PIPE_FLUSH_RENDER_CACHE
, r
->fence
);
867 r
->num_macroblocks
= 0;
871 update_render_target(struct vl_mpeg12_mc_renderer
*r
)
873 struct pipe_transfer
*buf_transfer
;
874 struct vertex_shader_consts
*vs_consts
;
876 vs_consts
= pipe_buffer_map
878 r
->pipe
, r
->vs_const_buf
,
879 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD
,
883 vs_consts
->norm
.x
= 1.0f
/ r
->surface
->width
;
884 vs_consts
->norm
.y
= 1.0f
/ r
->surface
->height
;
886 pipe_buffer_unmap(r
->pipe
, r
->vs_const_buf
, buf_transfer
);
888 r
->fb_state
.cbufs
[0] = r
->surface
;
890 r
->pipe
->set_constant_buffer(r
->pipe
, PIPE_SHADER_VERTEX
, 0, r
->vs_const_buf
);
894 get_motion_vectors(struct pipe_mpeg12_macroblock
*mb
, struct vertex2f mv
[4])
896 switch (mb
->mb_type
) {
897 case PIPE_MPEG12_MACROBLOCK_TYPE_BI
:
899 if (mb
->mo_type
== PIPE_MPEG12_MOTION_TYPE_FRAME
) {
901 mv
[2].x
= mb
->pmv
[0][1][0];
902 mv
[2].y
= mb
->pmv
[0][1][1];
905 mv
[2].x
= mb
->pmv
[0][1][0];
906 mv
[2].y
= mb
->pmv
[0][1][1] - (mb
->pmv
[0][1][1] % 4);
908 mv
[3].x
= mb
->pmv
[1][1][0];
909 mv
[3].y
= mb
->pmv
[1][1][1] - (mb
->pmv
[1][1][1] % 4);
911 if(mb
->mvfs
[0][1]) mv
[2].y
+= 2;
912 if(!mb
->mvfs
[1][1]) mv
[3].y
-= 2;
917 case PIPE_MPEG12_MACROBLOCK_TYPE_FWD
:
918 case PIPE_MPEG12_MACROBLOCK_TYPE_BKWD
:
920 if (mb
->mb_type
== PIPE_MPEG12_MACROBLOCK_TYPE_BKWD
) {
922 if (mb
->mo_type
== PIPE_MPEG12_MOTION_TYPE_FRAME
) {
923 mv
[0].x
= mb
->pmv
[0][1][0];
924 mv
[0].y
= mb
->pmv
[0][1][1];
927 mv
[0].x
= mb
->pmv
[0][1][0];
928 mv
[0].y
= mb
->pmv
[0][1][1] - (mb
->pmv
[0][1][1] % 4);
930 mv
[1].x
= mb
->pmv
[1][1][0];
931 mv
[1].y
= mb
->pmv
[1][1][1] - (mb
->pmv
[1][1][1] % 4);
933 if(mb
->mvfs
[0][1]) mv
[0].y
+= 2;
934 if(!mb
->mvfs
[1][1]) mv
[1].y
-= 2;
939 if (mb
->mo_type
== PIPE_MPEG12_MOTION_TYPE_FRAME
) {
940 mv
[0].x
= mb
->pmv
[0][0][0];
941 mv
[0].y
= mb
->pmv
[0][0][1];
944 mv
[0].x
= mb
->pmv
[0][0][0];
945 mv
[0].y
= mb
->pmv
[0][0][1] - (mb
->pmv
[0][0][1] % 4);
947 mv
[1].x
= mb
->pmv
[1][0][0];
948 mv
[1].y
= mb
->pmv
[1][0][1] - (mb
->pmv
[1][0][1] % 4);
950 if(mb
->mvfs
[0][0]) mv
[0].y
+= 2;
951 if(!mb
->mvfs
[1][0]) mv
[1].y
-= 2;
961 grab_vectors(struct vl_mpeg12_mc_renderer
*r
,
962 struct pipe_mpeg12_macroblock
*mb
)
964 enum VL_MACROBLOCK_TYPE type
;
965 struct vl_mc_mbtype_handler
*handler
;
966 struct vertex2f mv
[4];
967 unsigned ref_frames
, mv_per_frame
;
973 type
= get_macroblock_type(mb
);
975 ref_frames
= const_mbtype_config
[type
][0];
976 mv_per_frame
= const_mbtype_config
[type
][1];
978 handler
= &r
->mbtype_handlers
[type
];
980 pos
= handler
->pos
.num_blocks
* 4;
981 vl_vb_add_block(&handler
->pos
, false, mb
->mbx
, mb
->mby
);
983 get_motion_vectors(mb
, mv
);
984 for ( i
= 0; i
< 4; ++i
) {
985 handler
->interlaced
[i
+ pos
] = mb
->dct_type
== PIPE_MPEG12_DCT_TYPE_FIELD
? 1.0f
: 0.0f
;
986 for ( j
= 0; j
< 4 /*TODO: ref_frames * mv_per_frame */; ++j
)
987 handler
->mv
[j
][i
+ pos
] = mv
[j
];
992 grab_blocks(struct vl_mpeg12_mc_renderer
*r
, unsigned mbx
, unsigned mby
,
993 enum pipe_mpeg12_dct_type dct_type
, unsigned cbp
, short *blocks
)
1001 for (y
= 0; y
< 2; ++y
) {
1002 for (x
= 0; x
< 2; ++x
, ++tb
) {
1003 bool eb
= !(cbp
& (1 << (5 - tb
)));
1004 vl_idct_add_block(&r
->idct_y
, mbx
* 2 + x
, mby
* 2 + y
, eb
? NULL
: blocks
);
1005 blocks
+= eb
? 0 : BLOCK_WIDTH
* BLOCK_HEIGHT
;
1009 /* TODO: Implement 422, 444 */
1010 assert(r
->chroma_format
== PIPE_VIDEO_CHROMA_FORMAT_420
);
1012 for (tb
= 0; tb
< 2; ++tb
) {
1013 bool eb
= !(cbp
& (1 << (1 - tb
)));
1015 vl_idct_add_block(&r
->idct_cb
, mbx
, mby
, eb
? NULL
: blocks
);
1017 vl_idct_add_block(&r
->idct_cr
, mbx
, mby
, eb
? NULL
: blocks
);
1018 blocks
+= eb
? 0 : BLOCK_WIDTH
* BLOCK_HEIGHT
;
1023 grab_macroblock(struct vl_mpeg12_mc_renderer
*r
,
1024 struct pipe_mpeg12_macroblock
*mb
)
1029 assert(r
->num_macroblocks
< r
->macroblocks_per_batch
);
1031 grab_vectors(r
, mb
);
1032 grab_blocks(r
, mb
->mbx
, mb
->mby
, mb
->dct_type
, mb
->cbp
, mb
->blocks
);
1034 ++r
->num_macroblocks
;
1038 texview_map_delete(const struct keymap
*map
,
1039 const void *key
, void *data
,
1042 struct pipe_sampler_view
*sv
= (struct pipe_sampler_view
*)data
;
1049 pipe_sampler_view_reference(&sv
, NULL
);
1053 vl_mpeg12_mc_renderer_init(struct vl_mpeg12_mc_renderer
*renderer
,
1054 struct pipe_context
*pipe
,
1055 unsigned picture_width
,
1056 unsigned picture_height
,
1057 enum pipe_video_chroma_format chroma_format
,
1058 enum VL_MPEG12_MC_RENDERER_BUFFER_MODE bufmode
,
1061 struct pipe_resource
*idct_matrix
;
1066 /* TODO: Implement other policies */
1067 assert(bufmode
== VL_MPEG12_MC_RENDERER_BUFFER_PICTURE
);
1068 /* TODO: Non-pot buffers untested, probably doesn't work without changes to texcoord generation, vert shader, etc */
1069 assert(pot_buffers
);
1071 memset(renderer
, 0, sizeof(struct vl_mpeg12_mc_renderer
));
1073 renderer
->pipe
= pipe
;
1074 renderer
->picture_width
= picture_width
;
1075 renderer
->picture_height
= picture_height
;
1076 renderer
->chroma_format
= chroma_format
;
1077 renderer
->bufmode
= bufmode
;
1078 renderer
->pot_buffers
= pot_buffers
;
1080 renderer
->texview_map
= util_new_keymap(sizeof(struct pipe_surface
*), -1,
1081 texview_map_delete
);
1082 if (!renderer
->texview_map
)
1085 if (!init_pipe_state(renderer
))
1086 goto error_pipe_state
;
1088 if (!init_buffers(renderer
))
1091 renderer
->surface
= NULL
;
1092 renderer
->past
= NULL
;
1093 renderer
->future
= NULL
;
1094 renderer
->num_macroblocks
= 0;
1096 if(!(idct_matrix
= vl_idct_upload_matrix(pipe
)))
1097 goto error_idct_matrix
;
1099 if(!vl_idct_init(&renderer
->idct_y
, pipe
, renderer
->textures
.individual
.y
, idct_matrix
))
1102 if(!vl_idct_init(&renderer
->idct_cr
, pipe
, renderer
->textures
.individual
.cr
, idct_matrix
))
1105 if(!vl_idct_init(&renderer
->idct_cb
, pipe
, renderer
->textures
.individual
.cb
, idct_matrix
))
1111 vl_idct_cleanup(&renderer
->idct_cr
);
1114 vl_idct_cleanup(&renderer
->idct_y
);
1118 cleanup_buffers(renderer
);
1121 cleanup_pipe_state(renderer
);
1124 util_delete_keymap(renderer
->texview_map
, renderer
->pipe
);
1129 vl_mpeg12_mc_renderer_cleanup(struct vl_mpeg12_mc_renderer
*renderer
)
1133 vl_idct_cleanup(&renderer
->idct_y
);
1134 vl_idct_cleanup(&renderer
->idct_cr
);
1135 vl_idct_cleanup(&renderer
->idct_cb
);
1137 util_delete_keymap(renderer
->texview_map
, renderer
->pipe
);
1138 cleanup_pipe_state(renderer
);
1139 cleanup_buffers(renderer
);
1141 pipe_surface_reference(&renderer
->surface
, NULL
);
1142 pipe_surface_reference(&renderer
->past
, NULL
);
1143 pipe_surface_reference(&renderer
->future
, NULL
);
1147 vl_mpeg12_mc_renderer_render_macroblocks(struct vl_mpeg12_mc_renderer
1149 struct pipe_surface
*surface
,
1150 struct pipe_surface
*past
,
1151 struct pipe_surface
*future
,
1152 unsigned num_macroblocks
,
1153 struct pipe_mpeg12_macroblock
1154 *mpeg12_macroblocks
,
1155 struct pipe_fence_handle
**fence
)
1157 bool new_surface
= false;
1161 assert(num_macroblocks
);
1162 assert(mpeg12_macroblocks
);
1164 if (renderer
->surface
) {
1165 if (surface
!= renderer
->surface
) {
1166 if (renderer
->num_macroblocks
> 0) {
1173 /* If the surface we're rendering hasn't changed the ref frames shouldn't change. */
1174 assert(surface
!= renderer
->surface
|| renderer
->past
== past
);
1175 assert(surface
!= renderer
->surface
|| renderer
->future
== future
);
1181 pipe_surface_reference(&renderer
->surface
, surface
);
1182 pipe_surface_reference(&renderer
->past
, past
);
1183 pipe_surface_reference(&renderer
->future
, future
);
1184 renderer
->fence
= fence
;
1185 update_render_target(renderer
);
1188 while (num_macroblocks
) {
1189 unsigned left_in_batch
= renderer
->macroblocks_per_batch
- renderer
->num_macroblocks
;
1190 unsigned num_to_submit
= MIN2(num_macroblocks
, left_in_batch
);
1193 for (i
= 0; i
< num_to_submit
; ++i
) {
1194 assert(mpeg12_macroblocks
[i
].base
.codec
== PIPE_VIDEO_CODEC_MPEG12
);
1195 grab_macroblock(renderer
, &mpeg12_macroblocks
[i
]);
1198 num_macroblocks
-= num_to_submit
;
1200 if (renderer
->num_macroblocks
== renderer
->macroblocks_per_batch
) {
1202 /* Next time we get this surface it may have new ref frames */
1203 pipe_surface_reference(&renderer
->surface
, NULL
);
1204 pipe_surface_reference(&renderer
->past
, NULL
);
1205 pipe_surface_reference(&renderer
->future
, NULL
);