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