g3dvl: Some cleanups.
[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 <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"
16 #include "vl_util.h"
17 #include "vl_types.h"
18 #include "vl_defs.h"
19
20 const unsigned int DEFAULT_BUF_ALIGNMENT = 1;
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 vlMacroBlockVertexStream0
47 {
48 struct vlVertex2f pos;
49 struct vlVertex2f luma_tc;
50 struct vlVertex2f cb_tc;
51 struct vlVertex2f cr_tc;
52 };
53
54 struct vlR16SnormBufferedMC
55 {
56 struct vlRender base;
57
58 unsigned int picture_width;
59 unsigned int picture_height;
60 enum vlFormat picture_format;
61 unsigned int macroblocks_per_picture;
62
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];
71 short *texels[3];
72
73 struct pipe_context *pipe;
74 struct pipe_viewport_state viewport;
75 struct pipe_framebuffer_state render_target;
76
77 union
78 {
79 void *all[5];
80 struct
81 {
82 void *y;
83 void *cb;
84 void *cr;
85 void *ref[2];
86 };
87 } samplers;
88
89 union
90 {
91 struct pipe_texture *all[5];
92 struct
93 {
94 struct pipe_texture *y;
95 struct pipe_texture *cb;
96 struct pipe_texture *cr;
97 struct pipe_texture *ref[2];
98 };
99 } textures;
100
101 union
102 {
103 struct pipe_vertex_buffer all[3];
104 struct
105 {
106 struct pipe_vertex_buffer ycbcr;
107 struct pipe_vertex_buffer ref[2];
108 };
109 } vertex_bufs;
110
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;
116 };
117
118 static inline int vlBegin
119 (
120 struct vlRender *render
121 )
122 {
123 assert(render);
124
125 return 0;
126 }
127
128 static inline int vlGrabFrameCodedBlock(short *src, short *dst, unsigned int dst_pitch)
129 {
130 unsigned int y;
131
132 for (y = 0; y < VL_BLOCK_HEIGHT; ++y)
133 memcpy
134 (
135 dst + y * dst_pitch,
136 src + y * VL_BLOCK_WIDTH,
137 VL_BLOCK_WIDTH * 2
138 );
139
140 return 0;
141 }
142
143 static inline int vlGrabFieldCodedBlock(short *src, short *dst, unsigned int dst_pitch)
144 {
145 unsigned int y;
146
147 for (y = 0; y < VL_BLOCK_HEIGHT; ++y)
148 memcpy
149 (
150 dst + y * dst_pitch * 2,
151 src + y * VL_BLOCK_WIDTH,
152 VL_BLOCK_WIDTH * 2
153 );
154
155 return 0;
156 }
157
158 static inline int vlGrabNoBlock(short *dst, unsigned int dst_pitch)
159 {
160 unsigned int y;
161
162 for (y = 0; y < VL_BLOCK_HEIGHT; ++y)
163 memset
164 (
165 dst + y * dst_pitch,
166 0,
167 VL_BLOCK_WIDTH * 2
168 );
169
170 return 0;
171 }
172
173 static inline int vlGrabBlocks
174 (
175 struct vlR16SnormBufferedMC *mc,
176 unsigned int mbx,
177 unsigned int mby,
178 enum vlDCTType dct_type,
179 unsigned int coded_block_pattern,
180 short *blocks
181 )
182 {
183 short *texels;
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;
187
188 assert(mc);
189 assert(blocks);
190
191 tex_pitch = mc->tex_surface[0]->stride / mc->tex_surface[0]->block.size;
192 texels = mc->texels[0] + mbpy * tex_pitch + mbpx;
193
194 for (y = 0; y < 2; ++y)
195 {
196 for (x = 0; x < 2; ++x, ++tb)
197 {
198 if ((coded_block_pattern >> (5 - tb)) & 1)
199 {
200 short *cur_block = blocks + sb * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT;
201
202 if (dct_type == vlDCTTypeFrameCoded)
203 {
204 vlGrabFrameCodedBlock
205 (
206 cur_block,
207 texels + y * tex_pitch * VL_BLOCK_HEIGHT + x * VL_BLOCK_WIDTH,
208 tex_pitch
209 );
210 }
211 else
212 {
213 vlGrabFieldCodedBlock
214 (
215 cur_block,
216 texels + y * tex_pitch + x * VL_BLOCK_WIDTH,
217 tex_pitch
218 );
219 }
220
221 ++sb;
222 }
223 else if (mc->zero_block[0].x < 0.0f)
224 {
225 vlGrabNoBlock(texels + y * tex_pitch * VL_BLOCK_HEIGHT + x * VL_BLOCK_WIDTH, tex_pitch);
226
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;
229 }
230 }
231 }
232
233 /* TODO: Implement 422, 444 */
234 mbpx >>= 1;
235 mbpy >>= 1;
236
237 for (tb = 0; tb < 2; ++tb)
238 {
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;
241
242 if ((coded_block_pattern >> (1 - tb)) & 1)
243 {
244 short *cur_block = blocks + sb * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT;
245
246 vlGrabFrameCodedBlock
247 (
248 cur_block,
249 texels,
250 tex_pitch
251 );
252
253 ++sb;
254 }
255 else if (mc->zero_block[tb + 1].x < 0.0f)
256 {
257 vlGrabNoBlock(texels, tex_pitch);
258
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;
261 }
262 }
263
264 return 0;
265 }
266
267 static inline enum vlMacroBlockTypeEx vlGetMacroBlockTypeEx(struct vlMpeg2MacroBlock *mb)
268 {
269 assert(mb);
270
271 switch (mb->mb_type)
272 {
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;
284 default:
285 assert(0);
286 }
287
288 /* Unreachable */
289 return -1;
290 }
291
292 static inline int vlGrabMacroBlock
293 (
294 struct vlR16SnormBufferedMC *mc,
295 struct vlMpeg2MacroBlock *macroblock
296 )
297 {
298 assert(mc);
299 assert(macroblock);
300 assert(mc->num_macroblocks < mc->macroblocks_per_picture);
301
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;
317
318 vlGrabBlocks
319 (
320 mc,
321 macroblock->mbx,
322 macroblock->mby,
323 macroblock->dct_type,
324 macroblock->cbp,
325 macroblock->blocks
326 );
327
328 mc->num_macroblocks++;
329
330 return 0;
331 }
332
333 #define SET_BLOCK(vb, cbp, mbx, mby, unitx, unity, ofsx, ofsy, hx, hy, lm, cbm, crm, zb) \
334 do { \
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); \
341 \
342 if ((cbp) & (lm)) \
343 { \
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); \
350 } \
351 else \
352 { \
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); \
359 } \
360 \
361 if ((cbp) & (cbm)) \
362 { \
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); \
369 } \
370 else \
371 { \
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); \
378 } \
379 \
380 if ((cbp) & (crm)) \
381 { \
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); \
388 } \
389 else \
390 { \
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); \
397 } \
398 } while (0)
399
400 static inline int vlGenMacroblockVerts
401 (
402 struct vlR16SnormBufferedMC *mc,
403 struct vlMpeg2MacroBlock *macroblock,
404 unsigned int pos,
405 struct vlMacroBlockVertexStream0 *ycbcr_vb,
406 struct vlVertex2f **ref_vb
407 )
408 {
409 struct vlVertex2f mo_vec[2];
410 unsigned int i;
411
412 assert(mc);
413 assert(macroblock);
414 assert(ycbcr_vb);
415 assert(pos < mc->macroblocks_per_picture);
416
417 switch (macroblock->mb_type)
418 {
419 case vlMacroBlockTypeBiPredicted:
420 {
421 struct vlVertex2f *vb;
422
423 assert(ref_vb && ref_vb[1]);
424
425 vb = ref_vb[1] + pos * 2 * 24;
426
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;
429
430 if (macroblock->mo_type == vlMotionTypeFrame)
431 {
432 for (i = 0; i < 24 * 2; i += 2)
433 {
434 vb[i].x = mo_vec[0].x;
435 vb[i].y = mo_vec[0].y;
436 }
437 }
438 else
439 {
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;
442
443 for (i = 0; i < 24 * 2; i += 2)
444 {
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;
449 }
450 }
451
452 /* fall-through */
453 }
454 case vlMacroBlockTypeFwdPredicted:
455 case vlMacroBlockTypeBkwdPredicted:
456 {
457 struct vlVertex2f *vb;
458
459 assert(ref_vb && ref_vb[0]);
460
461 vb = ref_vb[0] + pos * 2 * 24;
462
463 if (macroblock->mb_type == vlMacroBlockTypeBkwdPredicted)
464 {
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;
467
468 if (macroblock->mo_type == vlMotionTypeField)
469 {
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;
472 }
473 }
474 else
475 {
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;
478
479 if (macroblock->mo_type == vlMotionTypeField)
480 {
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;
483 }
484 }
485
486 if (macroblock->mo_type == vlMotionTypeFrame)
487 {
488 for (i = 0; i < 24 * 2; i += 2)
489 {
490 vb[i].x = mo_vec[0].x;
491 vb[i].y = mo_vec[0].y;
492 }
493 }
494 else
495 {
496 for (i = 0; i < 24 * 2; i += 2)
497 {
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;
502 }
503 }
504
505 /* fall-through */
506 }
507 case vlMacroBlockTypeIntra:
508 {
509 const struct vlVertex2f unit =
510 {
511 mc->surface_tex_inv_size.x * VL_MACROBLOCK_WIDTH,
512 mc->surface_tex_inv_size.y * VL_MACROBLOCK_HEIGHT
513 };
514 const struct vlVertex2f half =
515 {
516 mc->surface_tex_inv_size.x * (VL_MACROBLOCK_WIDTH / 2),
517 mc->surface_tex_inv_size.y * (VL_MACROBLOCK_HEIGHT / 2)
518 };
519
520 struct vlMacroBlockVertexStream0 *vb;
521
522 vb = ycbcr_vb + pos * 24;
523
524 SET_BLOCK
525 (
526 vb,
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
530 );
531
532 SET_BLOCK
533 (
534 vb + 6,
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
538 );
539
540 SET_BLOCK
541 (
542 vb + 12,
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
546 );
547
548 SET_BLOCK
549 (
550 vb + 18,
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
554 );
555
556 break;
557 }
558 default:
559 assert(0);
560 }
561
562 return 0;
563 }
564
565 static int vlFlush
566 (
567 struct vlRender *render
568 )
569 {
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;
576 unsigned int i;
577
578 assert(render);
579
580 mc = (struct vlR16SnormBufferedMC*)render;
581
582 if (!mc->buffered_surface)
583 return 0;
584
585 if (mc->num_macroblocks < mc->macroblocks_per_picture)
586 return 0;
587
588 assert(mc->num_macroblocks <= mc->macroblocks_per_picture);
589
590 pipe = mc->pipe;
591
592 for (i = 0; i < mc->num_macroblocks; ++i)
593 {
594 enum vlMacroBlockTypeEx mb_type_ex = vlGetMacroBlockTypeEx(&mc->macroblocks[i]);
595
596 num_macroblocks[mb_type_ex]++;
597 }
598
599 offset[0] = 0;
600
601 for (i = 1; i < vlNumMacroBlockExTypes; ++i)
602 offset[i] = offset[i - 1] + num_macroblocks[i - 1];
603
604 {
605 struct vlMacroBlockVertexStream0 *ycbcr_vb;
606 struct vlVertex2f *ref_vb[2];
607
608 ycbcr_vb = (struct vlMacroBlockVertexStream0*)pipe_buffer_map
609 (
610 pipe->screen,
611 mc->vertex_bufs.ycbcr.buffer,
612 PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_DISCARD
613 );
614
615 for (i = 0; i < 2; ++i)
616 ref_vb[i] = (struct vlVertex2f*)pipe_buffer_map
617 (
618 pipe->screen,
619 mc->vertex_bufs.ref[i].buffer,
620 PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_DISCARD
621 );
622
623 for (i = 0; i < mc->num_macroblocks; ++i)
624 {
625 enum vlMacroBlockTypeEx mb_type_ex = vlGetMacroBlockTypeEx(&mc->macroblocks[i]);
626
627 vlGenMacroblockVerts(mc, &mc->macroblocks[i], offset[mb_type_ex], ycbcr_vb, ref_vb);
628
629 offset[mb_type_ex]++;
630 }
631
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);
635 }
636
637 for (i = 0; i < 3; ++i)
638 {
639 pipe_surface_unmap(mc->tex_surface[i]);
640 pipe_surface_reference(&mc->tex_surface[i], NULL);
641 }
642
643 mc->render_target.cbufs[0] = pipe->screen->get_tex_surface
644 (
645 pipe->screen,
646 mc->buffered_surface->texture,
647 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE
648 );
649
650 pipe->set_framebuffer_state(pipe, &mc->render_target);
651 pipe->set_viewport_state(pipe, &mc->viewport);
652 vs_consts = pipe->winsys->buffer_map
653 (
654 pipe->winsys,
655 mc->vs_const_buf.buffer,
656 PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_DISCARD
657 );
658
659 vs_consts->denorm.x = mc->buffered_surface->texture->width[0];
660 vs_consts->denorm.y = mc->buffered_surface->texture->height[0];
661
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);
665
666 if (num_macroblocks[vlMacroBlockExTypeIntra] > 0)
667 {
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);
674
675 pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeIntra] * 24);
676 vb_start += num_macroblocks[vlMacroBlockExTypeIntra] * 24;
677 }
678
679 if (num_macroblocks[vlMacroBlockExTypeFwdPredictedFrame] > 0)
680 {
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]);
688
689 pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeFwdPredictedFrame] * 24);
690 vb_start += num_macroblocks[vlMacroBlockExTypeFwdPredictedFrame] * 24;
691 }
692
693 if (num_macroblocks[vlMacroBlockExTypeFwdPredictedField] > 0)
694 {
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]);
702
703 pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeFwdPredictedField] * 24);
704 vb_start += num_macroblocks[vlMacroBlockExTypeFwdPredictedField] * 24;
705 }
706
707 if (num_macroblocks[vlMacroBlockExTypeBkwdPredictedFrame] > 0)
708 {
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]);
716
717 pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeBkwdPredictedFrame] * 24);
718 vb_start += num_macroblocks[vlMacroBlockExTypeBkwdPredictedFrame] * 24;
719 }
720
721 if (num_macroblocks[vlMacroBlockExTypeBkwdPredictedField] > 0)
722 {
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]);
730
731 pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeBkwdPredictedField] * 24);
732 vb_start += num_macroblocks[vlMacroBlockExTypeBkwdPredictedField] * 24;
733 }
734
735 if (num_macroblocks[vlMacroBlockExTypeBiPredictedFrame] > 0)
736 {
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]);
745
746 pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeBiPredictedFrame] * 24);
747 vb_start += num_macroblocks[vlMacroBlockExTypeBiPredictedFrame] * 24;
748 }
749
750 if (num_macroblocks[vlMacroBlockExTypeBiPredictedField] > 0)
751 {
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]);
760
761 pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeBiPredictedField] * 24);
762 vb_start += num_macroblocks[vlMacroBlockExTypeBiPredictedField] * 24;
763 }
764
765 pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, &mc->buffered_surface->render_fence);
766 pipe_surface_reference(&mc->render_target.cbufs[0], NULL);
767
768 for (i = 0; i < 3; ++i)
769 mc->zero_block[i].x = -1.0f;
770
771 mc->buffered_surface = NULL;
772 mc->num_macroblocks = 0;
773
774 return 0;
775 }
776
777 static int vlRenderMacroBlocksMpeg2R16SnormBuffered
778 (
779 struct vlRender *render,
780 struct vlMpeg2MacroBlockBatch *batch,
781 struct vlSurface *surface
782 )
783 {
784 struct vlR16SnormBufferedMC *mc;
785 bool new_surface = false;
786 unsigned int i;
787
788 assert(render);
789
790 mc = (struct vlR16SnormBufferedMC*)render;
791
792 if (mc->buffered_surface)
793 {
794 if (mc->buffered_surface != surface)
795 {
796 vlFlush(&mc->base);
797 new_surface = true;
798 }
799 }
800 else
801 new_surface = true;
802
803 if (new_surface)
804 {
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];
810
811 for (i = 0; i < 3; ++i)
812 {
813 mc->tex_surface[i] = mc->pipe->screen->get_tex_surface
814 (
815 mc->pipe->screen,
816 mc->textures.all[i],
817 0, 0, 0, PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_DISCARD
818 );
819
820 mc->texels[i] = pipe_surface_map(mc->tex_surface[i], PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_DISCARD);
821 }
822 }
823
824 for (i = 0; i < batch->num_macroblocks; ++i)
825 vlGrabMacroBlock(mc, &batch->macroblocks[i]);
826
827 return 0;
828 }
829
830 static inline int vlEnd
831 (
832 struct vlRender *render
833 )
834 {
835 assert(render);
836
837 return 0;
838 }
839
840 static int vlDestroy
841 (
842 struct vlRender *render
843 )
844 {
845 struct vlR16SnormBufferedMC *mc;
846 struct pipe_context *pipe;
847 unsigned int i;
848
849 assert(render);
850
851 mc = (struct vlR16SnormBufferedMC*)render;
852 pipe = mc->pipe;
853
854 for (i = 0; i < 5; ++i)
855 pipe->delete_sampler_state(pipe, mc->samplers.all[i]);
856
857 for (i = 0; i < 3; ++i)
858 pipe_buffer_reference(pipe->screen, &mc->vertex_bufs.all[i].buffer, NULL);
859
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);
863
864 pipe->delete_vs_state(pipe, mc->i_vs);
865 pipe->delete_fs_state(pipe, mc->i_fs);
866
867 for (i = 0; i < 2; ++i)
868 {
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]);
873 }
874
875 pipe_buffer_reference(pipe->screen, &mc->vs_const_buf.buffer, NULL);
876 pipe_buffer_reference(pipe->screen, &mc->fs_const_buf.buffer, NULL);
877
878 FREE(mc->macroblocks);
879 FREE(mc);
880
881 return 0;
882 }
883
884 /*
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.
889 */
890 static const struct vlFragmentShaderConsts fs_consts =
891 {
892 {32767.0f / 255.0f, 32767.0f / 255.0f, 32767.0f / 255.0f, 0.0f},
893 {0.5f, 2.0f, 0.0f, 0.0f}
894 };
895
896 #include "vl_r16snorm_mc_buf_shaders.inc"
897
898 static int vlCreateDataBufs
899 (
900 struct vlR16SnormBufferedMC *mc
901 )
902 {
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;
905
906 struct pipe_context *pipe;
907 unsigned int i;
908
909 assert(mc);
910
911 pipe = mc->pipe;
912 mc->macroblocks_per_picture = mbw * mbh;
913
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
919 (
920 pipe->screen,
921 DEFAULT_BUF_ALIGNMENT,
922 PIPE_BUFFER_USAGE_VERTEX | PIPE_BUFFER_USAGE_DISCARD,
923 sizeof(struct vlVertex2f) * 4 * 24 * mc->macroblocks_per_picture
924 );
925
926 for (i = 1; i < 3; ++i)
927 {
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
932 (
933 pipe->screen,
934 DEFAULT_BUF_ALIGNMENT,
935 PIPE_BUFFER_USAGE_VERTEX | PIPE_BUFFER_USAGE_DISCARD,
936 sizeof(struct vlVertex2f) * 2 * 24 * mc->macroblocks_per_picture
937 );
938 }
939
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;
945
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;
951
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;
957
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;
963
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;
969
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;
975
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;
981
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;
987
988 /* Create our constant buffer */
989 mc->vs_const_buf.size = sizeof(struct vlVertexShaderConsts);
990 mc->vs_const_buf.buffer = pipe_buffer_create
991 (
992 pipe->screen,
993 DEFAULT_BUF_ALIGNMENT,
994 PIPE_BUFFER_USAGE_CONSTANT | PIPE_BUFFER_USAGE_DISCARD,
995 mc->vs_const_buf.size
996 );
997
998 mc->fs_const_buf.size = sizeof(struct vlFragmentShaderConsts);
999 mc->fs_const_buf.buffer = pipe_buffer_create
1000 (
1001 pipe->screen,
1002 DEFAULT_BUF_ALIGNMENT,
1003 PIPE_BUFFER_USAGE_CONSTANT,
1004 mc->fs_const_buf.size
1005 );
1006
1007 memcpy
1008 (
1009 pipe_buffer_map(pipe->screen, mc->fs_const_buf.buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
1010 &fs_consts,
1011 sizeof(struct vlFragmentShaderConsts)
1012 );
1013
1014 pipe_buffer_unmap(pipe->screen, mc->fs_const_buf.buffer);
1015
1016 mc->macroblocks = MALLOC(sizeof(struct vlMpeg2MacroBlock) * mc->macroblocks_per_picture);
1017
1018 return 0;
1019 }
1020
1021 static int vlInit
1022 (
1023 struct vlR16SnormBufferedMC *mc
1024 )
1025 {
1026 struct pipe_context *pipe;
1027 struct pipe_sampler_state sampler;
1028 struct pipe_texture template;
1029 unsigned int filters[5];
1030 unsigned int i;
1031
1032 assert(mc);
1033
1034 pipe = mc->pipe;
1035
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;
1042
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;
1052
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;
1058
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;
1065
1066 for (i = 0; i < 5; ++i)
1067 {
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);
1085 }
1086
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;
1097
1098 mc->textures.y = pipe->screen->texture_create(pipe->screen, &template);
1099
1100 if (mc->picture_format == vlFormatYCbCr420)
1101 {
1102 template.width[0] = vlRoundUpPOT(mc->picture_width / 2);
1103 template.height[0] = vlRoundUpPOT(mc->picture_height / 2);
1104 }
1105 else if (mc->picture_format == vlFormatYCbCr422)
1106 template.height[0] = vlRoundUpPOT(mc->picture_height / 2);
1107
1108 mc->textures.cb = pipe->screen->texture_create(pipe->screen, &template);
1109 mc->textures.cr = pipe->screen->texture_create(pipe->screen, &template);
1110
1111 /* textures.all[3] & textures.all[4] are assigned from vlSurfaces for P and B macroblocks at render time */
1112
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);
1124
1125 return 0;
1126 }
1127
1128 int vlCreateR16SNormBufferedMC
1129 (
1130 struct pipe_context *pipe,
1131 unsigned int picture_width,
1132 unsigned int picture_height,
1133 enum vlFormat picture_format,
1134 struct vlRender **render
1135 )
1136 {
1137 struct vlR16SnormBufferedMC *mc;
1138
1139 assert(pipe);
1140 assert(render);
1141
1142 mc = CALLOC_STRUCT(vlR16SnormBufferedMC);
1143
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;
1149 mc->pipe = pipe;
1150 mc->picture_width = picture_width;
1151 mc->picture_height = picture_height;
1152
1153 vlInit(mc);
1154
1155 *render = &mc->base;
1156
1157 return 0;
1158 }