2 #include "vl_r16snorm_mc_buf.h"
4 #include <pipe/p_context.h>
5 #include <pipe/p_winsys.h>
6 #include <pipe/p_screen.h>
7 #include <pipe/p_state.h>
8 #include <pipe/p_inlines.h>
9 #include <tgsi/tgsi_parse.h>
10 #include <tgsi/tgsi_build.h>
11 #include <util/u_math.h>
12 #include <util/u_memory.h>
13 #include "vl_render.h"
14 #include "vl_shader_build.h"
15 #include "vl_surface.h"
20 const unsigned int DEFAULT_BUF_ALIGNMENT
= 1;
22 enum vlMacroBlockTypeEx
24 vlMacroBlockExTypeIntra
,
25 vlMacroBlockExTypeFwdPredictedFrame
,
26 vlMacroBlockExTypeFwdPredictedField
,
27 vlMacroBlockExTypeBkwdPredictedFrame
,
28 vlMacroBlockExTypeBkwdPredictedField
,
29 vlMacroBlockExTypeBiPredictedFrame
,
30 vlMacroBlockExTypeBiPredictedField
,
32 vlNumMacroBlockExTypes
35 struct vlVertexShaderConsts
37 struct vlVertex4f denorm
;
40 struct vlFragmentShaderConsts
42 struct vlVertex4f multiplier
;
43 struct vlVertex4f div
;
46 struct vlMacroBlockVertexStream0
48 struct vlVertex2f pos
;
49 struct vlVertex2f luma_tc
;
50 struct vlVertex2f cb_tc
;
51 struct vlVertex2f cr_tc
;
54 struct vlR16SnormBufferedMC
58 unsigned int picture_width
;
59 unsigned int picture_height
;
60 enum vlFormat picture_format
;
61 unsigned int macroblocks_per_picture
;
63 struct vlSurface
*buffered_surface
;
64 struct vlSurface
*past_surface
;
65 struct vlSurface
*future_surface
;
66 struct vlVertex2f surface_tex_inv_size
;
67 struct vlVertex2f zero_block
[3];
68 unsigned int num_macroblocks
;
69 struct vlMpeg2MacroBlock
*macroblocks
;
70 struct pipe_surface
*tex_surface
[3];
73 struct pipe_context
*pipe
;
74 struct pipe_viewport_state viewport
;
75 struct pipe_framebuffer_state render_target
;
91 struct pipe_texture
*all
[5];
94 struct pipe_texture
*y
;
95 struct pipe_texture
*cb
;
96 struct pipe_texture
*cr
;
97 struct pipe_texture
*ref
[2];
103 struct pipe_vertex_buffer all
[3];
106 struct pipe_vertex_buffer ycbcr
;
107 struct pipe_vertex_buffer ref
[2];
111 void *i_vs
, *p_vs
[2], *b_vs
[2];
112 void *i_fs
, *p_fs
[2], *b_fs
[2];
113 struct pipe_vertex_element vertex_elems
[8];
114 struct pipe_constant_buffer vs_const_buf
;
115 struct pipe_constant_buffer fs_const_buf
;
118 static inline int vlBegin
120 struct vlRender
*render
128 static inline int vlGrabFrameCodedBlock(short *src
, short *dst
, unsigned int dst_pitch
)
132 for (y
= 0; y
< VL_BLOCK_HEIGHT
; ++y
)
136 src
+ y
* VL_BLOCK_WIDTH
,
143 static inline int vlGrabFieldCodedBlock(short *src
, short *dst
, unsigned int dst_pitch
)
147 for (y
= 0; y
< VL_BLOCK_HEIGHT
; ++y
)
150 dst
+ y
* dst_pitch
* 2,
151 src
+ y
* VL_BLOCK_WIDTH
,
158 static inline int vlGrabNoBlock(short *dst
, unsigned int dst_pitch
)
162 for (y
= 0; y
< VL_BLOCK_HEIGHT
; ++y
)
173 static inline int vlGrabBlocks
175 struct vlR16SnormBufferedMC
*mc
,
178 enum vlDCTType dct_type
,
179 unsigned int coded_block_pattern
,
184 unsigned int tex_pitch
;
185 unsigned int x
, y
, tb
= 0, sb
= 0;
186 unsigned int mbpx
= mbx
* VL_MACROBLOCK_WIDTH
, mbpy
= mby
* VL_MACROBLOCK_HEIGHT
;
191 tex_pitch
= mc
->tex_surface
[0]->stride
/ mc
->tex_surface
[0]->block
.size
;
192 texels
= mc
->texels
[0] + mbpy
* tex_pitch
+ mbpx
;
194 for (y
= 0; y
< 2; ++y
)
196 for (x
= 0; x
< 2; ++x
, ++tb
)
198 if ((coded_block_pattern
>> (5 - tb
)) & 1)
200 short *cur_block
= blocks
+ sb
* VL_BLOCK_WIDTH
* VL_BLOCK_HEIGHT
;
202 if (dct_type
== vlDCTTypeFrameCoded
)
204 vlGrabFrameCodedBlock
207 texels
+ y
* tex_pitch
* VL_BLOCK_HEIGHT
+ x
* VL_BLOCK_WIDTH
,
213 vlGrabFieldCodedBlock
216 texels
+ y
* tex_pitch
+ x
* VL_BLOCK_WIDTH
,
223 else if (mc
->zero_block
[0].x
< 0.0f
)
225 vlGrabNoBlock(texels
+ y
* tex_pitch
* VL_BLOCK_HEIGHT
+ x
* VL_BLOCK_WIDTH
, tex_pitch
);
227 mc
->zero_block
[0].x
= (mbpx
+ x
* 8) * mc
->surface_tex_inv_size
.x
;
228 mc
->zero_block
[0].y
= (mbpy
+ y
* 8) * mc
->surface_tex_inv_size
.y
;
233 /* TODO: Implement 422, 444 */
237 for (tb
= 0; tb
< 2; ++tb
)
239 tex_pitch
= mc
->tex_surface
[tb
+ 1]->stride
/ mc
->tex_surface
[tb
+ 1]->block
.size
;
240 texels
= mc
->texels
[tb
+ 1] + mbpy
* tex_pitch
+ mbpx
;
242 if ((coded_block_pattern
>> (1 - tb
)) & 1)
244 short *cur_block
= blocks
+ sb
* VL_BLOCK_WIDTH
* VL_BLOCK_HEIGHT
;
246 vlGrabFrameCodedBlock
255 else if (mc
->zero_block
[tb
+ 1].x
< 0.0f
)
257 vlGrabNoBlock(texels
, tex_pitch
);
259 mc
->zero_block
[tb
+ 1].x
= (mbpx
<< 1) * mc
->surface_tex_inv_size
.x
;
260 mc
->zero_block
[tb
+ 1].y
= (mbpy
<< 1) * mc
->surface_tex_inv_size
.y
;
267 static inline enum vlMacroBlockTypeEx
vlGetMacroBlockTypeEx(struct vlMpeg2MacroBlock
*mb
)
273 case vlMacroBlockTypeIntra
:
274 return vlMacroBlockExTypeIntra
;
275 case vlMacroBlockTypeFwdPredicted
:
276 return mb
->mo_type
== vlMotionTypeFrame
?
277 vlMacroBlockExTypeFwdPredictedFrame
: vlMacroBlockExTypeFwdPredictedField
;
278 case vlMacroBlockTypeBkwdPredicted
:
279 return mb
->mo_type
== vlMotionTypeFrame
?
280 vlMacroBlockExTypeBkwdPredictedFrame
: vlMacroBlockExTypeBkwdPredictedField
;
281 case vlMacroBlockTypeBiPredicted
:
282 return mb
->mo_type
== vlMotionTypeFrame
?
283 vlMacroBlockExTypeBiPredictedFrame
: vlMacroBlockExTypeBiPredictedField
;
292 static inline int vlGrabMacroBlock
294 struct vlR16SnormBufferedMC
*mc
,
295 struct vlMpeg2MacroBlock
*macroblock
300 assert(mc
->num_macroblocks
< mc
->macroblocks_per_picture
);
302 mc
->macroblocks
[mc
->num_macroblocks
].mbx
= macroblock
->mbx
;
303 mc
->macroblocks
[mc
->num_macroblocks
].mby
= macroblock
->mby
;
304 mc
->macroblocks
[mc
->num_macroblocks
].mb_type
= macroblock
->mb_type
;
305 mc
->macroblocks
[mc
->num_macroblocks
].mo_type
= macroblock
->mo_type
;
306 mc
->macroblocks
[mc
->num_macroblocks
].dct_type
= macroblock
->dct_type
;
307 mc
->macroblocks
[mc
->num_macroblocks
].PMV
[0][0][0] = macroblock
->PMV
[0][0][0];
308 mc
->macroblocks
[mc
->num_macroblocks
].PMV
[0][0][1] = macroblock
->PMV
[0][0][1];
309 mc
->macroblocks
[mc
->num_macroblocks
].PMV
[0][1][0] = macroblock
->PMV
[0][1][0];
310 mc
->macroblocks
[mc
->num_macroblocks
].PMV
[0][1][1] = macroblock
->PMV
[0][1][1];
311 mc
->macroblocks
[mc
->num_macroblocks
].PMV
[1][0][0] = macroblock
->PMV
[1][0][0];
312 mc
->macroblocks
[mc
->num_macroblocks
].PMV
[1][0][1] = macroblock
->PMV
[1][0][1];
313 mc
->macroblocks
[mc
->num_macroblocks
].PMV
[1][1][0] = macroblock
->PMV
[1][1][0];
314 mc
->macroblocks
[mc
->num_macroblocks
].PMV
[1][1][1] = macroblock
->PMV
[1][1][1];
315 mc
->macroblocks
[mc
->num_macroblocks
].cbp
= macroblock
->cbp
;
316 mc
->macroblocks
[mc
->num_macroblocks
].blocks
= macroblock
->blocks
;
323 macroblock
->dct_type
,
328 mc
->num_macroblocks
++;
333 #define SET_BLOCK(vb, cbp, mbx, mby, unitx, unity, ofsx, ofsy, hx, hy, lm, cbm, crm, zb) \
335 (vb)[0].pos.x = (mbx) * (unitx) + (ofsx); (vb)[0].pos.y = (mby) * (unity) + (ofsy); \
336 (vb)[1].pos.x = (mbx) * (unitx) + (ofsx); (vb)[1].pos.y = (mby) * (unity) + (ofsy) + (hy); \
337 (vb)[2].pos.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[2].pos.y = (mby) * (unity) + (ofsy); \
338 (vb)[3].pos.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[3].pos.y = (mby) * (unity) + (ofsy); \
339 (vb)[4].pos.x = (mbx) * (unitx) + (ofsx); (vb)[4].pos.y = (mby) * (unity) + (ofsy) + (hy); \
340 (vb)[5].pos.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[5].pos.y = (mby) * (unity) + (ofsy) + (hy); \
344 (vb)[0].luma_tc.x = (mbx) * (unitx) + (ofsx); (vb)[0].luma_tc.y = (mby) * (unity) + (ofsy); \
345 (vb)[1].luma_tc.x = (mbx) * (unitx) + (ofsx); (vb)[1].luma_tc.y = (mby) * (unity) + (ofsy) + (hy); \
346 (vb)[2].luma_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[2].luma_tc.y = (mby) * (unity) + (ofsy); \
347 (vb)[3].luma_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[3].luma_tc.y = (mby) * (unity) + (ofsy); \
348 (vb)[4].luma_tc.x = (mbx) * (unitx) + (ofsx); (vb)[4].luma_tc.y = (mby) * (unity) + (ofsy) + (hy); \
349 (vb)[5].luma_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[5].luma_tc.y = (mby) * (unity) + (ofsy) + (hy); \
353 (vb)[0].luma_tc.x = (zb)[0].x; (vb)[0].luma_tc.y = (zb)[0].y; \
354 (vb)[1].luma_tc.x = (zb)[0].x; (vb)[1].luma_tc.y = (zb)[0].y + (hy); \
355 (vb)[2].luma_tc.x = (zb)[0].x + (hx); (vb)[2].luma_tc.y = (zb)[0].y; \
356 (vb)[3].luma_tc.x = (zb)[0].x + (hx); (vb)[3].luma_tc.y = (zb)[0].y; \
357 (vb)[4].luma_tc.x = (zb)[0].x; (vb)[4].luma_tc.y = (zb)[0].y + (hy); \
358 (vb)[5].luma_tc.x = (zb)[0].x + (hx); (vb)[5].luma_tc.y = (zb)[0].y + (hy); \
363 (vb)[0].cb_tc.x = (mbx) * (unitx) + (ofsx); (vb)[0].cb_tc.y = (mby) * (unity) + (ofsy); \
364 (vb)[1].cb_tc.x = (mbx) * (unitx) + (ofsx); (vb)[1].cb_tc.y = (mby) * (unity) + (ofsy) + (hy); \
365 (vb)[2].cb_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[2].cb_tc.y = (mby) * (unity) + (ofsy); \
366 (vb)[3].cb_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[3].cb_tc.y = (mby) * (unity) + (ofsy); \
367 (vb)[4].cb_tc.x = (mbx) * (unitx) + (ofsx); (vb)[4].cb_tc.y = (mby) * (unity) + (ofsy) + (hy); \
368 (vb)[5].cb_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[5].cb_tc.y = (mby) * (unity) + (ofsy) + (hy); \
372 (vb)[0].cb_tc.x = (zb)[1].x; (vb)[0].cb_tc.y = (zb)[1].y; \
373 (vb)[1].cb_tc.x = (zb)[1].x; (vb)[1].cb_tc.y = (zb)[1].y + (hy); \
374 (vb)[2].cb_tc.x = (zb)[1].x + (hx); (vb)[2].cb_tc.y = (zb)[1].y; \
375 (vb)[3].cb_tc.x = (zb)[1].x + (hx); (vb)[3].cb_tc.y = (zb)[1].y; \
376 (vb)[4].cb_tc.x = (zb)[1].x; (vb)[4].cb_tc.y = (zb)[1].y + (hy); \
377 (vb)[5].cb_tc.x = (zb)[1].x + (hx); (vb)[5].cb_tc.y = (zb)[1].y + (hy); \
382 (vb)[0].cr_tc.x = (mbx) * (unitx) + (ofsx); (vb)[0].cr_tc.y = (mby) * (unity) + (ofsy); \
383 (vb)[1].cr_tc.x = (mbx) * (unitx) + (ofsx); (vb)[1].cr_tc.y = (mby) * (unity) + (ofsy) + (hy); \
384 (vb)[2].cr_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[2].cr_tc.y = (mby) * (unity) + (ofsy); \
385 (vb)[3].cr_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[3].cr_tc.y = (mby) * (unity) + (ofsy); \
386 (vb)[4].cr_tc.x = (mbx) * (unitx) + (ofsx); (vb)[4].cr_tc.y = (mby) * (unity) + (ofsy) + (hy); \
387 (vb)[5].cr_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[5].cr_tc.y = (mby) * (unity) + (ofsy) + (hy); \
391 (vb)[0].cr_tc.x = (zb)[2].x; (vb)[0].cr_tc.y = (zb)[2].y; \
392 (vb)[1].cr_tc.x = (zb)[2].x; (vb)[1].cr_tc.y = (zb)[2].y + (hy); \
393 (vb)[2].cr_tc.x = (zb)[2].x + (hx); (vb)[2].cr_tc.y = (zb)[2].y; \
394 (vb)[3].cr_tc.x = (zb)[2].x + (hx); (vb)[3].cr_tc.y = (zb)[2].y; \
395 (vb)[4].cr_tc.x = (zb)[2].x; (vb)[4].cr_tc.y = (zb)[2].y + (hy); \
396 (vb)[5].cr_tc.x = (zb)[2].x + (hx); (vb)[5].cr_tc.y = (zb)[2].y + (hy); \
400 static inline int vlGenMacroblockVerts
402 struct vlR16SnormBufferedMC
*mc
,
403 struct vlMpeg2MacroBlock
*macroblock
,
405 struct vlMacroBlockVertexStream0
*ycbcr_vb
,
406 struct vlVertex2f
**ref_vb
409 struct vlVertex2f mo_vec
[2];
415 assert(pos
< mc
->macroblocks_per_picture
);
417 switch (macroblock
->mb_type
)
419 case vlMacroBlockTypeBiPredicted
:
421 struct vlVertex2f
*vb
;
423 assert(ref_vb
&& ref_vb
[1]);
425 vb
= ref_vb
[1] + pos
* 2 * 24;
427 mo_vec
[0].x
= macroblock
->PMV
[0][1][0] * 0.5f
* mc
->surface_tex_inv_size
.x
;
428 mo_vec
[0].y
= macroblock
->PMV
[0][1][1] * 0.5f
* mc
->surface_tex_inv_size
.y
;
430 if (macroblock
->mo_type
== vlMotionTypeFrame
)
432 for (i
= 0; i
< 24 * 2; i
+= 2)
434 vb
[i
].x
= mo_vec
[0].x
;
435 vb
[i
].y
= mo_vec
[0].y
;
440 mo_vec
[1].x
= macroblock
->PMV
[1][1][0] * 0.5f
* mc
->surface_tex_inv_size
.x
;
441 mo_vec
[1].y
= macroblock
->PMV
[1][1][1] * 0.5f
* mc
->surface_tex_inv_size
.y
;
443 for (i
= 0; i
< 24 * 2; i
+= 2)
445 vb
[i
].x
= mo_vec
[0].x
;
446 vb
[i
].y
= mo_vec
[0].y
;
447 vb
[i
+ 1].x
= mo_vec
[1].x
;
448 vb
[i
+ 1].y
= mo_vec
[1].y
;
454 case vlMacroBlockTypeFwdPredicted
:
455 case vlMacroBlockTypeBkwdPredicted
:
457 struct vlVertex2f
*vb
;
459 assert(ref_vb
&& ref_vb
[0]);
461 vb
= ref_vb
[0] + pos
* 2 * 24;
463 if (macroblock
->mb_type
== vlMacroBlockTypeBkwdPredicted
)
465 mo_vec
[0].x
= macroblock
->PMV
[0][1][0] * 0.5f
* mc
->surface_tex_inv_size
.x
;
466 mo_vec
[0].y
= macroblock
->PMV
[0][1][1] * 0.5f
* mc
->surface_tex_inv_size
.y
;
468 if (macroblock
->mo_type
== vlMotionTypeField
)
470 mo_vec
[1].x
= macroblock
->PMV
[1][1][0] * 0.5f
* mc
->surface_tex_inv_size
.x
;
471 mo_vec
[1].y
= macroblock
->PMV
[1][1][1] * 0.5f
* mc
->surface_tex_inv_size
.y
;
476 mo_vec
[0].x
= macroblock
->PMV
[0][0][0] * 0.5f
* mc
->surface_tex_inv_size
.x
;
477 mo_vec
[0].y
= macroblock
->PMV
[0][0][1] * 0.5f
* mc
->surface_tex_inv_size
.y
;
479 if (macroblock
->mo_type
== vlMotionTypeField
)
481 mo_vec
[1].x
= macroblock
->PMV
[1][0][0] * 0.5f
* mc
->surface_tex_inv_size
.x
;
482 mo_vec
[1].y
= macroblock
->PMV
[1][0][1] * 0.5f
* mc
->surface_tex_inv_size
.y
;
486 if (macroblock
->mo_type
== vlMotionTypeFrame
)
488 for (i
= 0; i
< 24 * 2; i
+= 2)
490 vb
[i
].x
= mo_vec
[0].x
;
491 vb
[i
].y
= mo_vec
[0].y
;
496 for (i
= 0; i
< 24 * 2; i
+= 2)
498 vb
[i
].x
= mo_vec
[0].x
;
499 vb
[i
].y
= mo_vec
[0].y
;
500 vb
[i
+ 1].x
= mo_vec
[1].x
;
501 vb
[i
+ 1].y
= mo_vec
[1].y
;
507 case vlMacroBlockTypeIntra
:
509 const struct vlVertex2f unit
=
511 mc
->surface_tex_inv_size
.x
* VL_MACROBLOCK_WIDTH
,
512 mc
->surface_tex_inv_size
.y
* VL_MACROBLOCK_HEIGHT
514 const struct vlVertex2f half
=
516 mc
->surface_tex_inv_size
.x
* (VL_MACROBLOCK_WIDTH
/ 2),
517 mc
->surface_tex_inv_size
.y
* (VL_MACROBLOCK_HEIGHT
/ 2)
520 struct vlMacroBlockVertexStream0
*vb
;
522 vb
= ycbcr_vb
+ pos
* 24;
527 macroblock
->cbp
, macroblock
->mbx
, macroblock
->mby
,
528 unit
.x
, unit
.y
, 0, 0, half
.x
, half
.y
,
529 32, 2, 1, mc
->zero_block
535 macroblock
->cbp
, macroblock
->mbx
, macroblock
->mby
,
536 unit
.x
, unit
.y
, half
.x
, 0, half
.x
, half
.y
,
537 16, 2, 1, mc
->zero_block
543 macroblock
->cbp
, macroblock
->mbx
, macroblock
->mby
,
544 unit
.x
, unit
.y
, 0, half
.y
, half
.x
, half
.y
,
545 8, 2, 1, mc
->zero_block
551 macroblock
->cbp
, macroblock
->mbx
, macroblock
->mby
,
552 unit
.x
, unit
.y
, half
.x
, half
.y
, half
.x
, half
.y
,
553 4, 2, 1, mc
->zero_block
567 struct vlRender
*render
570 struct vlR16SnormBufferedMC
*mc
;
571 struct pipe_context
*pipe
;
572 struct vlVertexShaderConsts
*vs_consts
;
573 unsigned int num_macroblocks
[vlNumMacroBlockExTypes
] = {0};
574 unsigned int offset
[vlNumMacroBlockExTypes
];
575 unsigned int vb_start
= 0;
580 mc
= (struct vlR16SnormBufferedMC
*)render
;
582 if (!mc
->buffered_surface
)
585 if (mc
->num_macroblocks
< mc
->macroblocks_per_picture
)
588 assert(mc
->num_macroblocks
<= mc
->macroblocks_per_picture
);
592 for (i
= 0; i
< mc
->num_macroblocks
; ++i
)
594 enum vlMacroBlockTypeEx mb_type_ex
= vlGetMacroBlockTypeEx(&mc
->macroblocks
[i
]);
596 num_macroblocks
[mb_type_ex
]++;
601 for (i
= 1; i
< vlNumMacroBlockExTypes
; ++i
)
602 offset
[i
] = offset
[i
- 1] + num_macroblocks
[i
- 1];
605 struct vlMacroBlockVertexStream0
*ycbcr_vb
;
606 struct vlVertex2f
*ref_vb
[2];
608 ycbcr_vb
= (struct vlMacroBlockVertexStream0
*)pipe_buffer_map
611 mc
->vertex_bufs
.ycbcr
.buffer
,
612 PIPE_BUFFER_USAGE_CPU_WRITE
| PIPE_BUFFER_USAGE_DISCARD
615 for (i
= 0; i
< 2; ++i
)
616 ref_vb
[i
] = (struct vlVertex2f
*)pipe_buffer_map
619 mc
->vertex_bufs
.ref
[i
].buffer
,
620 PIPE_BUFFER_USAGE_CPU_WRITE
| PIPE_BUFFER_USAGE_DISCARD
623 for (i
= 0; i
< mc
->num_macroblocks
; ++i
)
625 enum vlMacroBlockTypeEx mb_type_ex
= vlGetMacroBlockTypeEx(&mc
->macroblocks
[i
]);
627 vlGenMacroblockVerts(mc
, &mc
->macroblocks
[i
], offset
[mb_type_ex
], ycbcr_vb
, ref_vb
);
629 offset
[mb_type_ex
]++;
632 pipe_buffer_unmap(pipe
->screen
, mc
->vertex_bufs
.ycbcr
.buffer
);
633 for (i
= 0; i
< 2; ++i
)
634 pipe_buffer_unmap(pipe
->screen
, mc
->vertex_bufs
.ref
[i
].buffer
);
637 for (i
= 0; i
< 3; ++i
)
639 pipe_surface_unmap(mc
->tex_surface
[i
]);
640 pipe_surface_reference(&mc
->tex_surface
[i
], NULL
);
643 mc
->render_target
.cbufs
[0] = pipe
->screen
->get_tex_surface
646 mc
->buffered_surface
->texture
,
647 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ
| PIPE_BUFFER_USAGE_GPU_WRITE
650 pipe
->set_framebuffer_state(pipe
, &mc
->render_target
);
651 pipe
->set_viewport_state(pipe
, &mc
->viewport
);
652 vs_consts
= pipe
->winsys
->buffer_map
655 mc
->vs_const_buf
.buffer
,
656 PIPE_BUFFER_USAGE_CPU_WRITE
| PIPE_BUFFER_USAGE_DISCARD
659 vs_consts
->denorm
.x
= mc
->buffered_surface
->texture
->width
[0];
660 vs_consts
->denorm
.y
= mc
->buffered_surface
->texture
->height
[0];
662 pipe_buffer_unmap(pipe
->screen
, mc
->vs_const_buf
.buffer
);
663 pipe
->set_constant_buffer(pipe
, PIPE_SHADER_VERTEX
, 0, &mc
->vs_const_buf
);
664 pipe
->set_constant_buffer(pipe
, PIPE_SHADER_FRAGMENT
, 0, &mc
->fs_const_buf
);
666 if (num_macroblocks
[vlMacroBlockExTypeIntra
] > 0)
668 pipe
->set_vertex_buffers(pipe
, 1, mc
->vertex_bufs
.all
);
669 pipe
->set_vertex_elements(pipe
, 4, mc
->vertex_elems
);
670 pipe
->set_sampler_textures(pipe
, 3, mc
->textures
.all
);
671 pipe
->bind_sampler_states(pipe
, 3, mc
->samplers
.all
);
672 pipe
->bind_vs_state(pipe
, mc
->i_vs
);
673 pipe
->bind_fs_state(pipe
, mc
->i_fs
);
675 pipe
->draw_arrays(pipe
, PIPE_PRIM_TRIANGLES
, vb_start
, num_macroblocks
[vlMacroBlockExTypeIntra
] * 24);
676 vb_start
+= num_macroblocks
[vlMacroBlockExTypeIntra
] * 24;
679 if (num_macroblocks
[vlMacroBlockExTypeFwdPredictedFrame
] > 0)
681 pipe
->set_vertex_buffers(pipe
, 2, mc
->vertex_bufs
.all
);
682 pipe
->set_vertex_elements(pipe
, 6, mc
->vertex_elems
);
683 mc
->textures
.ref
[0] = mc
->past_surface
->texture
;
684 pipe
->set_sampler_textures(pipe
, 4, mc
->textures
.all
);
685 pipe
->bind_sampler_states(pipe
, 4, mc
->samplers
.all
);
686 pipe
->bind_vs_state(pipe
, mc
->p_vs
[0]);
687 pipe
->bind_fs_state(pipe
, mc
->p_fs
[0]);
689 pipe
->draw_arrays(pipe
, PIPE_PRIM_TRIANGLES
, vb_start
, num_macroblocks
[vlMacroBlockExTypeFwdPredictedFrame
] * 24);
690 vb_start
+= num_macroblocks
[vlMacroBlockExTypeFwdPredictedFrame
] * 24;
693 if (num_macroblocks
[vlMacroBlockExTypeFwdPredictedField
] > 0)
695 pipe
->set_vertex_buffers(pipe
, 2, mc
->vertex_bufs
.all
);
696 pipe
->set_vertex_elements(pipe
, 6, mc
->vertex_elems
);
697 mc
->textures
.ref
[0] = mc
->past_surface
->texture
;
698 pipe
->set_sampler_textures(pipe
, 4, mc
->textures
.all
);
699 pipe
->bind_sampler_states(pipe
, 4, mc
->samplers
.all
);
700 pipe
->bind_vs_state(pipe
, mc
->p_vs
[1]);
701 pipe
->bind_fs_state(pipe
, mc
->p_fs
[1]);
703 pipe
->draw_arrays(pipe
, PIPE_PRIM_TRIANGLES
, vb_start
, num_macroblocks
[vlMacroBlockExTypeFwdPredictedField
] * 24);
704 vb_start
+= num_macroblocks
[vlMacroBlockExTypeFwdPredictedField
] * 24;
707 if (num_macroblocks
[vlMacroBlockExTypeBkwdPredictedFrame
] > 0)
709 pipe
->set_vertex_buffers(pipe
, 2, mc
->vertex_bufs
.all
);
710 pipe
->set_vertex_elements(pipe
, 6, mc
->vertex_elems
);
711 mc
->textures
.ref
[0] = mc
->future_surface
->texture
;
712 pipe
->set_sampler_textures(pipe
, 4, mc
->textures
.all
);
713 pipe
->bind_sampler_states(pipe
, 4, mc
->samplers
.all
);
714 pipe
->bind_vs_state(pipe
, mc
->p_vs
[0]);
715 pipe
->bind_fs_state(pipe
, mc
->p_fs
[0]);
717 pipe
->draw_arrays(pipe
, PIPE_PRIM_TRIANGLES
, vb_start
, num_macroblocks
[vlMacroBlockExTypeBkwdPredictedFrame
] * 24);
718 vb_start
+= num_macroblocks
[vlMacroBlockExTypeBkwdPredictedFrame
] * 24;
721 if (num_macroblocks
[vlMacroBlockExTypeBkwdPredictedField
] > 0)
723 pipe
->set_vertex_buffers(pipe
, 2, mc
->vertex_bufs
.all
);
724 pipe
->set_vertex_elements(pipe
, 6, mc
->vertex_elems
);
725 mc
->textures
.ref
[0] = mc
->future_surface
->texture
;
726 pipe
->set_sampler_textures(pipe
, 4, mc
->textures
.all
);
727 pipe
->bind_sampler_states(pipe
, 4, mc
->samplers
.all
);
728 pipe
->bind_vs_state(pipe
, mc
->p_vs
[1]);
729 pipe
->bind_fs_state(pipe
, mc
->p_fs
[1]);
731 pipe
->draw_arrays(pipe
, PIPE_PRIM_TRIANGLES
, vb_start
, num_macroblocks
[vlMacroBlockExTypeBkwdPredictedField
] * 24);
732 vb_start
+= num_macroblocks
[vlMacroBlockExTypeBkwdPredictedField
] * 24;
735 if (num_macroblocks
[vlMacroBlockExTypeBiPredictedFrame
] > 0)
737 pipe
->set_vertex_buffers(pipe
, 3, mc
->vertex_bufs
.all
);
738 pipe
->set_vertex_elements(pipe
, 8, mc
->vertex_elems
);
739 mc
->textures
.ref
[0] = mc
->past_surface
->texture
;
740 mc
->textures
.ref
[1] = mc
->future_surface
->texture
;
741 pipe
->set_sampler_textures(pipe
, 5, mc
->textures
.all
);
742 pipe
->bind_sampler_states(pipe
, 5, mc
->samplers
.all
);
743 pipe
->bind_vs_state(pipe
, mc
->b_vs
[0]);
744 pipe
->bind_fs_state(pipe
, mc
->b_fs
[0]);
746 pipe
->draw_arrays(pipe
, PIPE_PRIM_TRIANGLES
, vb_start
, num_macroblocks
[vlMacroBlockExTypeBiPredictedFrame
] * 24);
747 vb_start
+= num_macroblocks
[vlMacroBlockExTypeBiPredictedFrame
] * 24;
750 if (num_macroblocks
[vlMacroBlockExTypeBiPredictedField
] > 0)
752 pipe
->set_vertex_buffers(pipe
, 3, mc
->vertex_bufs
.all
);
753 pipe
->set_vertex_elements(pipe
, 8, mc
->vertex_elems
);
754 mc
->textures
.ref
[0] = mc
->past_surface
->texture
;
755 mc
->textures
.ref
[1] = mc
->future_surface
->texture
;
756 pipe
->set_sampler_textures(pipe
, 5, mc
->textures
.all
);
757 pipe
->bind_sampler_states(pipe
, 5, mc
->samplers
.all
);
758 pipe
->bind_vs_state(pipe
, mc
->b_vs
[1]);
759 pipe
->bind_fs_state(pipe
, mc
->b_fs
[1]);
761 pipe
->draw_arrays(pipe
, PIPE_PRIM_TRIANGLES
, vb_start
, num_macroblocks
[vlMacroBlockExTypeBiPredictedField
] * 24);
762 vb_start
+= num_macroblocks
[vlMacroBlockExTypeBiPredictedField
] * 24;
765 pipe
->flush(pipe
, PIPE_FLUSH_RENDER_CACHE
, &mc
->buffered_surface
->render_fence
);
766 pipe_surface_reference(&mc
->render_target
.cbufs
[0], NULL
);
768 for (i
= 0; i
< 3; ++i
)
769 mc
->zero_block
[i
].x
= -1.0f
;
771 mc
->buffered_surface
= NULL
;
772 mc
->num_macroblocks
= 0;
777 static int vlRenderMacroBlocksMpeg2R16SnormBuffered
779 struct vlRender
*render
,
780 struct vlMpeg2MacroBlockBatch
*batch
,
781 struct vlSurface
*surface
784 struct vlR16SnormBufferedMC
*mc
;
785 bool new_surface
= false;
790 mc
= (struct vlR16SnormBufferedMC
*)render
;
792 if (mc
->buffered_surface
)
794 if (mc
->buffered_surface
!= surface
)
805 mc
->buffered_surface
= surface
;
806 mc
->past_surface
= batch
->past_surface
;
807 mc
->future_surface
= batch
->future_surface
;
808 mc
->surface_tex_inv_size
.x
= 1.0f
/ surface
->texture
->width
[0];
809 mc
->surface_tex_inv_size
.y
= 1.0f
/ surface
->texture
->height
[0];
811 for (i
= 0; i
< 3; ++i
)
813 mc
->tex_surface
[i
] = mc
->pipe
->screen
->get_tex_surface
817 0, 0, 0, PIPE_BUFFER_USAGE_CPU_WRITE
| PIPE_BUFFER_USAGE_DISCARD
820 mc
->texels
[i
] = pipe_surface_map(mc
->tex_surface
[i
], PIPE_BUFFER_USAGE_CPU_WRITE
| PIPE_BUFFER_USAGE_DISCARD
);
824 for (i
= 0; i
< batch
->num_macroblocks
; ++i
)
825 vlGrabMacroBlock(mc
, &batch
->macroblocks
[i
]);
830 static inline int vlEnd
832 struct vlRender
*render
842 struct vlRender
*render
845 struct vlR16SnormBufferedMC
*mc
;
846 struct pipe_context
*pipe
;
851 mc
= (struct vlR16SnormBufferedMC
*)render
;
854 for (i
= 0; i
< 5; ++i
)
855 pipe
->delete_sampler_state(pipe
, mc
->samplers
.all
[i
]);
857 for (i
= 0; i
< 3; ++i
)
858 pipe_buffer_reference(pipe
->screen
, &mc
->vertex_bufs
.all
[i
].buffer
, NULL
);
860 /* Textures 3 & 4 are not created directly, no need to release them here */
861 for (i
= 0; i
< 3; ++i
)
862 pipe_texture_reference(&mc
->textures
.all
[i
], NULL
);
864 pipe
->delete_vs_state(pipe
, mc
->i_vs
);
865 pipe
->delete_fs_state(pipe
, mc
->i_fs
);
867 for (i
= 0; i
< 2; ++i
)
869 pipe
->delete_vs_state(pipe
, mc
->p_vs
[i
]);
870 pipe
->delete_fs_state(pipe
, mc
->p_fs
[i
]);
871 pipe
->delete_vs_state(pipe
, mc
->b_vs
[i
]);
872 pipe
->delete_fs_state(pipe
, mc
->b_fs
[i
]);
875 pipe_buffer_reference(pipe
->screen
, &mc
->vs_const_buf
.buffer
, NULL
);
876 pipe_buffer_reference(pipe
->screen
, &mc
->fs_const_buf
.buffer
, NULL
);
878 FREE(mc
->macroblocks
);
885 * Muliplier renormalizes block samples from 16 bits to 12 bits.
886 * Divider is used when calculating Y % 2 for choosing top or bottom
887 * field for P or B macroblocks.
888 * TODO: Use immediates.
890 static const struct vlFragmentShaderConsts fs_consts
=
892 {32767.0f
/ 255.0f
, 32767.0f
/ 255.0f
, 32767.0f
/ 255.0f
, 0.0f
},
893 {0.5f
, 2.0f
, 0.0f
, 0.0f
}
896 #include "vl_r16snorm_mc_buf_shaders.inc"
898 static int vlCreateDataBufs
900 struct vlR16SnormBufferedMC
*mc
903 const unsigned int mbw
= align(mc
->picture_width
, VL_MACROBLOCK_WIDTH
) / VL_MACROBLOCK_WIDTH
;
904 const unsigned int mbh
= align(mc
->picture_height
, VL_MACROBLOCK_HEIGHT
) / VL_MACROBLOCK_HEIGHT
;
906 struct pipe_context
*pipe
;
912 mc
->macroblocks_per_picture
= mbw
* mbh
;
914 /* Create our vertex buffers */
915 mc
->vertex_bufs
.ycbcr
.pitch
= sizeof(struct vlVertex2f
) * 4;
916 mc
->vertex_bufs
.ycbcr
.max_index
= 24 * mc
->macroblocks_per_picture
- 1;
917 mc
->vertex_bufs
.ycbcr
.buffer_offset
= 0;
918 mc
->vertex_bufs
.ycbcr
.buffer
= pipe_buffer_create
921 DEFAULT_BUF_ALIGNMENT
,
922 PIPE_BUFFER_USAGE_VERTEX
| PIPE_BUFFER_USAGE_DISCARD
,
923 sizeof(struct vlVertex2f
) * 4 * 24 * mc
->macroblocks_per_picture
926 for (i
= 1; i
< 3; ++i
)
928 mc
->vertex_bufs
.all
[i
].pitch
= sizeof(struct vlVertex2f
) * 2;
929 mc
->vertex_bufs
.all
[i
].max_index
= 24 * mc
->macroblocks_per_picture
- 1;
930 mc
->vertex_bufs
.all
[i
].buffer_offset
= 0;
931 mc
->vertex_bufs
.all
[i
].buffer
= pipe_buffer_create
934 DEFAULT_BUF_ALIGNMENT
,
935 PIPE_BUFFER_USAGE_VERTEX
| PIPE_BUFFER_USAGE_DISCARD
,
936 sizeof(struct vlVertex2f
) * 2 * 24 * mc
->macroblocks_per_picture
940 /* Position element */
941 mc
->vertex_elems
[0].src_offset
= 0;
942 mc
->vertex_elems
[0].vertex_buffer_index
= 0;
943 mc
->vertex_elems
[0].nr_components
= 2;
944 mc
->vertex_elems
[0].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
946 /* Luma, texcoord element */
947 mc
->vertex_elems
[1].src_offset
= sizeof(struct vlVertex2f
);
948 mc
->vertex_elems
[1].vertex_buffer_index
= 0;
949 mc
->vertex_elems
[1].nr_components
= 2;
950 mc
->vertex_elems
[1].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
952 /* Chroma Cr texcoord element */
953 mc
->vertex_elems
[2].src_offset
= sizeof(struct vlVertex2f
) * 2;
954 mc
->vertex_elems
[2].vertex_buffer_index
= 0;
955 mc
->vertex_elems
[2].nr_components
= 2;
956 mc
->vertex_elems
[2].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
958 /* Chroma Cb texcoord element */
959 mc
->vertex_elems
[3].src_offset
= sizeof(struct vlVertex2f
) * 3;
960 mc
->vertex_elems
[3].vertex_buffer_index
= 0;
961 mc
->vertex_elems
[3].nr_components
= 2;
962 mc
->vertex_elems
[3].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
964 /* First ref surface top field texcoord element */
965 mc
->vertex_elems
[4].src_offset
= 0;
966 mc
->vertex_elems
[4].vertex_buffer_index
= 1;
967 mc
->vertex_elems
[4].nr_components
= 2;
968 mc
->vertex_elems
[4].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
970 /* First ref surface bottom field texcoord element */
971 mc
->vertex_elems
[5].src_offset
= sizeof(struct vlVertex2f
);
972 mc
->vertex_elems
[5].vertex_buffer_index
= 1;
973 mc
->vertex_elems
[5].nr_components
= 2;
974 mc
->vertex_elems
[5].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
976 /* Second ref surface top field texcoord element */
977 mc
->vertex_elems
[6].src_offset
= 0;
978 mc
->vertex_elems
[6].vertex_buffer_index
= 2;
979 mc
->vertex_elems
[6].nr_components
= 2;
980 mc
->vertex_elems
[6].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
982 /* Second ref surface bottom field texcoord element */
983 mc
->vertex_elems
[7].src_offset
= sizeof(struct vlVertex2f
);
984 mc
->vertex_elems
[7].vertex_buffer_index
= 2;
985 mc
->vertex_elems
[7].nr_components
= 2;
986 mc
->vertex_elems
[7].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
988 /* Create our constant buffer */
989 mc
->vs_const_buf
.size
= sizeof(struct vlVertexShaderConsts
);
990 mc
->vs_const_buf
.buffer
= pipe_buffer_create
993 DEFAULT_BUF_ALIGNMENT
,
994 PIPE_BUFFER_USAGE_CONSTANT
| PIPE_BUFFER_USAGE_DISCARD
,
995 mc
->vs_const_buf
.size
998 mc
->fs_const_buf
.size
= sizeof(struct vlFragmentShaderConsts
);
999 mc
->fs_const_buf
.buffer
= pipe_buffer_create
1002 DEFAULT_BUF_ALIGNMENT
,
1003 PIPE_BUFFER_USAGE_CONSTANT
,
1004 mc
->fs_const_buf
.size
1009 pipe_buffer_map(pipe
->screen
, mc
->fs_const_buf
.buffer
, PIPE_BUFFER_USAGE_CPU_WRITE
),
1011 sizeof(struct vlFragmentShaderConsts
)
1014 pipe_buffer_unmap(pipe
->screen
, mc
->fs_const_buf
.buffer
);
1016 mc
->macroblocks
= MALLOC(sizeof(struct vlMpeg2MacroBlock
) * mc
->macroblocks_per_picture
);
1023 struct vlR16SnormBufferedMC
*mc
1026 struct pipe_context
*pipe
;
1027 struct pipe_sampler_state sampler
;
1028 struct pipe_texture
template;
1029 unsigned int filters
[5];
1036 mc
->buffered_surface
= NULL
;
1037 mc
->past_surface
= NULL
;
1038 mc
->future_surface
= NULL
;
1039 for (i
= 0; i
< 3; ++i
)
1040 mc
->zero_block
[i
].x
= -1.0f
;
1041 mc
->num_macroblocks
= 0;
1043 /* For MC we render to textures, which are rounded up to nearest POT */
1044 mc
->viewport
.scale
[0] = vlRoundUpPOT(mc
->picture_width
);
1045 mc
->viewport
.scale
[1] = vlRoundUpPOT(mc
->picture_height
);
1046 mc
->viewport
.scale
[2] = 1;
1047 mc
->viewport
.scale
[3] = 1;
1048 mc
->viewport
.translate
[0] = 0;
1049 mc
->viewport
.translate
[1] = 0;
1050 mc
->viewport
.translate
[2] = 0;
1051 mc
->viewport
.translate
[3] = 0;
1053 mc
->render_target
.width
= vlRoundUpPOT(mc
->picture_width
);
1054 mc
->render_target
.height
= vlRoundUpPOT(mc
->picture_height
);
1055 mc
->render_target
.num_cbufs
= 1;
1056 /* FB for MC stage is a vlSurface created by the user, set at render time */
1057 mc
->render_target
.zsbuf
= NULL
;
1059 filters
[0] = PIPE_TEX_FILTER_NEAREST
;
1060 /* FIXME: Linear causes discoloration around block edges */
1061 filters
[1] = /*mc->picture_format == vlFormatYCbCr444 ?*/ PIPE_TEX_FILTER_NEAREST
/*: PIPE_TEX_FILTER_LINEAR*/;
1062 filters
[2] = /*mc->picture_format == vlFormatYCbCr444 ?*/ PIPE_TEX_FILTER_NEAREST
/*: PIPE_TEX_FILTER_LINEAR*/;
1063 filters
[3] = PIPE_TEX_FILTER_LINEAR
;
1064 filters
[4] = PIPE_TEX_FILTER_LINEAR
;
1066 for (i
= 0; i
< 5; ++i
)
1068 sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
1069 sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
1070 sampler
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
1071 sampler
.min_img_filter
= filters
[i
];
1072 sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
1073 sampler
.mag_img_filter
= filters
[i
];
1074 sampler
.compare_mode
= PIPE_TEX_COMPARE_NONE
;
1075 sampler
.compare_func
= PIPE_FUNC_ALWAYS
;
1076 sampler
.normalized_coords
= 1;
1077 /*sampler.prefilter = ;*/
1078 /*sampler.shadow_ambient = ;*/
1079 /*sampler.lod_bias = ;*/
1080 sampler
.min_lod
= 0;
1081 /*sampler.max_lod = ;*/
1082 /*sampler.border_color[i] = ;*/
1083 /*sampler.max_anisotropy = ;*/
1084 mc
->samplers
.all
[i
] = pipe
->create_sampler_state(pipe
, &sampler
);
1087 memset(&template, 0, sizeof(struct pipe_texture
));
1088 template.target
= PIPE_TEXTURE_2D
;
1089 template.format
= PIPE_FORMAT_R16_SNORM
;
1090 template.last_level
= 0;
1091 template.width
[0] = vlRoundUpPOT(mc
->picture_width
);
1092 template.height
[0] = vlRoundUpPOT(mc
->picture_height
);
1093 template.depth
[0] = 1;
1094 template.compressed
= 0;
1095 pf_get_block(template.format
, &template.block
);
1096 template.tex_usage
= PIPE_TEXTURE_USAGE_SAMPLER
| PIPE_TEXTURE_USAGE_DYNAMIC
;
1098 mc
->textures
.y
= pipe
->screen
->texture_create(pipe
->screen
, &template);
1100 if (mc
->picture_format
== vlFormatYCbCr420
)
1102 template.width
[0] = vlRoundUpPOT(mc
->picture_width
/ 2);
1103 template.height
[0] = vlRoundUpPOT(mc
->picture_height
/ 2);
1105 else if (mc
->picture_format
== vlFormatYCbCr422
)
1106 template.height
[0] = vlRoundUpPOT(mc
->picture_height
/ 2);
1108 mc
->textures
.cb
= pipe
->screen
->texture_create(pipe
->screen
, &template);
1109 mc
->textures
.cr
= pipe
->screen
->texture_create(pipe
->screen
, &template);
1111 /* textures.all[3] & textures.all[4] are assigned from vlSurfaces for P and B macroblocks at render time */
1113 vlCreateVertexShaderIMB(mc
);
1114 vlCreateFragmentShaderIMB(mc
);
1115 vlCreateVertexShaderFramePMB(mc
);
1116 vlCreateVertexShaderFieldPMB(mc
);
1117 vlCreateFragmentShaderFramePMB(mc
);
1118 vlCreateFragmentShaderFieldPMB(mc
);
1119 vlCreateVertexShaderFrameBMB(mc
);
1120 vlCreateVertexShaderFieldBMB(mc
);
1121 vlCreateFragmentShaderFrameBMB(mc
);
1122 vlCreateFragmentShaderFieldBMB(mc
);
1123 vlCreateDataBufs(mc
);
1128 int vlCreateR16SNormBufferedMC
1130 struct pipe_context
*pipe
,
1131 unsigned int picture_width
,
1132 unsigned int picture_height
,
1133 enum vlFormat picture_format
,
1134 struct vlRender
**render
1137 struct vlR16SnormBufferedMC
*mc
;
1142 mc
= CALLOC_STRUCT(vlR16SnormBufferedMC
);
1144 mc
->base
.vlBegin
= &vlBegin
;
1145 mc
->base
.vlRenderMacroBlocksMpeg2
= &vlRenderMacroBlocksMpeg2R16SnormBuffered
;
1146 mc
->base
.vlEnd
= &vlEnd
;
1147 mc
->base
.vlFlush
= &vlFlush
;
1148 mc
->base
.vlDestroy
= &vlDestroy
;
1150 mc
->picture_width
= picture_width
;
1151 mc
->picture_height
= picture_height
;
1155 *render
= &mc
->base
;