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