nouveau: Catch some more leaks.
[mesa.git] / src / gallium / state_trackers / g3dvl / vl_r16snorm_mc_buf.c
1 #define VL_INTERNAL
2 #include "vl_r16snorm_mc_buf.h"
3 #include <assert.h>
4 #include <stdlib.h>
5 #include <pipe/p_context.h>
6 #include <pipe/p_winsys.h>
7 #include <pipe/p_screen.h>
8 #include <pipe/p_state.h>
9 #include <pipe/p_inlines.h>
10 #include <tgsi/tgsi_parse.h>
11 #include <tgsi/tgsi_build.h>
12 #include <util/u_math.h>
13 #include "vl_render.h"
14 #include "vl_shader_build.h"
15 #include "vl_surface.h"
16 #include "vl_util.h"
17 #include "vl_types.h"
18 #include "vl_defs.h"
19
20 const unsigned int DEFAULT_BUF_ALIGNMENT = 256;
21
22 enum vlMacroBlockTypeEx
23 {
24 vlMacroBlockExTypeIntra,
25 vlMacroBlockExTypeFwdPredictedFrame,
26 vlMacroBlockExTypeFwdPredictedField,
27 vlMacroBlockExTypeBkwdPredictedFrame,
28 vlMacroBlockExTypeBkwdPredictedField,
29 vlMacroBlockExTypeBiPredictedFrame,
30 vlMacroBlockExTypeBiPredictedField,
31
32 vlNumMacroBlockExTypes
33 };
34
35 struct vlVertexShaderConsts
36 {
37 struct vlVertex4f denorm;
38 };
39
40 struct vlFragmentShaderConsts
41 {
42 struct vlVertex4f multiplier;
43 struct vlVertex4f div;
44 };
45
46 struct vlR16SnormBufferedMC
47 {
48 struct vlRender base;
49
50 unsigned int picture_width;
51 unsigned int picture_height;
52 enum vlFormat picture_format;
53 unsigned int macroblocks_per_picture;
54
55 struct vlSurface *buffered_surface;
56 struct vlSurface *past_surface;
57 struct vlSurface *future_surface;
58 struct vlVertex2f surface_tex_inv_size;
59 struct vlVertex2f zero_block[3];
60 unsigned int num_macroblocks;
61 struct vlMpeg2MacroBlock *macroblocks;
62 struct pipe_surface *tex_surface[3];
63 short *texels[3];
64
65 struct pipe_context *pipe;
66 struct pipe_viewport_state viewport;
67 struct pipe_framebuffer_state render_target;
68
69 union
70 {
71 void *all[5];
72 struct
73 {
74 void *y;
75 void *cb;
76 void *cr;
77 void *ref[2];
78 };
79 } samplers;
80
81 union
82 {
83 struct pipe_texture *all[5];
84 struct
85 {
86 struct pipe_texture *y;
87 struct pipe_texture *cb;
88 struct pipe_texture *cr;
89 struct pipe_texture *ref[2];
90 };
91 } textures;
92
93 union
94 {
95 struct pipe_vertex_buffer all[3];
96 struct
97 {
98 struct pipe_vertex_buffer ycbcr;
99 struct pipe_vertex_buffer ref[2];
100 };
101 } vertex_bufs;
102
103 void *i_vs, *p_vs[2], *b_vs[2];
104 void *i_fs, *p_fs[2], *b_fs[2];
105 struct pipe_vertex_element vertex_elems[8];
106 struct pipe_constant_buffer vs_const_buf;
107 struct pipe_constant_buffer fs_const_buf;
108 };
109
110 static inline int vlBegin
111 (
112 struct vlRender *render
113 )
114 {
115 assert(render);
116
117 return 0;
118 }
119
120 static inline int vlGrabFrameCodedBlock(short *src, short *dst, unsigned int dst_pitch)
121 {
122 unsigned int y;
123
124 for (y = 0; y < VL_BLOCK_HEIGHT; ++y)
125 memcpy
126 (
127 dst + y * dst_pitch,
128 src + y * VL_BLOCK_WIDTH,
129 VL_BLOCK_WIDTH * 2
130 );
131
132 return 0;
133 }
134
135 static inline int vlGrabFieldCodedBlock(short *src, short *dst, unsigned int dst_pitch)
136 {
137 unsigned int y;
138
139 for (y = 0; y < VL_BLOCK_HEIGHT; ++y)
140 memcpy
141 (
142 dst + y * dst_pitch * 2,
143 src + y * VL_BLOCK_WIDTH,
144 VL_BLOCK_WIDTH * 2
145 );
146
147 return 0;
148 }
149
150 static inline int vlGrabNoBlock(short *dst, unsigned int dst_pitch)
151 {
152 unsigned int y;
153
154 for (y = 0; y < VL_BLOCK_HEIGHT; ++y)
155 memset
156 (
157 dst + y * dst_pitch,
158 0,
159 VL_BLOCK_WIDTH * 2
160 );
161
162 return 0;
163 }
164
165 static inline int vlGrabBlocks
166 (
167 struct vlR16SnormBufferedMC *mc,
168 unsigned int mbx,
169 unsigned int mby,
170 enum vlDCTType dct_type,
171 unsigned int coded_block_pattern,
172 short *blocks
173 )
174 {
175 short *texels;
176 unsigned int tex_pitch;
177 unsigned int x, y, tb = 0, sb = 0;
178 unsigned int mbpx = mbx * VL_MACROBLOCK_WIDTH, mbpy = mby * VL_MACROBLOCK_HEIGHT;
179
180 assert(mc);
181 assert(blocks);
182
183 tex_pitch = mc->tex_surface[0]->stride / mc->tex_surface[0]->block.size;
184 texels = mc->texels[0] + mbpy * tex_pitch + mbpx;
185
186 for (y = 0; y < 2; ++y)
187 {
188 for (x = 0; x < 2; ++x, ++tb)
189 {
190 if ((coded_block_pattern >> (5 - tb)) & 1)
191 {
192 short *cur_block = blocks + sb * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT;
193
194 if (dct_type == vlDCTTypeFrameCoded)
195 {
196 vlGrabFrameCodedBlock
197 (
198 cur_block,
199 texels + y * tex_pitch * VL_BLOCK_HEIGHT + x * VL_BLOCK_WIDTH,
200 tex_pitch
201 );
202 }
203 else
204 {
205 vlGrabFieldCodedBlock
206 (
207 cur_block,
208 texels + y * tex_pitch + x * VL_BLOCK_WIDTH,
209 tex_pitch
210 );
211 }
212
213 ++sb;
214 }
215 else if (mc->zero_block[0].x < 0.0f)
216 {
217 vlGrabNoBlock(texels + y * tex_pitch * VL_BLOCK_HEIGHT + x * VL_BLOCK_WIDTH, tex_pitch);
218
219 mc->zero_block[0].x = (mbpx + x * 8) * mc->surface_tex_inv_size.x;
220 mc->zero_block[0].y = (mbpy + y * 8) * mc->surface_tex_inv_size.y;
221 }
222 }
223 }
224
225 /* TODO: Implement 422, 444 */
226 mbpx >>= 1;
227 mbpy >>= 1;
228
229 for (tb = 0; tb < 2; ++tb)
230 {
231 tex_pitch = mc->tex_surface[tb + 1]->stride / mc->tex_surface[tb + 1]->block.size;
232 texels = mc->texels[tb + 1] + mbpy * tex_pitch + mbpx;
233
234 if ((coded_block_pattern >> (1 - tb)) & 1)
235 {
236 short *cur_block = blocks + sb * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT;
237
238 vlGrabFrameCodedBlock
239 (
240 cur_block,
241 texels,
242 tex_pitch
243 );
244
245 ++sb;
246 }
247 else if (mc->zero_block[tb + 1].x < 0.0f)
248 {
249 vlGrabNoBlock(texels, tex_pitch);
250
251 mc->zero_block[tb + 1].x = (mbpx << 1) * mc->surface_tex_inv_size.x;
252 mc->zero_block[tb + 1].y = (mbpy << 1) * mc->surface_tex_inv_size.y;
253 }
254 }
255
256 return 0;
257 }
258
259 static inline enum vlMacroBlockTypeEx vlGetMacroBlockTypeEx(struct vlMpeg2MacroBlock *mb)
260 {
261 assert(mb);
262
263 switch (mb->mb_type)
264 {
265 case vlMacroBlockTypeIntra:
266 return vlMacroBlockExTypeIntra;
267 case vlMacroBlockTypeFwdPredicted:
268 return mb->mo_type == vlMotionTypeFrame ?
269 vlMacroBlockExTypeFwdPredictedFrame : vlMacroBlockExTypeFwdPredictedField;
270 case vlMacroBlockTypeBkwdPredicted:
271 return mb->mo_type == vlMotionTypeFrame ?
272 vlMacroBlockExTypeBkwdPredictedFrame : vlMacroBlockExTypeBkwdPredictedField;
273 case vlMacroBlockTypeBiPredicted:
274 return mb->mo_type == vlMotionTypeFrame ?
275 vlMacroBlockExTypeBiPredictedFrame : vlMacroBlockExTypeBiPredictedField;
276 default:
277 assert(0);
278 }
279
280 /* Unreachable */
281 return -1;
282 }
283
284 static inline int vlGrabMacroBlock
285 (
286 struct vlR16SnormBufferedMC *mc,
287 struct vlMpeg2MacroBlock *macroblock
288 )
289 {
290 assert(mc);
291 assert(macroblock);
292
293 mc->macroblocks[mc->num_macroblocks].mbx = macroblock->mbx;
294 mc->macroblocks[mc->num_macroblocks].mby = macroblock->mby;
295 mc->macroblocks[mc->num_macroblocks].mb_type = macroblock->mb_type;
296 mc->macroblocks[mc->num_macroblocks].mo_type = macroblock->mo_type;
297 mc->macroblocks[mc->num_macroblocks].dct_type = macroblock->dct_type;
298 mc->macroblocks[mc->num_macroblocks].PMV[0][0][0] = macroblock->PMV[0][0][0];
299 mc->macroblocks[mc->num_macroblocks].PMV[0][0][1] = macroblock->PMV[0][0][1];
300 mc->macroblocks[mc->num_macroblocks].PMV[0][1][0] = macroblock->PMV[0][1][0];
301 mc->macroblocks[mc->num_macroblocks].PMV[0][1][1] = macroblock->PMV[0][1][1];
302 mc->macroblocks[mc->num_macroblocks].PMV[1][0][0] = macroblock->PMV[1][0][0];
303 mc->macroblocks[mc->num_macroblocks].PMV[1][0][1] = macroblock->PMV[1][0][1];
304 mc->macroblocks[mc->num_macroblocks].PMV[1][1][0] = macroblock->PMV[1][1][0];
305 mc->macroblocks[mc->num_macroblocks].PMV[1][1][1] = macroblock->PMV[1][1][1];
306 mc->macroblocks[mc->num_macroblocks].cbp = macroblock->cbp;
307 mc->macroblocks[mc->num_macroblocks].blocks = macroblock->blocks;
308
309 vlGrabBlocks
310 (
311 mc,
312 macroblock->mbx,
313 macroblock->mby,
314 macroblock->dct_type,
315 macroblock->cbp,
316 macroblock->blocks
317 );
318
319 mc->num_macroblocks++;
320
321 return 0;
322 }
323
324 #define SET_BLOCK(vb, cbp, mbx, mby, unitx, unity, ofsx, ofsy, hx, hy, lm, cbm, crm, zb) \
325 (vb)[0].pos.x = (mbx) * (unitx) + (ofsx); (vb)[0].pos.y = (mby) * (unity) + (ofsy); \
326 (vb)[1].pos.x = (mbx) * (unitx) + (ofsx); (vb)[1].pos.y = (mby) * (unity) + (ofsy) + (hy); \
327 (vb)[2].pos.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[2].pos.y = (mby) * (unity) + (ofsy); \
328 (vb)[3].pos.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[3].pos.y = (mby) * (unity) + (ofsy); \
329 (vb)[4].pos.x = (mbx) * (unitx) + (ofsx); (vb)[4].pos.y = (mby) * (unity) + (ofsy) + (hy); \
330 (vb)[5].pos.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[5].pos.y = (mby) * (unity) + (ofsy) + (hy); \
331 \
332 if ((cbp) & (lm)) \
333 { \
334 (vb)[0].luma_tc.x = (mbx) * (unitx) + (ofsx); (vb)[0].luma_tc.y = (mby) * (unity) + (ofsy); \
335 (vb)[1].luma_tc.x = (mbx) * (unitx) + (ofsx); (vb)[1].luma_tc.y = (mby) * (unity) + (ofsy) + (hy); \
336 (vb)[2].luma_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[2].luma_tc.y = (mby) * (unity) + (ofsy); \
337 (vb)[3].luma_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[3].luma_tc.y = (mby) * (unity) + (ofsy); \
338 (vb)[4].luma_tc.x = (mbx) * (unitx) + (ofsx); (vb)[4].luma_tc.y = (mby) * (unity) + (ofsy) + (hy); \
339 (vb)[5].luma_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[5].luma_tc.y = (mby) * (unity) + (ofsy) + (hy); \
340 } \
341 else \
342 { \
343 (vb)[0].luma_tc.x = (zb)[0].x; (vb)[0].luma_tc.y = (zb)[0].y; \
344 (vb)[1].luma_tc.x = (zb)[0].x; (vb)[1].luma_tc.y = (zb)[0].y + (hy); \
345 (vb)[2].luma_tc.x = (zb)[0].x + (hx); (vb)[2].luma_tc.y = (zb)[0].y; \
346 (vb)[3].luma_tc.x = (zb)[0].x + (hx); (vb)[3].luma_tc.y = (zb)[0].y; \
347 (vb)[4].luma_tc.x = (zb)[0].x; (vb)[4].luma_tc.y = (zb)[0].y + (hy); \
348 (vb)[5].luma_tc.x = (zb)[0].x + (hx); (vb)[5].luma_tc.y = (zb)[0].y + (hy); \
349 } \
350 \
351 if ((cbp) & (cbm)) \
352 { \
353 (vb)[0].cb_tc.x = (mbx) * (unitx) + (ofsx); (vb)[0].cb_tc.y = (mby) * (unity) + (ofsy); \
354 (vb)[1].cb_tc.x = (mbx) * (unitx) + (ofsx); (vb)[1].cb_tc.y = (mby) * (unity) + (ofsy) + (hy); \
355 (vb)[2].cb_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[2].cb_tc.y = (mby) * (unity) + (ofsy); \
356 (vb)[3].cb_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[3].cb_tc.y = (mby) * (unity) + (ofsy); \
357 (vb)[4].cb_tc.x = (mbx) * (unitx) + (ofsx); (vb)[4].cb_tc.y = (mby) * (unity) + (ofsy) + (hy); \
358 (vb)[5].cb_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[5].cb_tc.y = (mby) * (unity) + (ofsy) + (hy); \
359 } \
360 else \
361 { \
362 (vb)[0].cb_tc.x = (zb)[1].x; (vb)[0].cb_tc.y = (zb)[1].y; \
363 (vb)[1].cb_tc.x = (zb)[1].x; (vb)[1].cb_tc.y = (zb)[1].y + (hy); \
364 (vb)[2].cb_tc.x = (zb)[1].x + (hx); (vb)[2].cb_tc.y = (zb)[1].y; \
365 (vb)[3].cb_tc.x = (zb)[1].x + (hx); (vb)[3].cb_tc.y = (zb)[1].y; \
366 (vb)[4].cb_tc.x = (zb)[1].x; (vb)[4].cb_tc.y = (zb)[1].y + (hy); \
367 (vb)[5].cb_tc.x = (zb)[1].x + (hx); (vb)[5].cb_tc.y = (zb)[1].y + (hy); \
368 } \
369 \
370 if ((cbp) & (crm)) \
371 { \
372 (vb)[0].cr_tc.x = (mbx) * (unitx) + (ofsx); (vb)[0].cr_tc.y = (mby) * (unity) + (ofsy); \
373 (vb)[1].cr_tc.x = (mbx) * (unitx) + (ofsx); (vb)[1].cr_tc.y = (mby) * (unity) + (ofsy) + (hy); \
374 (vb)[2].cr_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[2].cr_tc.y = (mby) * (unity) + (ofsy); \
375 (vb)[3].cr_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[3].cr_tc.y = (mby) * (unity) + (ofsy); \
376 (vb)[4].cr_tc.x = (mbx) * (unitx) + (ofsx); (vb)[4].cr_tc.y = (mby) * (unity) + (ofsy) + (hy); \
377 (vb)[5].cr_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[5].cr_tc.y = (mby) * (unity) + (ofsy) + (hy); \
378 } \
379 else \
380 { \
381 (vb)[0].cr_tc.x = (zb)[2].x; (vb)[0].cr_tc.y = (zb)[2].y; \
382 (vb)[1].cr_tc.x = (zb)[2].x; (vb)[1].cr_tc.y = (zb)[2].y + (hy); \
383 (vb)[2].cr_tc.x = (zb)[2].x + (hx); (vb)[2].cr_tc.y = (zb)[2].y; \
384 (vb)[3].cr_tc.x = (zb)[2].x + (hx); (vb)[3].cr_tc.y = (zb)[2].y; \
385 (vb)[4].cr_tc.x = (zb)[2].x; (vb)[4].cr_tc.y = (zb)[2].y + (hy); \
386 (vb)[5].cr_tc.x = (zb)[2].x + (hx); (vb)[5].cr_tc.y = (zb)[2].y + (hy); \
387 }
388
389 static inline int vlGrabMacroBlockVB
390 (
391 struct vlR16SnormBufferedMC *mc,
392 struct vlMpeg2MacroBlock *macroblock,
393 unsigned int pos
394 )
395 {
396 struct vlVertex2f mo_vec[2];
397 unsigned int i;
398
399 assert(mc);
400 assert(macroblock);
401
402 switch (macroblock->mb_type)
403 {
404 case vlMacroBlockTypeBiPredicted:
405 {
406 struct vlVertex2f *vb;
407
408 vb = (struct vlVertex2f*)mc->pipe->winsys->buffer_map
409 (
410 mc->pipe->winsys,
411 mc->vertex_bufs.ref[1].buffer,
412 PIPE_BUFFER_USAGE_CPU_WRITE
413 ) + pos * 2 * 24;
414
415 mo_vec[0].x = macroblock->PMV[0][1][0] * 0.5f * mc->surface_tex_inv_size.x;
416 mo_vec[0].y = macroblock->PMV[0][1][1] * 0.5f * mc->surface_tex_inv_size.y;
417
418 if (macroblock->mo_type == vlMotionTypeFrame)
419 {
420 for (i = 0; i < 24 * 2; i += 2)
421 {
422 vb[i].x = mo_vec[0].x;
423 vb[i].y = mo_vec[0].y;
424 }
425 }
426 else
427 {
428 mo_vec[1].x = macroblock->PMV[1][1][0] * 0.5f * mc->surface_tex_inv_size.x;
429 mo_vec[1].y = macroblock->PMV[1][1][1] * 0.5f * mc->surface_tex_inv_size.y;
430
431 for (i = 0; i < 24 * 2; i += 2)
432 {
433 vb[i].x = mo_vec[0].x;
434 vb[i].y = mo_vec[0].y;
435 vb[i + 1].x = mo_vec[1].x;
436 vb[i + 1].y = mo_vec[1].y;
437 }
438 }
439
440 mc->pipe->winsys->buffer_unmap(mc->pipe->winsys, mc->vertex_bufs.ref[1].buffer);
441
442 /* fall-through */
443 }
444 case vlMacroBlockTypeFwdPredicted:
445 case vlMacroBlockTypeBkwdPredicted:
446 {
447 struct vlVertex2f *vb;
448
449 vb = (struct vlVertex2f*)mc->pipe->winsys->buffer_map
450 (
451 mc->pipe->winsys,
452 mc->vertex_bufs.ref[0].buffer,
453 PIPE_BUFFER_USAGE_CPU_WRITE
454 ) + pos * 2 * 24;
455
456 if (macroblock->mb_type == vlMacroBlockTypeBkwdPredicted)
457 {
458 mo_vec[0].x = macroblock->PMV[0][1][0] * 0.5f * mc->surface_tex_inv_size.x;
459 mo_vec[0].y = macroblock->PMV[0][1][1] * 0.5f * mc->surface_tex_inv_size.y;
460
461 if (macroblock->mo_type == vlMotionTypeField)
462 {
463 mo_vec[1].x = macroblock->PMV[1][1][0] * 0.5f * mc->surface_tex_inv_size.x;
464 mo_vec[1].y = macroblock->PMV[1][1][1] * 0.5f * mc->surface_tex_inv_size.y;
465 }
466 }
467 else
468 {
469 mo_vec[0].x = macroblock->PMV[0][0][0] * 0.5f * mc->surface_tex_inv_size.x;
470 mo_vec[0].y = macroblock->PMV[0][0][1] * 0.5f * mc->surface_tex_inv_size.y;
471
472 if (macroblock->mo_type == vlMotionTypeField)
473 {
474 mo_vec[1].x = macroblock->PMV[1][0][0] * 0.5f * mc->surface_tex_inv_size.x;
475 mo_vec[1].y = macroblock->PMV[1][0][1] * 0.5f * mc->surface_tex_inv_size.y;
476 }
477 }
478
479 if (macroblock->mo_type == vlMotionTypeFrame)
480 {
481 for (i = 0; i < 24 * 2; i += 2)
482 {
483 vb[i].x = mo_vec[0].x;
484 vb[i].y = mo_vec[0].y;
485 }
486 }
487 else
488 {
489 for (i = 0; i < 24 * 2; i += 2)
490 {
491 vb[i].x = mo_vec[0].x;
492 vb[i].y = mo_vec[0].y;
493 vb[i + 1].x = mo_vec[1].x;
494 vb[i + 1].y = mo_vec[1].y;
495 }
496 }
497
498 mc->pipe->winsys->buffer_unmap(mc->pipe->winsys, mc->vertex_bufs.ref[0].buffer);
499
500 /* fall-through */
501 }
502 case vlMacroBlockTypeIntra:
503 {
504 const struct vlVertex2f unit =
505 {
506 mc->surface_tex_inv_size.x * VL_MACROBLOCK_WIDTH,
507 mc->surface_tex_inv_size.y * VL_MACROBLOCK_HEIGHT
508 };
509 const struct vlVertex2f half =
510 {
511 mc->surface_tex_inv_size.x * (VL_MACROBLOCK_WIDTH / 2),
512 mc->surface_tex_inv_size.y * (VL_MACROBLOCK_HEIGHT / 2)
513 };
514
515 struct vlMacroBlockVertexStream0
516 {
517 struct vlVertex2f pos;
518 struct vlVertex2f luma_tc;
519 struct vlVertex2f cb_tc;
520 struct vlVertex2f cr_tc;
521 } *vb;
522
523 vb = (struct vlMacroBlockVertexStream0*)mc->pipe->winsys->buffer_map
524 (
525 mc->pipe->winsys,
526 mc->vertex_bufs.ycbcr.buffer,
527 PIPE_BUFFER_USAGE_CPU_WRITE
528 ) + pos * 24;
529
530 SET_BLOCK
531 (
532 vb,
533 macroblock->cbp, macroblock->mbx, macroblock->mby,
534 unit.x, unit.y, 0, 0, half.x, half.y,
535 32, 2, 1, mc->zero_block
536 );
537
538 SET_BLOCK
539 (
540 vb + 6,
541 macroblock->cbp, macroblock->mbx, macroblock->mby,
542 unit.x, unit.y, half.x, 0, half.x, half.y,
543 16, 2, 1, mc->zero_block
544 );
545
546 SET_BLOCK
547 (
548 vb + 12,
549 macroblock->cbp, macroblock->mbx, macroblock->mby,
550 unit.x, unit.y, 0, half.y, half.x, half.y,
551 8, 2, 1, mc->zero_block
552 );
553
554 SET_BLOCK
555 (
556 vb + 18,
557 macroblock->cbp, macroblock->mbx, macroblock->mby,
558 unit.x, unit.y, half.x, half.y, half.x, half.y,
559 4, 2, 1, mc->zero_block
560 );
561
562 mc->pipe->winsys->buffer_unmap(mc->pipe->winsys, mc->vertex_bufs.ycbcr.buffer);
563
564 break;
565 }
566 default:
567 assert(0);
568 }
569
570 return 0;
571 }
572
573 static int vlFlush
574 (
575 struct vlRender *render
576 )
577 {
578 struct vlR16SnormBufferedMC *mc;
579 struct pipe_context *pipe;
580 struct vlVertexShaderConsts *vs_consts;
581 unsigned int num_macroblocks[vlNumMacroBlockExTypes] = {0};
582 unsigned int offset[vlNumMacroBlockExTypes];
583 unsigned int vb_start = 0;
584 unsigned int i;
585
586 assert(render);
587
588 mc = (struct vlR16SnormBufferedMC*)render;
589
590 if (!mc->buffered_surface)
591 return 0;
592
593 if (mc->num_macroblocks < mc->macroblocks_per_picture)
594 return 0;
595
596 pipe = mc->pipe;
597
598 for (i = 0; i < mc->num_macroblocks; ++i)
599 {
600 enum vlMacroBlockTypeEx mb_type_ex = vlGetMacroBlockTypeEx(&mc->macroblocks[i]);
601
602 num_macroblocks[mb_type_ex]++;
603 }
604
605 offset[0] = 0;
606
607 for (i = 1; i < vlNumMacroBlockExTypes; ++i)
608 offset[i] = offset[i - 1] + num_macroblocks[i - 1];
609
610 for (i = 0; i < mc->num_macroblocks; ++i)
611 {
612 enum vlMacroBlockTypeEx mb_type_ex = vlGetMacroBlockTypeEx(&mc->macroblocks[i]);
613
614 vlGrabMacroBlockVB(mc, &mc->macroblocks[i], offset[mb_type_ex]);
615
616 offset[mb_type_ex]++;
617 }
618
619 for (i = 0; i < 3; ++i)
620 {
621 pipe_surface_unmap(mc->tex_surface[i]);
622 mc->pipe->screen->tex_surface_release(mc->pipe->screen, &mc->tex_surface[i]);
623 }
624
625 mc->render_target.cbufs[0] = pipe->screen->get_tex_surface
626 (
627 pipe->screen,
628 mc->buffered_surface->texture,
629 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE
630 );
631
632 pipe->set_framebuffer_state(pipe, &mc->render_target);
633 pipe->set_viewport_state(pipe, &mc->viewport);
634 vs_consts = pipe->winsys->buffer_map
635 (
636 pipe->winsys,
637 mc->vs_const_buf.buffer,
638 PIPE_BUFFER_USAGE_CPU_WRITE
639 );
640
641 vs_consts->denorm.x = mc->buffered_surface->texture->width[0];
642 vs_consts->denorm.y = mc->buffered_surface->texture->height[0];
643
644 pipe->winsys->buffer_unmap(pipe->winsys, mc->vs_const_buf.buffer);
645 pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, &mc->vs_const_buf);
646 pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, &mc->fs_const_buf);
647
648 if (num_macroblocks[vlMacroBlockExTypeIntra] > 0)
649 {
650 pipe->set_vertex_buffers(pipe, 1, mc->vertex_bufs.all);
651 pipe->set_vertex_elements(pipe, 4, mc->vertex_elems);
652 pipe->set_sampler_textures(pipe, 3, mc->textures.all);
653 pipe->bind_sampler_states(pipe, 3, mc->samplers.all);
654 pipe->bind_vs_state(pipe, mc->i_vs);
655 pipe->bind_fs_state(pipe, mc->i_fs);
656
657 pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeIntra] * 24);
658 vb_start += num_macroblocks[vlMacroBlockExTypeIntra] * 24;
659 }
660
661 if (num_macroblocks[vlMacroBlockExTypeFwdPredictedFrame] > 0)
662 {
663 pipe->set_vertex_buffers(pipe, 2, mc->vertex_bufs.all);
664 pipe->set_vertex_elements(pipe, 6, mc->vertex_elems);
665 mc->textures.ref[0] = mc->past_surface->texture;
666 pipe->set_sampler_textures(pipe, 4, mc->textures.all);
667 pipe->bind_sampler_states(pipe, 4, mc->samplers.all);
668 pipe->bind_vs_state(pipe, mc->p_vs[0]);
669 pipe->bind_fs_state(pipe, mc->p_fs[0]);
670
671 pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeFwdPredictedFrame] * 24);
672 vb_start += num_macroblocks[vlMacroBlockExTypeFwdPredictedFrame] * 24;
673 }
674
675 if (num_macroblocks[vlMacroBlockExTypeFwdPredictedField] > 0)
676 {
677 pipe->set_vertex_buffers(pipe, 2, mc->vertex_bufs.all);
678 pipe->set_vertex_elements(pipe, 6, mc->vertex_elems);
679 mc->textures.ref[0] = mc->past_surface->texture;
680 pipe->set_sampler_textures(pipe, 4, mc->textures.all);
681 pipe->bind_sampler_states(pipe, 4, mc->samplers.all);
682 pipe->bind_vs_state(pipe, mc->p_vs[1]);
683 pipe->bind_fs_state(pipe, mc->p_fs[1]);
684
685 pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeFwdPredictedField] * 24);
686 vb_start += num_macroblocks[vlMacroBlockExTypeFwdPredictedField] * 24;
687 }
688
689 if (num_macroblocks[vlMacroBlockExTypeBkwdPredictedFrame] > 0)
690 {
691 pipe->set_vertex_buffers(pipe, 2, mc->vertex_bufs.all);
692 pipe->set_vertex_elements(pipe, 6, mc->vertex_elems);
693 mc->textures.ref[0] = mc->future_surface->texture;
694 pipe->set_sampler_textures(pipe, 4, mc->textures.all);
695 pipe->bind_sampler_states(pipe, 4, mc->samplers.all);
696 pipe->bind_vs_state(pipe, mc->p_vs[0]);
697 pipe->bind_fs_state(pipe, mc->p_fs[0]);
698
699 pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeBkwdPredictedFrame] * 24);
700 vb_start += num_macroblocks[vlMacroBlockExTypeBkwdPredictedFrame] * 24;
701 }
702
703 if (num_macroblocks[vlMacroBlockExTypeBkwdPredictedField] > 0)
704 {
705 pipe->set_vertex_buffers(pipe, 2, mc->vertex_bufs.all);
706 pipe->set_vertex_elements(pipe, 6, mc->vertex_elems);
707 mc->textures.ref[0] = mc->future_surface->texture;
708 pipe->set_sampler_textures(pipe, 4, mc->textures.all);
709 pipe->bind_sampler_states(pipe, 4, mc->samplers.all);
710 pipe->bind_vs_state(pipe, mc->p_vs[1]);
711 pipe->bind_fs_state(pipe, mc->p_fs[1]);
712
713 pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeBkwdPredictedField] * 24);
714 vb_start += num_macroblocks[vlMacroBlockExTypeBkwdPredictedField] * 24;
715 }
716
717 if (num_macroblocks[vlMacroBlockExTypeBiPredictedFrame] > 0)
718 {
719 pipe->set_vertex_buffers(pipe, 3, mc->vertex_bufs.all);
720 pipe->set_vertex_elements(pipe, 8, mc->vertex_elems);
721 mc->textures.ref[0] = mc->past_surface->texture;
722 mc->textures.ref[1] = mc->future_surface->texture;
723 pipe->set_sampler_textures(pipe, 5, mc->textures.all);
724 pipe->bind_sampler_states(pipe, 5, mc->samplers.all);
725 pipe->bind_vs_state(pipe, mc->b_vs[0]);
726 pipe->bind_fs_state(pipe, mc->b_fs[0]);
727
728 pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeBiPredictedFrame] * 24);
729 vb_start += num_macroblocks[vlMacroBlockExTypeBiPredictedFrame] * 24;
730 }
731
732 if (num_macroblocks[vlMacroBlockExTypeBiPredictedField] > 0)
733 {
734 pipe->set_vertex_buffers(pipe, 3, mc->vertex_bufs.all);
735 pipe->set_vertex_elements(pipe, 8, mc->vertex_elems);
736 mc->textures.ref[0] = mc->past_surface->texture;
737 mc->textures.ref[1] = mc->future_surface->texture;
738 pipe->set_sampler_textures(pipe, 5, mc->textures.all);
739 pipe->bind_sampler_states(pipe, 5, mc->samplers.all);
740 pipe->bind_vs_state(pipe, mc->b_vs[1]);
741 pipe->bind_fs_state(pipe, mc->b_fs[1]);
742
743 pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeBiPredictedField] * 24);
744 vb_start += num_macroblocks[vlMacroBlockExTypeBiPredictedField] * 24;
745 }
746
747 pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, &mc->buffered_surface->render_fence);
748 pipe->screen->tex_surface_release(pipe->screen, mc->render_target.cbufs[0]);
749
750 for (i = 0; i < 3; ++i)
751 mc->zero_block[i].x = -1.0f;
752
753 mc->buffered_surface = NULL;
754 mc->num_macroblocks = 0;
755
756 return 0;
757 }
758
759 static int vlRenderMacroBlocksMpeg2R16SnormBuffered
760 (
761 struct vlRender *render,
762 struct vlMpeg2MacroBlockBatch *batch,
763 struct vlSurface *surface
764 )
765 {
766 struct vlR16SnormBufferedMC *mc;
767 bool new_surface = false;
768 unsigned int i;
769
770 assert(render);
771
772 mc = (struct vlR16SnormBufferedMC*)render;
773
774 if (mc->buffered_surface)
775 {
776 if (mc->buffered_surface != surface)
777 {
778 vlFlush(&mc->base);
779 new_surface = true;
780 }
781 }
782 else
783 new_surface = true;
784
785 if (new_surface)
786 {
787 mc->buffered_surface = surface;
788 mc->past_surface = batch->past_surface;
789 mc->future_surface = batch->future_surface;
790 mc->surface_tex_inv_size.x = 1.0f / surface->texture->width[0];
791 mc->surface_tex_inv_size.y = 1.0f / surface->texture->height[0];
792
793 for (i = 0; i < 3; ++i)
794 {
795 mc->tex_surface[i] = mc->pipe->screen->get_tex_surface
796 (
797 mc->pipe->screen,
798 mc->textures.all[i],
799 0, 0, 0, PIPE_BUFFER_USAGE_CPU_WRITE
800 );
801
802 mc->texels[i] = pipe_surface_map(mc->tex_surface[i], PIPE_BUFFER_USAGE_CPU_WRITE);
803 }
804 }
805
806 for (i = 0; i < batch->num_macroblocks; ++i)
807 vlGrabMacroBlock(mc, &batch->macroblocks[i]);
808
809 return 0;
810 }
811
812 static inline int vlEnd
813 (
814 struct vlRender *render
815 )
816 {
817 assert(render);
818
819 return 0;
820 }
821
822 static int vlDestroy
823 (
824 struct vlRender *render
825 )
826 {
827 struct vlR16SnormBufferedMC *mc;
828 struct pipe_context *pipe;
829 unsigned int i;
830
831 assert(render);
832
833 mc = (struct vlR16SnormBufferedMC*)render;
834 pipe = mc->pipe;
835
836 for (i = 0; i < 5; ++i)
837 pipe->delete_sampler_state(pipe, mc->samplers.all[i]);
838
839 for (i = 0; i < 3; ++i)
840 pipe->winsys->buffer_destroy(pipe->winsys, mc->vertex_bufs.all[i].buffer);
841
842 /* Textures 3 & 4 are not created directly, no need to release them here */
843 for (i = 0; i < 3; ++i)
844 pipe_texture_release(&mc->textures.all[i]);
845
846 pipe->delete_vs_state(pipe, mc->i_vs);
847 pipe->delete_fs_state(pipe, mc->i_fs);
848
849 for (i = 0; i < 2; ++i)
850 {
851 pipe->delete_vs_state(pipe, mc->p_vs[i]);
852 pipe->delete_fs_state(pipe, mc->p_fs[i]);
853 pipe->delete_vs_state(pipe, mc->b_vs[i]);
854 pipe->delete_fs_state(pipe, mc->b_fs[i]);
855 }
856
857 pipe->winsys->buffer_destroy(pipe->winsys, mc->vs_const_buf.buffer);
858 pipe->winsys->buffer_destroy(pipe->winsys, mc->fs_const_buf.buffer);
859
860 free(mc->macroblocks);
861 free(mc);
862
863 return 0;
864 }
865
866 /*
867 * Muliplier renormalizes block samples from 16 bits to 12 bits.
868 * Divider is used when calculating Y % 2 for choosing top or bottom
869 * field for P or B macroblocks.
870 * TODO: Use immediates.
871 */
872 static const struct vlFragmentShaderConsts fs_consts =
873 {
874 {32767.0f / 255.0f, 32767.0f / 255.0f, 32767.0f / 255.0f, 0.0f},
875 {0.5f, 2.0f, 0.0f, 0.0f}
876 };
877
878 #include "vl_r16snorm_mc_buf_shaders.inc"
879
880 static int vlCreateDataBufs
881 (
882 struct vlR16SnormBufferedMC *mc
883 )
884 {
885 const unsigned int mbw = align(mc->picture_width, VL_MACROBLOCK_WIDTH) / VL_MACROBLOCK_WIDTH;
886 const unsigned int mbh = align(mc->picture_height, VL_MACROBLOCK_HEIGHT) / VL_MACROBLOCK_HEIGHT;
887
888 struct pipe_context *pipe;
889 unsigned int i;
890
891 assert(mc);
892
893 pipe = mc->pipe;
894 mc->macroblocks_per_picture = mbw * mbh;
895
896 /* Create our vertex buffers */
897 mc->vertex_bufs.ycbcr.pitch = sizeof(struct vlVertex2f) * 4;
898 mc->vertex_bufs.ycbcr.max_index = 24 * mc->macroblocks_per_picture - 1;
899 mc->vertex_bufs.ycbcr.buffer_offset = 0;
900 mc->vertex_bufs.ycbcr.buffer = pipe->winsys->buffer_create
901 (
902 pipe->winsys,
903 DEFAULT_BUF_ALIGNMENT,
904 PIPE_BUFFER_USAGE_VERTEX,
905 sizeof(struct vlVertex2f) * 4 * 24 * mc->macroblocks_per_picture
906 );
907
908 for (i = 1; i < 3; ++i)
909 {
910 mc->vertex_bufs.all[i].pitch = sizeof(struct vlVertex2f) * 2;
911 mc->vertex_bufs.all[i].max_index = 24 * mc->macroblocks_per_picture - 1;
912 mc->vertex_bufs.all[i].buffer_offset = 0;
913 mc->vertex_bufs.all[i].buffer = pipe->winsys->buffer_create
914 (
915 pipe->winsys,
916 DEFAULT_BUF_ALIGNMENT,
917 PIPE_BUFFER_USAGE_VERTEX,
918 sizeof(struct vlVertex2f) * 2 * 24 * mc->macroblocks_per_picture
919 );
920 }
921
922 /* Position element */
923 mc->vertex_elems[0].src_offset = 0;
924 mc->vertex_elems[0].vertex_buffer_index = 0;
925 mc->vertex_elems[0].nr_components = 2;
926 mc->vertex_elems[0].src_format = PIPE_FORMAT_R32G32_FLOAT;
927
928 /* Luma, texcoord element */
929 mc->vertex_elems[1].src_offset = sizeof(struct vlVertex2f);
930 mc->vertex_elems[1].vertex_buffer_index = 0;
931 mc->vertex_elems[1].nr_components = 2;
932 mc->vertex_elems[1].src_format = PIPE_FORMAT_R32G32_FLOAT;
933
934 /* Chroma Cr texcoord element */
935 mc->vertex_elems[2].src_offset = sizeof(struct vlVertex2f) * 2;
936 mc->vertex_elems[2].vertex_buffer_index = 0;
937 mc->vertex_elems[2].nr_components = 2;
938 mc->vertex_elems[2].src_format = PIPE_FORMAT_R32G32_FLOAT;
939
940 /* Chroma Cb texcoord element */
941 mc->vertex_elems[3].src_offset = sizeof(struct vlVertex2f) * 3;
942 mc->vertex_elems[3].vertex_buffer_index = 0;
943 mc->vertex_elems[3].nr_components = 2;
944 mc->vertex_elems[3].src_format = PIPE_FORMAT_R32G32_FLOAT;
945
946 /* First ref surface top field texcoord element */
947 mc->vertex_elems[4].src_offset = 0;
948 mc->vertex_elems[4].vertex_buffer_index = 1;
949 mc->vertex_elems[4].nr_components = 2;
950 mc->vertex_elems[4].src_format = PIPE_FORMAT_R32G32_FLOAT;
951
952 /* First ref surface bottom field texcoord element */
953 mc->vertex_elems[5].src_offset = sizeof(struct vlVertex2f);
954 mc->vertex_elems[5].vertex_buffer_index = 1;
955 mc->vertex_elems[5].nr_components = 2;
956 mc->vertex_elems[5].src_format = PIPE_FORMAT_R32G32_FLOAT;
957
958 /* Second ref surface top field texcoord element */
959 mc->vertex_elems[6].src_offset = 0;
960 mc->vertex_elems[6].vertex_buffer_index = 2;
961 mc->vertex_elems[6].nr_components = 2;
962 mc->vertex_elems[6].src_format = PIPE_FORMAT_R32G32_FLOAT;
963
964 /* Second ref surface bottom field texcoord element */
965 mc->vertex_elems[7].src_offset = sizeof(struct vlVertex2f);
966 mc->vertex_elems[7].vertex_buffer_index = 2;
967 mc->vertex_elems[7].nr_components = 2;
968 mc->vertex_elems[7].src_format = PIPE_FORMAT_R32G32_FLOAT;
969
970 /* Create our constant buffer */
971 mc->vs_const_buf.size = sizeof(struct vlVertexShaderConsts);
972 mc->vs_const_buf.buffer = pipe->winsys->buffer_create
973 (
974 pipe->winsys,
975 DEFAULT_BUF_ALIGNMENT,
976 PIPE_BUFFER_USAGE_CONSTANT,
977 mc->vs_const_buf.size
978 );
979
980 mc->fs_const_buf.size = sizeof(struct vlFragmentShaderConsts);
981 mc->fs_const_buf.buffer = pipe->winsys->buffer_create
982 (
983 pipe->winsys,
984 DEFAULT_BUF_ALIGNMENT,
985 PIPE_BUFFER_USAGE_CONSTANT,
986 mc->fs_const_buf.size
987 );
988
989 memcpy
990 (
991 pipe->winsys->buffer_map(pipe->winsys, mc->fs_const_buf.buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
992 &fs_consts,
993 sizeof(struct vlFragmentShaderConsts)
994 );
995
996 pipe->winsys->buffer_unmap(pipe->winsys, mc->fs_const_buf.buffer);
997
998 mc->macroblocks = malloc(sizeof(struct vlMpeg2MacroBlock) * mc->macroblocks_per_picture);
999
1000 return 0;
1001 }
1002
1003 static int vlInit
1004 (
1005 struct vlR16SnormBufferedMC *mc
1006 )
1007 {
1008 struct pipe_context *pipe;
1009 struct pipe_sampler_state sampler;
1010 struct pipe_texture template;
1011 unsigned int filters[5];
1012 unsigned int i;
1013
1014 assert(mc);
1015
1016 pipe = mc->pipe;
1017
1018 mc->buffered_surface = NULL;
1019 mc->past_surface = NULL;
1020 mc->future_surface = NULL;
1021 for (i = 0; i < 3; ++i)
1022 mc->zero_block[i].x = -1.0f;
1023 mc->num_macroblocks = 0;
1024
1025 /* For MC we render to textures, which are rounded up to nearest POT */
1026 mc->viewport.scale[0] = vlRoundUpPOT(mc->picture_width);
1027 mc->viewport.scale[1] = vlRoundUpPOT(mc->picture_height);
1028 mc->viewport.scale[2] = 1;
1029 mc->viewport.scale[3] = 1;
1030 mc->viewport.translate[0] = 0;
1031 mc->viewport.translate[1] = 0;
1032 mc->viewport.translate[2] = 0;
1033 mc->viewport.translate[3] = 0;
1034
1035 mc->render_target.width = vlRoundUpPOT(mc->picture_width);
1036 mc->render_target.height = vlRoundUpPOT(mc->picture_height);
1037 mc->render_target.num_cbufs = 1;
1038 /* FB for MC stage is a vlSurface created by the user, set at render time */
1039 mc->render_target.zsbuf = NULL;
1040
1041 filters[0] = PIPE_TEX_FILTER_NEAREST;
1042 /* FIXME: Linear causes discoloration around block edges */
1043 filters[1] = /*mc->picture_format == vlFormatYCbCr444 ?*/ PIPE_TEX_FILTER_NEAREST /*: PIPE_TEX_FILTER_LINEAR*/;
1044 filters[2] = /*mc->picture_format == vlFormatYCbCr444 ?*/ PIPE_TEX_FILTER_NEAREST /*: PIPE_TEX_FILTER_LINEAR*/;
1045 filters[3] = PIPE_TEX_FILTER_LINEAR;
1046 filters[4] = PIPE_TEX_FILTER_LINEAR;
1047
1048 for (i = 0; i < 5; ++i)
1049 {
1050 sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
1051 sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
1052 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
1053 sampler.min_img_filter = filters[i];
1054 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
1055 sampler.mag_img_filter = filters[i];
1056 sampler.compare_mode = PIPE_TEX_COMPARE_NONE;
1057 sampler.compare_func = PIPE_FUNC_ALWAYS;
1058 sampler.normalized_coords = 1;
1059 /*sampler.prefilter = ;*/
1060 /*sampler.shadow_ambient = ;*/
1061 /*sampler.lod_bias = ;*/
1062 sampler.min_lod = 0;
1063 /*sampler.max_lod = ;*/
1064 /*sampler.border_color[i] = ;*/
1065 /*sampler.max_anisotropy = ;*/
1066 mc->samplers.all[i] = pipe->create_sampler_state(pipe, &sampler);
1067 }
1068
1069 memset(&template, 0, sizeof(struct pipe_texture));
1070 template.target = PIPE_TEXTURE_2D;
1071 template.format = PIPE_FORMAT_R16_SNORM;
1072 template.last_level = 0;
1073 template.width[0] = vlRoundUpPOT(mc->picture_width);
1074 template.height[0] = vlRoundUpPOT(mc->picture_height);
1075 template.depth[0] = 1;
1076 template.compressed = 0;
1077 pf_get_block(template.format, &template.block);
1078 template.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER | PIPE_TEXTURE_USAGE_DYNAMIC;
1079
1080 mc->textures.y = pipe->screen->texture_create(pipe->screen, &template);
1081
1082 if (mc->picture_format == vlFormatYCbCr420)
1083 {
1084 template.width[0] = vlRoundUpPOT(mc->picture_width / 2);
1085 template.height[0] = vlRoundUpPOT(mc->picture_height / 2);
1086 }
1087 else if (mc->picture_format == vlFormatYCbCr422)
1088 template.height[0] = vlRoundUpPOT(mc->picture_height / 2);
1089
1090 mc->textures.cb = pipe->screen->texture_create(pipe->screen, &template);
1091 mc->textures.cr = pipe->screen->texture_create(pipe->screen, &template);
1092
1093 /* textures.all[3] & textures.all[4] are assigned from vlSurfaces for P and B macroblocks at render time */
1094
1095 vlCreateVertexShaderIMB(mc);
1096 vlCreateFragmentShaderIMB(mc);
1097 vlCreateVertexShaderFramePMB(mc);
1098 vlCreateVertexShaderFieldPMB(mc);
1099 vlCreateFragmentShaderFramePMB(mc);
1100 vlCreateFragmentShaderFieldPMB(mc);
1101 vlCreateVertexShaderFrameBMB(mc);
1102 vlCreateVertexShaderFieldBMB(mc);
1103 vlCreateFragmentShaderFrameBMB(mc);
1104 vlCreateFragmentShaderFieldBMB(mc);
1105 vlCreateDataBufs(mc);
1106
1107 return 0;
1108 }
1109
1110 int vlCreateR16SNormBufferedMC
1111 (
1112 struct pipe_context *pipe,
1113 unsigned int picture_width,
1114 unsigned int picture_height,
1115 enum vlFormat picture_format,
1116 struct vlRender **render
1117 )
1118 {
1119 struct vlR16SnormBufferedMC *mc;
1120
1121 assert(pipe);
1122 assert(render);
1123
1124 mc = calloc(1, sizeof(struct vlR16SnormBufferedMC));
1125
1126 mc->base.vlBegin = &vlBegin;
1127 mc->base.vlRenderMacroBlocksMpeg2 = &vlRenderMacroBlocksMpeg2R16SnormBuffered;
1128 mc->base.vlEnd = &vlEnd;
1129 mc->base.vlFlush = &vlFlush;
1130 mc->base.vlDestroy = &vlDestroy;
1131 mc->pipe = pipe;
1132 mc->picture_width = picture_width;
1133 mc->picture_height = picture_height;
1134
1135 vlInit(mc);
1136
1137 *render = &mc->base;
1138
1139 return 0;
1140 }