[g3dvl] split empty block handling
[mesa.git] / src / gallium / auxiliary / vl / vl_mpeg12_mc_renderer.c
1 /**************************************************************************
2 *
3 * Copyright 2009 Younes Manton.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #include "vl_mpeg12_mc_renderer.h"
29 #include "util/u_draw.h"
30 #include <assert.h>
31 #include <pipe/p_context.h>
32 #include <util/u_inlines.h>
33 #include <util/u_format.h>
34 #include <util/u_math.h>
35 #include <util/u_memory.h>
36 #include <util/u_keymap.h>
37 #include <util/u_sampler.h>
38 #include <tgsi/tgsi_ureg.h>
39
40 #define DEFAULT_BUF_ALIGNMENT 1
41 #define MACROBLOCK_WIDTH 16
42 #define MACROBLOCK_HEIGHT 16
43 #define BLOCK_WIDTH 8
44 #define BLOCK_HEIGHT 8
45
46 struct vertex_stream_0
47 {
48 struct vertex2f pos;
49 struct {
50 float y;
51 float cr;
52 float cb;
53 } eb[2][2];
54 float interlaced;
55 };
56
57 enum VS_INPUT
58 {
59 VS_I_RECT,
60 VS_I_VPOS,
61 VS_I_EB_0_0,
62 VS_I_EB_0_1,
63 VS_I_EB_1_0,
64 VS_I_EB_1_1,
65 VS_I_INTERLACED,
66 VS_I_MV0,
67 VS_I_MV1,
68 VS_I_MV2,
69 VS_I_MV3,
70
71 NUM_VS_INPUTS
72 };
73
74 enum VS_OUTPUT
75 {
76 VS_O_VPOS,
77 VS_O_LINE,
78 VS_O_TEX0,
79 VS_O_TEX1,
80 VS_O_TEX2,
81 VS_O_EB_0,
82 VS_O_EB_1,
83 VS_O_MV0,
84 VS_O_MV1,
85 VS_O_MV2,
86 VS_O_MV3
87 };
88
89 static const unsigned const_mbtype_config[VL_NUM_MACROBLOCK_TYPES][2] = {
90 [VL_MACROBLOCK_TYPE_INTRA] = { 0, 0 },
91 [VL_MACROBLOCK_TYPE_FWD_FRAME_PRED] = { 1, 1 },
92 [VL_MACROBLOCK_TYPE_FWD_FIELD_PRED] = { 1, 2 },
93 [VL_MACROBLOCK_TYPE_BKWD_FRAME_PRED] = { 1, 1 },
94 [VL_MACROBLOCK_TYPE_BKWD_FIELD_PRED] = { 1, 2 },
95 [VL_MACROBLOCK_TYPE_BI_FRAME_PRED] = { 2, 1 },
96 [VL_MACROBLOCK_TYPE_BI_FIELD_PRED] = { 2, 2 }
97 };
98
99 static void *
100 create_vert_shader(struct vl_mpeg12_mc_renderer *r, unsigned ref_frames, unsigned mv_per_frame)
101 {
102 struct ureg_program *shader;
103 struct ureg_src scale;
104 struct ureg_src vrect, vpos, eb[2][2], interlaced, vmv[4];
105 struct ureg_dst t_vpos, t_vtex;
106 struct ureg_dst o_vpos, o_line, o_vtex[3], o_eb[2], o_vmv[4];
107 unsigned i, j, count, label;
108
109 shader = ureg_create(TGSI_PROCESSOR_VERTEX);
110 if (!shader)
111 return NULL;
112
113 t_vpos = ureg_DECL_temporary(shader);
114 t_vtex = ureg_DECL_temporary(shader);
115
116 vrect = ureg_DECL_vs_input(shader, VS_I_RECT);
117 vpos = ureg_DECL_vs_input(shader, VS_I_VPOS);
118 eb[0][0] = ureg_DECL_vs_input(shader, VS_I_EB_0_0);
119 eb[1][0] = ureg_DECL_vs_input(shader, VS_I_EB_1_0);
120 eb[0][1] = ureg_DECL_vs_input(shader, VS_I_EB_0_1);
121 eb[1][1] = ureg_DECL_vs_input(shader, VS_I_EB_1_1);
122 interlaced = ureg_DECL_vs_input(shader, VS_I_INTERLACED);
123
124 o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, VS_O_VPOS);
125 o_line = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_LINE);
126 o_vtex[0] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_TEX0);
127 o_vtex[1] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_TEX1);
128 o_vtex[2] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_TEX2);
129 o_eb[0] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_EB_0);
130 o_eb[1] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_EB_1);
131
132 count=0;
133 for (i = 0; i < ref_frames; ++i) {
134 for (j = 0; j < 2; ++j) {
135 if(j < mv_per_frame) {
136 vmv[count] = ureg_DECL_vs_input(shader, VS_I_MV0 + count);
137 o_vmv[count] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_MV0 + count);
138 count++;
139 }
140 }
141 }
142
143 /*
144 * scale = (MACROBLOCK_WIDTH, MACROBLOCK_HEIGHT) / (dst.width, dst.height)
145 *
146 * t_vpos = (vpos + vrect) * scale
147 * o_vpos.xy = t_vpos
148 * o_vpos.zw = vpos
149 *
150 * o_line.xy = vrect * 8
151 * o_line.z = interlaced
152 *
153 * if(interlaced) {
154 * t_vtex.x = vrect.x
155 * t_vtex.y = vrect.y * 0.5
156 * t_vtex += vpos
157 *
158 * o_vtex[0].xy = t_vtex * scale
159 *
160 * t_vtex.y += 0.5
161 * o_vtex[1].xy = t_vtex * scale
162 * } else {
163 * o_vtex[0..1].xy = t_vpos
164 * }
165 * o_vtex[2].xy = t_vpos
166 *
167 * o_eb[0..1] = vrect.x ? eb[0..1][1] : eb[0..1][0]
168 *
169 * if(count > 0) { // Apply motion vectors
170 * scale = 0.5 / (dst.width, dst.height);
171 * o_vmv[0..count] = t_vpos + vmv[0..count] * scale
172 * }
173 *
174 */
175 scale = ureg_imm2f(shader,
176 (float)MACROBLOCK_WIDTH / r->buffer_width,
177 (float)MACROBLOCK_HEIGHT / r->buffer_height);
178
179 ureg_ADD(shader, ureg_writemask(t_vpos, TGSI_WRITEMASK_XY), vpos, vrect);
180 ureg_MUL(shader, ureg_writemask(t_vpos, TGSI_WRITEMASK_XY), ureg_src(t_vpos), scale);
181 ureg_MOV(shader, ureg_writemask(o_vpos, TGSI_WRITEMASK_XY), ureg_src(t_vpos));
182 ureg_MOV(shader, ureg_writemask(o_vpos, TGSI_WRITEMASK_ZW), vpos);
183
184 ureg_MUL(shader, ureg_writemask(o_line, TGSI_WRITEMASK_XY), vrect,
185 ureg_imm2f(shader, MACROBLOCK_WIDTH / 2, MACROBLOCK_HEIGHT / 2));
186 ureg_MOV(shader, ureg_writemask(o_line, TGSI_WRITEMASK_Z),
187 ureg_scalar(interlaced, TGSI_SWIZZLE_X));
188
189 ureg_IF(shader, interlaced, &label);
190
191 ureg_MOV(shader, ureg_writemask(t_vtex, TGSI_WRITEMASK_X), vrect);
192 ureg_MUL(shader, ureg_writemask(t_vtex, TGSI_WRITEMASK_Y), vrect, ureg_imm1f(shader, 0.5f));
193 ureg_ADD(shader, ureg_writemask(t_vtex, TGSI_WRITEMASK_XY), vpos, ureg_src(t_vtex));
194 ureg_MUL(shader, ureg_writemask(o_vtex[0], TGSI_WRITEMASK_XY), ureg_src(t_vtex), scale);
195 ureg_ADD(shader, ureg_writemask(t_vtex, TGSI_WRITEMASK_Y), ureg_src(t_vtex), ureg_imm1f(shader, 0.5f));
196 ureg_MUL(shader, ureg_writemask(o_vtex[1], TGSI_WRITEMASK_XY), ureg_src(t_vtex), scale);
197
198 ureg_ELSE(shader, &label);
199
200 ureg_MOV(shader, ureg_writemask(o_vtex[0], TGSI_WRITEMASK_XY), ureg_src(t_vpos));
201 ureg_MOV(shader, ureg_writemask(o_vtex[1], TGSI_WRITEMASK_XY), ureg_src(t_vpos));
202
203 ureg_ENDIF(shader);
204 ureg_MOV(shader, ureg_writemask(o_vtex[2], TGSI_WRITEMASK_XY), ureg_src(t_vpos));
205
206 ureg_CMP(shader, ureg_writemask(o_eb[0], TGSI_WRITEMASK_XYZ),
207 ureg_negate(ureg_scalar(vrect, TGSI_SWIZZLE_X)),
208 eb[0][1], eb[0][0]);
209 ureg_CMP(shader, ureg_writemask(o_eb[1], TGSI_WRITEMASK_XYZ),
210 ureg_negate(ureg_scalar(vrect, TGSI_SWIZZLE_X)),
211 eb[1][1], eb[1][0]);
212
213 if(count > 0) {
214 scale = ureg_imm2f(shader,
215 0.5f / r->buffer_width,
216 0.5f / r->buffer_height);
217
218 for (i = 0; i < count; ++i)
219 ureg_MAD(shader, ureg_writemask(o_vmv[i], TGSI_WRITEMASK_XY), scale, vmv[i], ureg_src(t_vpos));
220 }
221
222 ureg_release_temporary(shader, t_vtex);
223 ureg_release_temporary(shader, t_vpos);
224
225 ureg_END(shader);
226
227 return ureg_create_shader_and_destroy(shader, r->pipe);
228 }
229
230 static struct ureg_dst
231 calc_field(struct ureg_program *shader)
232 {
233 struct ureg_dst tmp;
234 struct ureg_src line;
235
236 tmp = ureg_DECL_temporary(shader);
237 line = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_LINE, TGSI_INTERPOLATE_LINEAR);
238
239 /*
240 * line.xy going from 0 to 8 in steps of 0.5
241 * line.z flag that controls interlacing
242 *
243 * tmp.z = fraction(line.y)
244 * tmp.z = tmp.z >= 0.5 ? 1 : 0
245 * tmp.xy = line >= 4 ? 1 : 0
246 * tmp.w = line.z ? tmp.z : tmp.y
247 */
248 ureg_FRC(shader, ureg_writemask(tmp, TGSI_WRITEMASK_Z), ureg_scalar(line, TGSI_SWIZZLE_Y));
249 ureg_SGE(shader, ureg_writemask(tmp, TGSI_WRITEMASK_Z), ureg_src(tmp), ureg_imm1f(shader, 0.5f));
250 ureg_SGE(shader, ureg_writemask(tmp, TGSI_WRITEMASK_XY), line, ureg_imm2f(shader, BLOCK_WIDTH / 2, BLOCK_HEIGHT / 2));
251 ureg_CMP(shader, ureg_writemask(tmp, TGSI_WRITEMASK_W),
252 ureg_negate(ureg_scalar(line, TGSI_SWIZZLE_Z)),
253 ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_Z),
254 ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_Y));
255
256 return tmp;
257 }
258
259 static struct ureg_dst
260 fetch_ycbcr(struct vl_mpeg12_mc_renderer *r, struct ureg_program *shader, struct ureg_dst field)
261 {
262 struct ureg_src tc[3], sampler[3], eb[2];
263 struct ureg_dst texel, t_tc, t_eb_info, tmp;
264 unsigned i, label;
265
266 texel = ureg_DECL_temporary(shader);
267 t_tc = ureg_DECL_temporary(shader);
268 t_eb_info = ureg_DECL_temporary(shader);
269 tmp = ureg_DECL_temporary(shader);
270
271 tc[0] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_TEX0, TGSI_INTERPOLATE_LINEAR);
272 tc[1] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_TEX1, TGSI_INTERPOLATE_LINEAR);
273 tc[2] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_TEX2, TGSI_INTERPOLATE_LINEAR);
274
275 eb[0] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_EB_0, TGSI_INTERPOLATE_CONSTANT);
276 eb[1] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_EB_1, TGSI_INTERPOLATE_CONSTANT);
277
278 for (i = 0; i < 3; ++i) {
279 sampler[i] = ureg_DECL_sampler(shader, i);
280 }
281
282 /*
283 * texel.y = tex(field.y ? tc[1] : tc[0], sampler[0])
284 * texel.cb = tex(tc[2], sampler[1])
285 * texel.cr = tex(tc[2], sampler[2])
286 */
287
288 ureg_CMP(shader, ureg_writemask(t_tc, TGSI_WRITEMASK_XY),
289 ureg_negate(ureg_scalar(ureg_src(field), TGSI_SWIZZLE_W)),
290 tc[1], tc[0]);
291
292 ureg_CMP(shader, ureg_writemask(t_eb_info, TGSI_WRITEMASK_XYZ),
293 ureg_negate(ureg_scalar(ureg_src(field), TGSI_SWIZZLE_W)),
294 eb[1], eb[0]);
295
296 /* r600g is ignoring TGSI_INTERPOLATE_CONSTANT, just workaround this */
297 ureg_SGE(shader, ureg_writemask(t_eb_info, TGSI_WRITEMASK_XYZ), ureg_src(t_eb_info), ureg_imm1f(shader, 0.5f));
298
299 for (i = 0; i < 3; ++i) {
300 ureg_IF(shader, ureg_scalar(ureg_src(t_eb_info), TGSI_SWIZZLE_X + i), &label);
301 ureg_MOV(shader, ureg_writemask(texel, TGSI_WRITEMASK_X << i), ureg_imm1f(shader, 0.0f));
302 ureg_ELSE(shader, &label);
303
304 /* Nouveau and r600g can't writemask tex dst regs (yet?), do in two steps */
305 if(i==0 || r->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_444) {
306 ureg_TEX(shader, tmp, TGSI_TEXTURE_3D, ureg_src(t_tc), sampler[i]);
307 } else {
308 ureg_TEX(shader, tmp, TGSI_TEXTURE_3D, tc[2], sampler[i]);
309 }
310
311 ureg_MOV(shader, ureg_writemask(texel, TGSI_WRITEMASK_X << i), ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X));
312
313 ureg_ENDIF(shader);
314 }
315
316 ureg_release_temporary(shader, t_tc);
317 ureg_release_temporary(shader, t_eb_info);
318 ureg_release_temporary(shader, tmp);
319
320 return texel;
321 }
322
323 static struct ureg_dst
324 fetch_ref(struct ureg_program *shader, struct ureg_dst field, unsigned ref_frames, unsigned mv_per_frame)
325 {
326 struct ureg_src tc[ref_frames * mv_per_frame], sampler[ref_frames];
327 struct ureg_dst ref[ref_frames], t_tc, result;
328 unsigned i;
329
330 for (i = 0; i < ref_frames * mv_per_frame; ++i)
331 tc[i] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_MV0 + i, TGSI_INTERPOLATE_LINEAR);
332
333 for (i = 0; i < ref_frames; ++i) {
334 sampler[i] = ureg_DECL_sampler(shader, i + 3);
335 ref[i] = ureg_DECL_temporary(shader);
336 }
337
338 result = ureg_DECL_temporary(shader);
339
340 if (ref_frames == 1) {
341 if(mv_per_frame == 1)
342 /*
343 * result = tex(tc[0], sampler[0])
344 */
345 ureg_TEX(shader, result, TGSI_TEXTURE_2D, tc[0], sampler[0]);
346 else {
347 t_tc = ureg_DECL_temporary(shader);
348 /*
349 * result = tex(field.y ? tc[1] : tc[0], sampler[0])
350 */
351 ureg_CMP(shader, ureg_writemask(t_tc, TGSI_WRITEMASK_XY),
352 ureg_negate(ureg_scalar(ureg_src(field), TGSI_SWIZZLE_Z)),
353 tc[1], tc[0]);
354 ureg_TEX(shader, result, TGSI_TEXTURE_2D, ureg_src(t_tc), sampler[0]);
355
356 ureg_release_temporary(shader, t_tc);
357 }
358
359 } else if (ref_frames == 2) {
360 if(mv_per_frame == 1) {
361 /*
362 * ref[0..1] = tex(tc[0..1], sampler[0..1])
363 */
364 ureg_TEX(shader, ref[0], TGSI_TEXTURE_2D, tc[0], sampler[0]);
365 ureg_TEX(shader, ref[1], TGSI_TEXTURE_2D, tc[1], sampler[1]);
366 } else {
367 t_tc = ureg_DECL_temporary(shader);
368
369 /*
370 * if (field.y)
371 * ref[0..1] = tex(tc[0..1], sampler[0..1])
372 * else
373 * ref[0..1] = tex(tc[2..3], sampler[0..1])
374 */
375 ureg_CMP(shader, ureg_writemask(t_tc, TGSI_WRITEMASK_XY),
376 ureg_negate(ureg_scalar(ureg_src(field), TGSI_SWIZZLE_Z)),
377 tc[1], tc[0]);
378 ureg_TEX(shader, ref[0], TGSI_TEXTURE_2D, ureg_src(t_tc), sampler[0]);
379
380 ureg_CMP(shader, ureg_writemask(t_tc, TGSI_WRITEMASK_XY),
381 ureg_negate(ureg_scalar(ureg_src(field), TGSI_SWIZZLE_Z)),
382 tc[3], tc[2]);
383 ureg_TEX(shader, ref[1], TGSI_TEXTURE_2D, ureg_src(t_tc), sampler[1]);
384
385 ureg_release_temporary(shader, t_tc);
386 }
387
388 ureg_LRP(shader, result, ureg_scalar(ureg_imm1f(shader, 0.5f), TGSI_SWIZZLE_X), ureg_src(ref[0]), ureg_src(ref[1]));
389 }
390
391 for (i = 0; i < ref_frames; ++i)
392 ureg_release_temporary(shader, ref[i]);
393
394 return result;
395 }
396
397 static void *
398 create_frag_shader(struct vl_mpeg12_mc_renderer *r, unsigned ref_frames, unsigned mv_per_frame)
399 {
400 struct ureg_program *shader;
401 struct ureg_src result;
402 struct ureg_dst field, texel;
403 struct ureg_dst fragment;
404
405 shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
406 if (!shader)
407 return NULL;
408
409 fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
410
411 field = calc_field(shader);
412 texel = fetch_ycbcr(r, shader, field);
413
414 if (ref_frames == 0)
415 result = ureg_imm1f(shader, 0.5f);
416 else
417 result = ureg_src(fetch_ref(shader, field, ref_frames, mv_per_frame));
418
419 ureg_ADD(shader, fragment, ureg_src(texel), result);
420
421 ureg_release_temporary(shader, field);
422 ureg_release_temporary(shader, texel);
423 ureg_END(shader);
424
425 return ureg_create_shader_and_destroy(shader, r->pipe);
426 }
427
428 static bool
429 init_mbtype_handler(struct vl_mpeg12_mc_renderer *r, enum VL_MACROBLOCK_TYPE type,
430 struct pipe_vertex_element vertex_elems[NUM_VS_INPUTS])
431 {
432 unsigned ref_frames, mv_per_frame;
433 struct vl_mc_mbtype_handler *handler;
434 unsigned i;
435
436 assert(r);
437
438 ref_frames = const_mbtype_config[type][0];
439 mv_per_frame = const_mbtype_config[type][1];
440
441 handler = &r->mbtype_handlers[type];
442
443 handler->vs = create_vert_shader(r, ref_frames, mv_per_frame);
444 handler->fs = create_frag_shader(r, ref_frames, mv_per_frame);
445
446 if (handler->vs == NULL || handler->fs == NULL)
447 return false;
448
449 handler->vertex_elems_state = r->pipe->create_vertex_elements_state(
450 r->pipe, 7 + ref_frames * mv_per_frame, vertex_elems);
451
452 if (handler->vertex_elems_state == NULL)
453 return false;
454
455 if (!vl_vb_init(&handler->pos, r->macroblocks_per_batch, sizeof(struct vertex_stream_0) / sizeof(float)))
456 return false;
457
458 for (i = 0; i < ref_frames * mv_per_frame; ++i) {
459 if (!vl_vb_init(&handler->mv[i], r->macroblocks_per_batch, sizeof(struct vertex2f) / sizeof(float)))
460 return false;
461 }
462
463 return true;
464 }
465
466 static void
467 cleanup_mbtype_handler(struct vl_mpeg12_mc_renderer *r, enum VL_MACROBLOCK_TYPE type)
468 {
469 unsigned ref_frames, mv_per_frame;
470 struct vl_mc_mbtype_handler *handler;
471 unsigned i;
472
473 assert(r);
474
475 ref_frames = const_mbtype_config[type][0];
476 mv_per_frame = const_mbtype_config[type][1];
477
478 handler = &r->mbtype_handlers[type];
479
480 r->pipe->delete_vs_state(r->pipe, handler->vs);
481 r->pipe->delete_fs_state(r->pipe, handler->fs);
482 r->pipe->delete_vertex_elements_state(r->pipe, handler->vertex_elems_state);
483
484 vl_vb_cleanup(&handler->pos);
485
486 for (i = 0; i < ref_frames * mv_per_frame; ++i)
487 vl_vb_cleanup(&handler->mv[i]);
488 }
489
490
491 static bool
492 init_pipe_state(struct vl_mpeg12_mc_renderer *r)
493 {
494 struct pipe_sampler_state sampler;
495 struct pipe_rasterizer_state rs_state;
496 unsigned filters[5];
497 unsigned i;
498
499 assert(r);
500
501 r->viewport.scale[0] = r->buffer_width;
502 r->viewport.scale[1] = r->buffer_height;
503 r->viewport.scale[2] = 1;
504 r->viewport.scale[3] = 1;
505 r->viewport.translate[0] = 0;
506 r->viewport.translate[1] = 0;
507 r->viewport.translate[2] = 0;
508 r->viewport.translate[3] = 0;
509
510 r->fb_state.width = r->buffer_width;
511 r->fb_state.height = r->buffer_height;
512 r->fb_state.nr_cbufs = 1;
513 r->fb_state.zsbuf = NULL;
514
515 /* Luma filter */
516 filters[0] = PIPE_TEX_FILTER_NEAREST;
517 /* Chroma filters */
518 if (r->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_444 || true) { //TODO
519 filters[1] = PIPE_TEX_FILTER_NEAREST;
520 filters[2] = PIPE_TEX_FILTER_NEAREST;
521 }
522 else {
523 filters[1] = PIPE_TEX_FILTER_LINEAR;
524 filters[2] = PIPE_TEX_FILTER_LINEAR;
525 }
526 /* Fwd, bkwd ref filters */
527 filters[3] = PIPE_TEX_FILTER_LINEAR;
528 filters[4] = PIPE_TEX_FILTER_LINEAR;
529
530 for (i = 0; i < 5; ++i) {
531 memset(&sampler, 0, sizeof(sampler));
532 sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
533 sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
534 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_BORDER;
535 sampler.min_img_filter = filters[i];
536 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
537 sampler.mag_img_filter = filters[i];
538 sampler.compare_mode = PIPE_TEX_COMPARE_NONE;
539 sampler.compare_func = PIPE_FUNC_ALWAYS;
540 sampler.normalized_coords = 1;
541 /*sampler.shadow_ambient = ; */
542 /*sampler.lod_bias = ; */
543 sampler.min_lod = 0;
544 /*sampler.max_lod = ; */
545 sampler.border_color[0] = 0.0f;
546 sampler.border_color[1] = 0.0f;
547 sampler.border_color[2] = 0.0f;
548 sampler.border_color[3] = 0.0f;
549 /*sampler.max_anisotropy = ; */
550 r->samplers.all[i] = r->pipe->create_sampler_state(r->pipe, &sampler);
551 }
552
553 memset(&rs_state, 0, sizeof(rs_state));
554 /*rs_state.sprite_coord_enable */
555 rs_state.sprite_coord_mode = PIPE_SPRITE_COORD_UPPER_LEFT;
556 rs_state.point_quad_rasterization = true;
557 rs_state.point_size = BLOCK_WIDTH;
558 rs_state.gl_rasterization_rules = true;
559 r->rs_state = r->pipe->create_rasterizer_state(r->pipe, &rs_state);
560
561 return true;
562 }
563
564 static void
565 cleanup_pipe_state(struct vl_mpeg12_mc_renderer *r)
566 {
567 unsigned i;
568
569 assert(r);
570
571 for (i = 0; i < 5; ++i)
572 r->pipe->delete_sampler_state(r->pipe, r->samplers.all[i]);
573
574 r->pipe->delete_rasterizer_state(r->pipe, r->rs_state);
575 }
576
577 static bool
578 init_buffers(struct vl_mpeg12_mc_renderer *r)
579 {
580 struct pipe_resource *idct_matrix;
581 struct pipe_resource template;
582 struct pipe_vertex_element vertex_elems[NUM_VS_INPUTS];
583 struct pipe_sampler_view sampler_view;
584
585 const unsigned mbw =
586 align(r->buffer_width, MACROBLOCK_WIDTH) / MACROBLOCK_WIDTH;
587 const unsigned mbh =
588 align(r->buffer_height, MACROBLOCK_HEIGHT) / MACROBLOCK_HEIGHT;
589
590 unsigned i, stride;
591
592 assert(r);
593
594 r->macroblocks_per_batch =
595 mbw * (r->bufmode == VL_MPEG12_MC_RENDERER_BUFFER_PICTURE ? mbh : 1);
596 r->num_macroblocks = 0;
597
598 memset(&template, 0, sizeof(struct pipe_resource));
599 template.target = PIPE_TEXTURE_2D;
600 /* TODO: Accomodate HW that can't do this and also for cases when this isn't precise enough */
601 template.format = PIPE_FORMAT_R16_SNORM;
602 template.last_level = 0;
603 template.width0 = r->buffer_width;
604 template.height0 = r->buffer_height;
605 template.depth0 = 1;
606 template.usage = PIPE_USAGE_DYNAMIC;
607 template.bind = PIPE_BIND_SAMPLER_VIEW;
608 template.flags = 0;
609
610 r->textures.individual.y = r->pipe->screen->resource_create(r->pipe->screen, &template);
611
612 if (!(idct_matrix = vl_idct_upload_matrix(r->pipe)))
613 return false;
614
615 if (!vl_idct_init(&r->idct_luma, r->pipe, r->buffer_width, r->buffer_height, idct_matrix))
616 return false;
617
618 if (!vl_idct_init_buffer(&r->idct_luma, &r->idct_y, r->textures.individual.y))
619 return false;
620
621 vl_idct_map_buffers(&r->idct_luma, &r->idct_y);
622
623 if (r->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420) {
624 template.width0 = r->buffer_width / 2;
625 template.height0 = r->buffer_height / 2;
626 }
627 else if (r->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_422)
628 template.height0 = r->buffer_height / 2;
629
630 r->textures.individual.cb =
631 r->pipe->screen->resource_create(r->pipe->screen, &template);
632 r->textures.individual.cr =
633 r->pipe->screen->resource_create(r->pipe->screen, &template);
634
635 if(!vl_idct_init(&r->idct_chroma, r->pipe, template.width0, template.height0, idct_matrix))
636 return false;
637
638 if (!vl_idct_init_buffer(&r->idct_chroma, &r->idct_cb, r->textures.individual.cb))
639 return false;
640
641 vl_idct_map_buffers(&r->idct_chroma, &r->idct_cb);
642
643 if (!vl_idct_init_buffer(&r->idct_chroma, &r->idct_cr, r->textures.individual.cr))
644 return false;
645
646 vl_idct_map_buffers(&r->idct_chroma, &r->idct_cr);
647
648 for (i = 0; i < 3; ++i) {
649 u_sampler_view_default_template(&sampler_view,
650 r->textures.all[i],
651 r->textures.all[i]->format);
652 r->sampler_views.all[i] = r->pipe->create_sampler_view(r->pipe, r->textures.all[i], &sampler_view);
653 }
654
655 memset(&vertex_elems, 0, sizeof(vertex_elems));
656
657 vertex_elems[VS_I_RECT] = vl_vb_get_quad_vertex_element();
658 r->vertex_bufs.individual.quad = vl_vb_upload_quads(r->pipe, r->macroblocks_per_batch);
659
660 /* Position element */
661 vertex_elems[VS_I_VPOS].src_format = PIPE_FORMAT_R32G32_FLOAT;
662
663 /* y, cr, cb empty block element top left block */
664 vertex_elems[VS_I_EB_0_0].src_format = PIPE_FORMAT_R32G32B32_FLOAT;
665
666 /* y, cr, cb empty block element top right block */
667 vertex_elems[VS_I_EB_0_1].src_format = PIPE_FORMAT_R32G32B32_FLOAT;
668
669 /* y, cr, cb empty block element bottom left block */
670 vertex_elems[VS_I_EB_1_0].src_format = PIPE_FORMAT_R32G32B32_FLOAT;
671
672 /* y, cr, cb empty block element bottom right block */
673 vertex_elems[VS_I_EB_1_1].src_format = PIPE_FORMAT_R32G32B32_FLOAT;
674
675 /* progressive=0.0f interlaced=1.0f */
676 vertex_elems[VS_I_INTERLACED].src_format = PIPE_FORMAT_R32_FLOAT;
677
678 stride = vl_vb_element_helper(&vertex_elems[VS_I_VPOS], 6, 1);
679
680 r->vertex_bufs.individual.pos = vl_vb_create_buffer(
681 r->pipe, r->macroblocks_per_batch, stride);
682
683 for (i = 0; i < 4; ++i) {
684 /* motion vector 0..4 element */
685 vertex_elems[VS_I_MV0 + i].src_format = PIPE_FORMAT_R32G32_FLOAT;
686 stride = vl_vb_element_helper(&vertex_elems[VS_I_MV0 + i], 1, i + 2);
687 r->vertex_bufs.individual.mv[i] = vl_vb_create_buffer(
688 r->pipe, r->macroblocks_per_batch, stride);
689 }
690
691 for(i = 0; i < VL_NUM_MACROBLOCK_TYPES; ++i)
692 init_mbtype_handler(r, i, vertex_elems);
693
694 return true;
695 }
696
697 static void
698 cleanup_buffers(struct vl_mpeg12_mc_renderer *r)
699 {
700 unsigned i;
701
702 assert(r);
703
704 for (i = 0; i < 3; ++i) {
705 pipe_sampler_view_reference(&r->sampler_views.all[i], NULL);
706 pipe_resource_reference(&r->vertex_bufs.all[i].buffer, NULL);
707 pipe_resource_reference(&r->textures.all[i], NULL);
708 }
709
710 for(i = 0; i<VL_NUM_MACROBLOCK_TYPES; ++i)
711 cleanup_mbtype_handler(r, i);
712
713 vl_idct_unmap_buffers(&r->idct_luma, &r->idct_y);
714 vl_idct_unmap_buffers(&r->idct_chroma, &r->idct_cb);
715 vl_idct_unmap_buffers(&r->idct_chroma, &r->idct_cr);
716
717 vl_idct_cleanup_buffer(&r->idct_luma, &r->idct_y);
718 vl_idct_cleanup_buffer(&r->idct_chroma, &r->idct_cb);
719 vl_idct_cleanup_buffer(&r->idct_chroma, &r->idct_cr);
720
721 vl_idct_cleanup(&r->idct_luma);
722 vl_idct_cleanup(&r->idct_chroma);
723 }
724
725 static enum VL_MACROBLOCK_TYPE
726 get_macroblock_type(struct pipe_mpeg12_macroblock *mb)
727 {
728 assert(mb);
729
730 switch (mb->mb_type) {
731 case PIPE_MPEG12_MACROBLOCK_TYPE_INTRA:
732 return VL_MACROBLOCK_TYPE_INTRA;
733 case PIPE_MPEG12_MACROBLOCK_TYPE_FWD:
734 return mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FRAME ?
735 VL_MACROBLOCK_TYPE_FWD_FRAME_PRED : VL_MACROBLOCK_TYPE_FWD_FIELD_PRED;
736 case PIPE_MPEG12_MACROBLOCK_TYPE_BKWD:
737 return mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FRAME ?
738 VL_MACROBLOCK_TYPE_BKWD_FRAME_PRED : VL_MACROBLOCK_TYPE_BKWD_FIELD_PRED;
739 case PIPE_MPEG12_MACROBLOCK_TYPE_BI:
740 return mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FRAME ?
741 VL_MACROBLOCK_TYPE_BI_FRAME_PRED : VL_MACROBLOCK_TYPE_BI_FIELD_PRED;
742 default:
743 assert(0);
744 }
745
746 /* Unreachable */
747 return -1;
748 }
749
750 static void
751 upload_vertex_stream(struct vl_mpeg12_mc_renderer *r,
752 unsigned num_macroblocks[VL_NUM_MACROBLOCK_TYPES])
753 {
754 struct vertex_stream_0 *pos;
755 struct vertex2f *mv[4];
756
757 struct pipe_transfer *buf_transfer[5];
758
759 unsigned i, j;
760
761 assert(r);
762 assert(num_macroblocks);
763
764 pos = (struct vertex_stream_0 *)pipe_buffer_map
765 (
766 r->pipe,
767 r->vertex_bufs.individual.pos.buffer,
768 PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD,
769 &buf_transfer[0]
770 );
771
772 for (i = 0; i < 4; ++i)
773 mv[i] = (struct vertex2f *)pipe_buffer_map
774 (
775 r->pipe,
776 r->vertex_bufs.individual.mv[i].buffer,
777 PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD,
778 &buf_transfer[i + 1]
779 );
780
781 for (i = 0; i < VL_NUM_MACROBLOCK_TYPES; ++i) {
782 struct vl_mc_mbtype_handler *handler = &r->mbtype_handlers[i];
783 unsigned count = vl_vb_upload(&handler->pos, pos);
784 if (count > 0) {
785 pos += count;
786
787 unsigned ref_frames, mv_per_frame;
788
789 ref_frames = const_mbtype_config[i][0];
790 mv_per_frame = const_mbtype_config[i][1];
791
792 for (j = 0; j < ref_frames * mv_per_frame; ++j)
793 vl_vb_upload(&handler->mv[j], mv[j]);
794
795 for (j = 0; j < 4; ++j)
796 mv[j] += count;
797 }
798 num_macroblocks[i] = count;
799 }
800
801 pipe_buffer_unmap(r->pipe, r->vertex_bufs.individual.pos.buffer, buf_transfer[0]);
802 for (i = 0; i < 4; ++i)
803 pipe_buffer_unmap(r->pipe, r->vertex_bufs.individual.mv[i].buffer, buf_transfer[i + 1]);
804 }
805
806 static struct pipe_sampler_view
807 *find_or_create_sampler_view(struct vl_mpeg12_mc_renderer *r, struct pipe_surface *surface)
808 {
809 struct pipe_sampler_view *sampler_view;
810 assert(r);
811 assert(surface);
812
813 sampler_view = (struct pipe_sampler_view*)util_keymap_lookup(r->texview_map, &surface);
814 if (!sampler_view) {
815 struct pipe_sampler_view templat;
816 boolean added_to_map;
817
818 u_sampler_view_default_template(&templat, surface->texture,
819 surface->texture->format);
820 sampler_view = r->pipe->create_sampler_view(r->pipe, surface->texture,
821 &templat);
822 if (!sampler_view)
823 return NULL;
824
825 added_to_map = util_keymap_insert(r->texview_map, &surface,
826 sampler_view, r->pipe);
827 assert(added_to_map);
828 }
829
830 return sampler_view;
831 }
832
833 static unsigned
834 flush_mbtype_handler(struct vl_mpeg12_mc_renderer *r, enum VL_MACROBLOCK_TYPE type,
835 unsigned vb_start, unsigned num_macroblocks)
836 {
837 unsigned ref_frames, mv_per_frame;
838 struct vl_mc_mbtype_handler *handler;
839
840 assert(r);
841
842 ref_frames = const_mbtype_config[type][0];
843 mv_per_frame = const_mbtype_config[type][1];
844
845 handler = &r->mbtype_handlers[type];
846
847 r->pipe->set_vertex_buffers(r->pipe, 2 + ref_frames * mv_per_frame, r->vertex_bufs.all);
848 r->pipe->bind_vertex_elements_state(r->pipe, handler->vertex_elems_state);
849
850 if(ref_frames == 2) {
851
852 r->textures.individual.ref[0] = r->past->texture;
853 r->textures.individual.ref[1] = r->future->texture;
854 r->sampler_views.individual.ref[0] = find_or_create_sampler_view(r, r->past);
855 r->sampler_views.individual.ref[1] = find_or_create_sampler_view(r, r->future);
856
857 } else if(ref_frames == 1) {
858
859 struct pipe_surface *ref;
860
861 if(type == VL_MACROBLOCK_TYPE_BKWD_FRAME_PRED ||
862 type == VL_MACROBLOCK_TYPE_BKWD_FIELD_PRED)
863 ref = r->future;
864 else
865 ref = r->past;
866
867 r->textures.individual.ref[0] = ref->texture;
868 r->sampler_views.individual.ref[0] = find_or_create_sampler_view(r, ref);
869 }
870
871 r->pipe->set_fragment_sampler_views(r->pipe, 3 + ref_frames, r->sampler_views.all);
872 r->pipe->bind_fragment_sampler_states(r->pipe, 3 + ref_frames, r->samplers.all);
873 r->pipe->bind_vs_state(r->pipe, handler->vs);
874 r->pipe->bind_fs_state(r->pipe, handler->fs);
875
876 util_draw_arrays(r->pipe, PIPE_PRIM_QUADS, vb_start, num_macroblocks);
877 return num_macroblocks;
878 }
879
880 static void
881 get_motion_vectors(struct pipe_mpeg12_macroblock *mb, struct vertex2f mv[4])
882 {
883 switch (mb->mb_type) {
884 case PIPE_MPEG12_MACROBLOCK_TYPE_BI:
885 {
886 if (mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FRAME) {
887
888 mv[1].x = mb->pmv[0][1][0];
889 mv[1].y = mb->pmv[0][1][1];
890
891 } else {
892 mv[2].x = mb->pmv[0][1][0];
893 mv[2].y = mb->pmv[0][1][1] - (mb->pmv[0][1][1] % 4);
894
895 mv[3].x = mb->pmv[1][1][0];
896 mv[3].y = mb->pmv[1][1][1] - (mb->pmv[1][1][1] % 4);
897
898 if(mb->mvfs[0][1]) mv[2].y += 2;
899 if(!mb->mvfs[1][1]) mv[3].y -= 2;
900 }
901
902 /* fall-through */
903 }
904 case PIPE_MPEG12_MACROBLOCK_TYPE_FWD:
905 case PIPE_MPEG12_MACROBLOCK_TYPE_BKWD:
906 {
907 if (mb->mb_type == PIPE_MPEG12_MACROBLOCK_TYPE_BKWD) {
908
909 if (mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FRAME) {
910 mv[0].x = mb->pmv[0][1][0];
911 mv[0].y = mb->pmv[0][1][1];
912
913 } else {
914 mv[0].x = mb->pmv[0][1][0];
915 mv[0].y = mb->pmv[0][1][1] - (mb->pmv[0][1][1] % 4);
916
917 mv[1].x = mb->pmv[1][1][0];
918 mv[1].y = mb->pmv[1][1][1] - (mb->pmv[1][1][1] % 4);
919
920 if(mb->mvfs[0][1]) mv[0].y += 2;
921 if(!mb->mvfs[1][1]) mv[1].y -= 2;
922 }
923
924 } else {
925
926 if (mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FRAME) {
927 mv[0].x = mb->pmv[0][0][0];
928 mv[0].y = mb->pmv[0][0][1];
929
930 } else {
931 mv[0].x = mb->pmv[0][0][0];
932 mv[0].y = mb->pmv[0][0][1] - (mb->pmv[0][0][1] % 4);
933
934 mv[1].x = mb->pmv[1][0][0];
935 mv[1].y = mb->pmv[1][0][1] - (mb->pmv[1][0][1] % 4);
936
937 if(mb->mvfs[0][0]) mv[0].y += 2;
938 if(!mb->mvfs[1][0]) mv[1].y -= 2;
939 }
940 }
941 }
942 default:
943 break;
944 }
945 }
946
947 static bool
948 empty_block(enum pipe_video_chroma_format chroma_format,
949 unsigned cbp, unsigned component,
950 unsigned x, unsigned y)
951 {
952 /* TODO: Implement 422, 444 */
953 assert(chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420);
954
955 if(component == 0) /*luma*/
956 return !(cbp & (1 << (5 - (x + y * 2))));
957 else /*cr cb*/
958 return !(cbp & (1 << (2 - component)));
959 }
960
961 static void
962 grab_vectors(struct vl_mpeg12_mc_renderer *r,
963 struct pipe_mpeg12_macroblock *mb)
964 {
965 enum VL_MACROBLOCK_TYPE type;
966 struct vl_mc_mbtype_handler *handler;
967 struct vertex2f mv[4];
968 struct vertex_stream_0 info;
969
970 unsigned ref_frames, mv_per_frame;
971 unsigned i, j, pos;
972
973 assert(r);
974 assert(mb);
975
976 type = get_macroblock_type(mb);
977
978 ref_frames = const_mbtype_config[type][0];
979 mv_per_frame = const_mbtype_config[type][1];
980
981 handler = &r->mbtype_handlers[type];
982
983 pos = handler->pos.num_verts;
984
985 info.pos.x = mb->mbx;
986 info.pos.y = mb->mby;
987 for ( i = 0; i < 2; ++i) {
988 for ( j = 0; j < 2; ++j) {
989 info.eb[i][j].y = empty_block(r->chroma_format, mb->cbp, 0, j, i);
990 info.eb[i][j].cr = empty_block(r->chroma_format, mb->cbp, 1, j, i);
991 info.eb[i][j].cb = empty_block(r->chroma_format, mb->cbp, 2, j, i);
992 }
993 }
994 info.interlaced = mb->dct_type == PIPE_MPEG12_DCT_TYPE_FIELD ? 1.0f : 0.0f;
995 vl_vb_add_block(&handler->pos, (float*)&info);
996
997 get_motion_vectors(mb, mv);
998 for ( j = 0; j < ref_frames * mv_per_frame; ++j )
999 vl_vb_add_block(&handler->mv[j], (float*)&mv[j]);
1000 }
1001
1002 static void
1003 grab_blocks(struct vl_mpeg12_mc_renderer *r, unsigned mbx, unsigned mby,
1004 enum pipe_mpeg12_dct_type dct_type, unsigned cbp, short *blocks)
1005 {
1006 unsigned tb = 0;
1007 unsigned x, y;
1008
1009 assert(r);
1010 assert(blocks);
1011
1012 for (y = 0; y < 2; ++y) {
1013 for (x = 0; x < 2; ++x, ++tb) {
1014 if (!empty_block(r->chroma_format, cbp, 0, x, y)) {
1015 vl_idct_add_block(&r->idct_y, mbx * 2 + x, mby * 2 + y, blocks);
1016 blocks += BLOCK_WIDTH * BLOCK_HEIGHT;
1017 }
1018 }
1019 }
1020
1021 /* TODO: Implement 422, 444 */
1022 assert(r->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420);
1023
1024 for (tb = 1; tb < 3; ++tb) {
1025 if (!empty_block(r->chroma_format, cbp, tb, 0, 0)) {
1026 if(tb == 1)
1027 vl_idct_add_block(&r->idct_cb, mbx, mby, blocks);
1028 else
1029 vl_idct_add_block(&r->idct_cr, mbx, mby, blocks);
1030 blocks += BLOCK_WIDTH * BLOCK_HEIGHT;
1031 }
1032 }
1033 }
1034
1035 static void
1036 grab_macroblock(struct vl_mpeg12_mc_renderer *r,
1037 struct pipe_mpeg12_macroblock *mb)
1038 {
1039 assert(r);
1040 assert(mb);
1041 assert(mb->blocks);
1042 assert(r->num_macroblocks < r->macroblocks_per_batch);
1043
1044 grab_vectors(r, mb);
1045 grab_blocks(r, mb->mbx, mb->mby, mb->dct_type, mb->cbp, mb->blocks);
1046
1047 ++r->num_macroblocks;
1048 }
1049
1050 static void
1051 texview_map_delete(const struct keymap *map,
1052 const void *key, void *data,
1053 void *user)
1054 {
1055 struct pipe_sampler_view *sv = (struct pipe_sampler_view*)data;
1056
1057 assert(map);
1058 assert(key);
1059 assert(data);
1060 assert(user);
1061
1062 pipe_sampler_view_reference(&sv, NULL);
1063 }
1064
1065 bool
1066 vl_mpeg12_mc_renderer_init(struct vl_mpeg12_mc_renderer *renderer,
1067 struct pipe_context *pipe,
1068 unsigned buffer_width,
1069 unsigned buffer_height,
1070 enum pipe_video_chroma_format chroma_format,
1071 enum VL_MPEG12_MC_RENDERER_BUFFER_MODE bufmode)
1072 {
1073 assert(renderer);
1074 assert(pipe);
1075
1076 /* TODO: Implement other policies */
1077 assert(bufmode == VL_MPEG12_MC_RENDERER_BUFFER_PICTURE);
1078
1079 memset(renderer, 0, sizeof(struct vl_mpeg12_mc_renderer));
1080
1081 renderer->pipe = pipe;
1082 renderer->buffer_width = buffer_width;
1083 renderer->buffer_height = buffer_height;
1084 renderer->chroma_format = chroma_format;
1085 renderer->bufmode = bufmode;
1086
1087 renderer->texview_map = util_new_keymap(sizeof(struct pipe_surface*), -1,
1088 texview_map_delete);
1089 if (!renderer->texview_map)
1090 return false;
1091
1092 if (!init_pipe_state(renderer))
1093 goto error_pipe_state;
1094
1095 if (!init_buffers(renderer))
1096 goto error_buffers;
1097
1098 renderer->surface = NULL;
1099 renderer->past = NULL;
1100 renderer->future = NULL;
1101 renderer->num_macroblocks = 0;
1102
1103 return true;
1104
1105 error_buffers:
1106 cleanup_pipe_state(renderer);
1107
1108 error_pipe_state:
1109 util_delete_keymap(renderer->texview_map, renderer->pipe);
1110 return false;
1111 }
1112
1113 void
1114 vl_mpeg12_mc_renderer_cleanup(struct vl_mpeg12_mc_renderer *renderer)
1115 {
1116 assert(renderer);
1117
1118 util_delete_keymap(renderer->texview_map, renderer->pipe);
1119 cleanup_pipe_state(renderer);
1120 cleanup_buffers(renderer);
1121
1122 pipe_surface_reference(&renderer->surface, NULL);
1123 pipe_surface_reference(&renderer->past, NULL);
1124 pipe_surface_reference(&renderer->future, NULL);
1125 }
1126
1127 void
1128 vl_mpeg12_mc_renderer_render_macroblocks(struct vl_mpeg12_mc_renderer
1129 *renderer,
1130 struct pipe_surface *surface,
1131 struct pipe_surface *past,
1132 struct pipe_surface *future,
1133 unsigned num_macroblocks,
1134 struct pipe_mpeg12_macroblock
1135 *mpeg12_macroblocks,
1136 struct pipe_fence_handle **fence)
1137 {
1138 assert(renderer);
1139 assert(surface);
1140 assert(num_macroblocks);
1141 assert(mpeg12_macroblocks);
1142
1143 if (surface != renderer->surface) {
1144 pipe_surface_reference(&renderer->surface, surface);
1145 pipe_surface_reference(&renderer->past, past);
1146 pipe_surface_reference(&renderer->future, future);
1147 renderer->fence = fence;
1148 }
1149
1150 while (num_macroblocks) {
1151 unsigned left_in_batch = renderer->macroblocks_per_batch - renderer->num_macroblocks;
1152 unsigned num_to_submit = MIN2(num_macroblocks, left_in_batch);
1153 unsigned i;
1154
1155 for (i = 0; i < num_to_submit; ++i) {
1156 assert(mpeg12_macroblocks[i].base.codec == PIPE_VIDEO_CODEC_MPEG12);
1157 grab_macroblock(renderer, &mpeg12_macroblocks[i]);
1158 }
1159
1160 num_macroblocks -= num_to_submit;
1161
1162 if (renderer->num_macroblocks == renderer->macroblocks_per_batch) {
1163 vl_mpeg12_mc_renderer_flush(renderer);
1164
1165 /* Next time we get this surface it may have new ref frames */
1166 pipe_surface_reference(&renderer->surface, NULL);
1167 pipe_surface_reference(&renderer->past, NULL);
1168 pipe_surface_reference(&renderer->future, NULL);
1169 }
1170 }
1171 }
1172
1173 void
1174 vl_mpeg12_mc_renderer_flush(struct vl_mpeg12_mc_renderer *renderer)
1175 {
1176 unsigned num_verts[VL_NUM_MACROBLOCK_TYPES] = { 0 };
1177 unsigned vb_start = 0, i;
1178
1179 assert(renderer);
1180 assert(renderer->num_macroblocks <= renderer->macroblocks_per_batch);
1181
1182 if (renderer->num_macroblocks == 0)
1183 return;
1184
1185 vl_idct_unmap_buffers(&renderer->idct_luma, &renderer->idct_y);
1186 vl_idct_unmap_buffers(&renderer->idct_chroma, &renderer->idct_cr);
1187 vl_idct_unmap_buffers(&renderer->idct_chroma, &renderer->idct_cb);
1188
1189 vl_idct_flush(&renderer->idct_luma, &renderer->idct_y);
1190 vl_idct_flush(&renderer->idct_chroma, &renderer->idct_cr);
1191 vl_idct_flush(&renderer->idct_chroma, &renderer->idct_cb);
1192
1193 upload_vertex_stream(renderer, num_verts);
1194
1195 renderer->fb_state.cbufs[0] = renderer->surface;
1196 renderer->pipe->bind_rasterizer_state(renderer->pipe, renderer->rs_state);
1197 renderer->pipe->set_framebuffer_state(renderer->pipe, &renderer->fb_state);
1198 renderer->pipe->set_viewport_state(renderer->pipe, &renderer->viewport);
1199
1200 for (i = 0; i < VL_NUM_MACROBLOCK_TYPES; ++i) {
1201 if (num_verts[i] > 0)
1202 vb_start += flush_mbtype_handler(renderer, i, vb_start, num_verts[i]);
1203 }
1204
1205 renderer->pipe->flush(renderer->pipe, PIPE_FLUSH_RENDER_CACHE, renderer->fence);
1206
1207 vl_idct_map_buffers(&renderer->idct_luma, &renderer->idct_y);
1208 vl_idct_map_buffers(&renderer->idct_chroma, &renderer->idct_cr);
1209 vl_idct_map_buffers(&renderer->idct_chroma, &renderer->idct_cb);
1210
1211 renderer->num_macroblocks = 0;
1212 }