[g3dvl] fix of my one bug in SCALE_FACTOR_16_TO_9
[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 #define SCALE_FACTOR_16_TO_9 (32768.0f / 256.0f)
46
47 struct vertex_shader_consts
48 {
49 struct vertex4f norm;
50 };
51
52 struct fragment_shader_consts
53 {
54 struct vertex4f multiplier;
55 struct vertex4f div;
56 };
57
58 struct vert_stream_0
59 {
60 struct vertex2f pos;
61
62 struct {
63 float luma_eb;
64 float cb_eb;
65 float cr_eb;
66 } field[2][2];
67
68 float interlaced;
69 };
70
71 enum VS_INPUT
72 {
73 VS_I_RECT,
74 VS_I_VPOS,
75 VS_I_EB_0_0,
76 VS_I_EB_0_1,
77 VS_I_EB_1_0,
78 VS_I_EB_1_1,
79 VS_I_INTERLACED,
80 VS_I_MV0,
81 VS_I_MV1,
82 VS_I_MV2,
83 VS_I_MV3,
84
85 NUM_VS_INPUTS
86 };
87
88 enum VS_OUTPUT
89 {
90 VS_O_VPOS,
91 VS_O_LINE,
92 VS_O_TEX0,
93 VS_O_TEX1,
94 VS_O_TEX2,
95 VS_O_EB_0_0,
96 VS_O_EB_0_1,
97 VS_O_EB_1_0,
98 VS_O_EB_1_1,
99 VS_O_INTERLACED,
100 VS_O_MV0,
101 VS_O_MV1,
102 VS_O_MV2,
103 VS_O_MV3
104 };
105
106 enum MACROBLOCK_TYPE
107 {
108 MACROBLOCK_TYPE_INTRA,
109 MACROBLOCK_TYPE_FWD_FRAME_PRED,
110 MACROBLOCK_TYPE_FWD_FIELD_PRED,
111 MACROBLOCK_TYPE_BKWD_FRAME_PRED,
112 MACROBLOCK_TYPE_BKWD_FIELD_PRED,
113 MACROBLOCK_TYPE_BI_FRAME_PRED,
114 MACROBLOCK_TYPE_BI_FIELD_PRED,
115
116 NUM_MACROBLOCK_TYPES
117 };
118
119 /* vertices for four quads covering the blocks */
120 static const struct vertex2f const_quad[4] = {
121 {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f}
122 };
123
124 static void *
125 create_vert_shader(struct vl_mpeg12_mc_renderer *r, unsigned ref_frames, unsigned mv_per_frame)
126 {
127 struct ureg_program *shader;
128 struct ureg_src norm, mbs;
129 struct ureg_src vrect, vpos, eb[2][2], interlaced, vmv[4];
130 struct ureg_dst scale, t_vpos, t_vtex;
131 struct ureg_dst o_vpos, o_line, o_vtex[3], o_eb[2][2], o_interlaced, o_vmv[4];
132 unsigned i, j, count, label;
133
134 shader = ureg_create(TGSI_PROCESSOR_VERTEX);
135 if (!shader)
136 return NULL;
137
138 norm = ureg_DECL_constant(shader, 0);
139 mbs = ureg_imm2f(shader, MACROBLOCK_WIDTH, MACROBLOCK_HEIGHT);
140
141 scale = ureg_DECL_temporary(shader);
142 t_vpos = ureg_DECL_temporary(shader);
143 t_vtex = ureg_DECL_temporary(shader);
144
145 vrect = ureg_DECL_vs_input(shader, VS_I_RECT);
146 vpos = ureg_DECL_vs_input(shader, VS_I_VPOS);
147 eb[0][0] = ureg_DECL_vs_input(shader, VS_I_EB_0_0);
148 eb[1][0] = ureg_DECL_vs_input(shader, VS_I_EB_1_0);
149 eb[0][1] = ureg_DECL_vs_input(shader, VS_I_EB_0_1);
150 eb[1][1] = ureg_DECL_vs_input(shader, VS_I_EB_1_1);
151 interlaced = ureg_DECL_vs_input(shader, VS_I_INTERLACED);
152
153 o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, VS_O_VPOS);
154 o_line = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_LINE);
155 o_vtex[0] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_TEX0);
156 o_vtex[1] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_TEX1);
157 o_vtex[2] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_TEX2);
158 o_eb[0][0] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_EB_0_0);
159 o_eb[0][1] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_EB_0_1);
160 o_eb[1][0] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_EB_1_0);
161 o_eb[1][1] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_EB_1_1);
162 o_interlaced = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_INTERLACED);
163
164 count=0;
165 for (i = 0; i < ref_frames; ++i) {
166 for (j = 0; j < 2; ++j) {
167 if(j < mv_per_frame) {
168 vmv[count] = ureg_DECL_vs_input(shader, VS_I_MV0 + i * 2 + j);
169 o_vmv[count] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_MV0 + count);
170 count++;
171 }
172 /* workaround for r600g */
173 else if(ref_frames == 2)
174 ureg_DECL_vs_input(shader, VS_I_MV0 + i * 2 + j);
175 }
176 }
177
178 /*
179 * scale = norm * mbs;
180 *
181 * t_vpos = (vpos + vrect) * scale
182 * o_vpos.xy = t_vpos
183 * o_vpos.zw = vpos
184 *
185 * o_line = vpos * 8
186 *
187 * if(interlaced) {
188 * t_vtex.x = vrect.x
189 * t_vtex.y = vrect.y * 0.5
190 * t_vtex += vpos
191 *
192 * o_vtex[0].xy = t_vtex * scale
193 *
194 * t_vtex.y += 0.5
195 * o_vtex[1].xy = t_vtex * scale
196 * } else {
197 * o_vtex[0..1].xy = t_vpos
198 * }
199 * o_vtex[2].xy = t_vpos
200 *
201 * if(count > 0) { // Apply motion vectors
202 * scale = norm * 0.5;
203 * o_vmv[0..count] = t_vpos + vmv[0..4] * scale
204 * }
205 *
206 */
207 ureg_MUL(shader, ureg_writemask(scale, TGSI_WRITEMASK_XY), norm, mbs);
208
209 ureg_ADD(shader, ureg_writemask(t_vpos, TGSI_WRITEMASK_XY), vpos, vrect);
210 ureg_MUL(shader, ureg_writemask(t_vpos, TGSI_WRITEMASK_XY), ureg_src(t_vpos), ureg_src(scale));
211 ureg_MOV(shader, ureg_writemask(o_vpos, TGSI_WRITEMASK_XY), ureg_src(t_vpos));
212 ureg_MOV(shader, ureg_writemask(o_vpos, TGSI_WRITEMASK_ZW), vpos);
213
214 ureg_MUL(shader, ureg_writemask(o_line, TGSI_WRITEMASK_XY), vrect,
215 ureg_imm2f(shader, MACROBLOCK_WIDTH / 2, MACROBLOCK_HEIGHT / 2));
216
217 ureg_IF(shader, interlaced, &label);
218
219 ureg_MOV(shader, ureg_writemask(t_vtex, TGSI_WRITEMASK_X), vrect);
220 ureg_MUL(shader, ureg_writemask(t_vtex, TGSI_WRITEMASK_Y), vrect, ureg_imm1f(shader, 0.5f));
221 ureg_ADD(shader, ureg_writemask(t_vtex, TGSI_WRITEMASK_XY), vpos, ureg_src(t_vtex));
222 ureg_MUL(shader, ureg_writemask(o_vtex[0], TGSI_WRITEMASK_XY), ureg_src(t_vtex), ureg_src(scale));
223 ureg_ADD(shader, ureg_writemask(t_vtex, TGSI_WRITEMASK_Y), ureg_src(t_vtex), ureg_imm1f(shader, 0.5f));
224 ureg_MUL(shader, ureg_writemask(o_vtex[1], TGSI_WRITEMASK_XY), ureg_src(t_vtex), ureg_src(scale));
225
226 ureg_ELSE(shader, &label);
227
228 ureg_MOV(shader, ureg_writemask(o_vtex[0], TGSI_WRITEMASK_XY), ureg_src(t_vpos));
229 ureg_MOV(shader, ureg_writemask(o_vtex[1], TGSI_WRITEMASK_XY), ureg_src(t_vpos));
230
231 ureg_ENDIF(shader);
232 ureg_MOV(shader, ureg_writemask(o_vtex[2], TGSI_WRITEMASK_XY), ureg_src(t_vpos));
233
234 ureg_MOV(shader, o_eb[0][0], eb[0][0]);
235 ureg_MOV(shader, o_eb[0][1], eb[0][1]);
236 ureg_MOV(shader, o_eb[1][0], eb[1][0]);
237 ureg_MOV(shader, o_eb[1][1], eb[1][1]);
238
239 ureg_MOV(shader, o_interlaced, interlaced);
240
241 if(count > 0) {
242 ureg_MUL(shader, ureg_writemask(scale, TGSI_WRITEMASK_XY), norm, ureg_imm1f(shader, 0.5f));
243 for (i = 0; i < count; ++i)
244 ureg_MAD(shader, ureg_writemask(o_vmv[i], TGSI_WRITEMASK_XY), ureg_src(scale), vmv[i], ureg_src(t_vpos));
245 }
246
247 ureg_release_temporary(shader, t_vtex);
248 ureg_release_temporary(shader, t_vpos);
249 ureg_release_temporary(shader, scale);
250
251 ureg_END(shader);
252
253 return ureg_create_shader_and_destroy(shader, r->pipe);
254 }
255
256 static struct ureg_dst
257 calc_field(struct ureg_program *shader)
258 {
259 struct ureg_dst tmp;
260 struct ureg_src line;
261
262 tmp = ureg_DECL_temporary(shader);
263 line = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_LINE, TGSI_INTERPOLATE_LINEAR);
264
265 /*
266 * line going from 0 to 8 in steps of 0.5
267 *
268 * tmp.z = fraction(line.y)
269 * tmp.z = tmp.z >= 0.5 ? 1 : 0
270 * tmp.xy = line > 4 ? 1 : 0
271 */
272 ureg_FRC(shader, ureg_writemask(tmp, TGSI_WRITEMASK_Z), ureg_scalar(line, TGSI_SWIZZLE_Y));
273 ureg_SGE(shader, ureg_writemask(tmp, TGSI_WRITEMASK_Z), ureg_src(tmp), ureg_imm1f(shader, 0.5f));
274 ureg_SGE(shader, ureg_writemask(tmp, TGSI_WRITEMASK_XY), line, ureg_imm2f(shader, BLOCK_WIDTH / 2, BLOCK_HEIGHT / 2));
275
276 return tmp;
277 }
278
279 static struct ureg_dst
280 fetch_ycbcr(struct vl_mpeg12_mc_renderer *r, struct ureg_program *shader, struct ureg_dst field)
281 {
282 struct ureg_src tc[3], eb[2][2], interlaced;
283 struct ureg_src sampler[3];
284 struct ureg_dst texel, t_tc, t_field, tmp;
285 unsigned i, l_interlaced, l_y, l_x;
286
287 texel = ureg_DECL_temporary(shader);
288 t_tc = ureg_DECL_temporary(shader);
289 t_field = ureg_DECL_temporary(shader);
290 tmp = ureg_DECL_temporary(shader);
291
292 tc[0] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_TEX0, TGSI_INTERPOLATE_LINEAR);
293 tc[1] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_TEX1, TGSI_INTERPOLATE_LINEAR);
294 tc[2] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_TEX2, TGSI_INTERPOLATE_LINEAR);
295
296 eb[0][0] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_EB_0_0, TGSI_INTERPOLATE_CONSTANT);
297 eb[0][1] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_EB_0_1, TGSI_INTERPOLATE_CONSTANT);
298 eb[1][0] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_EB_1_0, TGSI_INTERPOLATE_CONSTANT);
299 eb[1][1] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_EB_1_1, TGSI_INTERPOLATE_CONSTANT);
300
301 interlaced = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_INTERLACED, TGSI_INTERPOLATE_CONSTANT);
302
303 for (i = 0; i < 3; ++i) {
304 sampler[i] = ureg_DECL_sampler(shader, i);
305 }
306
307 /*
308 * texel.y = tex(field ? tc[1] : tc[0], sampler[0])
309 * texel.cb = tex(tc[2], sampler[1])
310 * texel.cr = tex(tc[2], sampler[2])
311 */
312 ureg_MOV(shader, ureg_writemask(t_field, TGSI_WRITEMASK_XY), ureg_src(field));
313 ureg_IF(shader, interlaced, &l_interlaced);
314 ureg_MOV(shader, ureg_writemask(t_field, TGSI_WRITEMASK_Y), ureg_scalar(ureg_src(field), TGSI_SWIZZLE_Z));
315 ureg_ENDIF(shader);
316
317 for (i = 0; i < 3; ++i) {
318 if(i==0 || r->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_444) {
319 ureg_IF(shader, ureg_scalar(ureg_src(t_field), TGSI_SWIZZLE_Y), &l_y);
320 ureg_MOV(shader, ureg_writemask(t_tc, TGSI_WRITEMASK_XY), tc[1]);
321
322 ureg_IF(shader, ureg_scalar(ureg_src(t_field), TGSI_SWIZZLE_X), &l_x);
323 ureg_MOV(shader, ureg_writemask(t_tc, TGSI_WRITEMASK_Z), ureg_scalar(eb[1][1], TGSI_SWIZZLE_X + i));
324 ureg_ELSE(shader, &l_x);
325 ureg_MOV(shader, ureg_writemask(t_tc, TGSI_WRITEMASK_Z), ureg_scalar(eb[1][0], TGSI_SWIZZLE_X + i));
326 ureg_ENDIF(shader);
327
328 ureg_ELSE(shader, &l_y);
329 ureg_MOV(shader, ureg_writemask(t_tc, TGSI_WRITEMASK_XY), tc[0]);
330
331 ureg_IF(shader, ureg_scalar(ureg_src(t_field), TGSI_SWIZZLE_X), &l_x);
332 ureg_MOV(shader, ureg_writemask(t_tc, TGSI_WRITEMASK_Z), ureg_scalar(eb[0][1], TGSI_SWIZZLE_X + i));
333 ureg_ELSE(shader, &l_x);
334 ureg_MOV(shader, ureg_writemask(t_tc, TGSI_WRITEMASK_Z), ureg_scalar(eb[0][0], TGSI_SWIZZLE_X + i));
335 ureg_ENDIF(shader);
336
337 ureg_ENDIF(shader);
338
339 } else {
340 ureg_MOV(shader, ureg_writemask(t_tc, TGSI_WRITEMASK_XY), tc[2]);
341 ureg_MOV(shader, ureg_writemask(t_tc, TGSI_WRITEMASK_Z), ureg_scalar(eb[0][0], TGSI_SWIZZLE_X + i));
342 }
343
344 /* Nouveau can't writemask tex dst regs (yet?), do in two steps */
345 ureg_TEX(shader, tmp, TGSI_TEXTURE_3D, ureg_src(t_tc), sampler[i]);
346 ureg_MOV(shader, ureg_writemask(texel, TGSI_WRITEMASK_X << i), ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X));
347 }
348
349 ureg_release_temporary(shader, t_field);
350 ureg_release_temporary(shader, t_tc);
351 ureg_release_temporary(shader, tmp);
352
353 return texel;
354 }
355
356 static void *
357 create_intra_frag_shader(struct vl_mpeg12_mc_renderer *r)
358 {
359 struct ureg_program *shader;
360 struct ureg_dst field, texel;
361 struct ureg_dst fragment;
362
363 shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
364 if (!shader)
365 return NULL;
366
367 fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
368
369 /*
370 * texel = fetch_ycbcr()
371 * fragment = texel * scale
372 */
373 field = calc_field(shader);
374 texel = fetch_ycbcr(r, shader, field);
375 ureg_MUL(shader, fragment, ureg_src(texel), ureg_scalar(ureg_imm1f(shader, SCALE_FACTOR_16_TO_9), TGSI_SWIZZLE_X));
376
377 ureg_release_temporary(shader, field);
378 ureg_release_temporary(shader, texel);
379 ureg_END(shader);
380
381 return ureg_create_shader_and_destroy(shader, r->pipe);
382 }
383
384 static void *
385 create_frame_pred_frag_shader(struct vl_mpeg12_mc_renderer *r)
386 {
387 struct ureg_program *shader;
388 struct ureg_src tc;
389 struct ureg_src sampler;
390 struct ureg_dst field, texel, ref;
391 struct ureg_dst fragment;
392
393 shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
394 if (!shader)
395 return NULL;
396
397 tc = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_MV0, TGSI_INTERPOLATE_LINEAR);
398 sampler = ureg_DECL_sampler(shader, 3);
399
400 ref = ureg_DECL_temporary(shader);
401 fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
402
403 /*
404 * texel = fetch_ycbcr()
405 * ref = tex(tc, sampler)
406 * fragment = texel * scale + ref
407 */
408 field = calc_field(shader);
409 texel = fetch_ycbcr(r, shader, field);
410 ureg_TEX(shader, ref, TGSI_TEXTURE_2D, tc, sampler);
411 ureg_MAD(shader, fragment, ureg_src(texel), ureg_scalar(ureg_imm1f(shader, SCALE_FACTOR_16_TO_9), TGSI_SWIZZLE_X), ureg_src(ref));
412
413 ureg_release_temporary(shader, field);
414 ureg_release_temporary(shader, texel);
415 ureg_release_temporary(shader, ref);
416 ureg_END(shader);
417
418 return ureg_create_shader_and_destroy(shader, r->pipe);
419 }
420
421 static void *
422 create_field_pred_frag_shader(struct vl_mpeg12_mc_renderer *r)
423 {
424 struct ureg_program *shader;
425 struct ureg_src tc[2];
426 struct ureg_src sampler;
427 struct ureg_dst texel, ref, field;
428 struct ureg_dst fragment;
429 unsigned i, label;
430
431 shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
432 if (!shader)
433 return NULL;
434
435 for (i = 0; i < 2; ++i)
436 tc[i] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_MV0 + i, TGSI_INTERPOLATE_LINEAR);
437 sampler = ureg_DECL_sampler(shader, 3);
438
439 ref = ureg_DECL_temporary(shader);
440 fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
441
442 /*
443 * texel = fetch_ycbcr()
444 * field = calc_field();
445 * if(field == 1)
446 * ref = tex(tc[1], sampler)
447 * else
448 * ref = tex(tc[0], sampler)
449 * fragment = texel * scale + ref
450 */
451 field = calc_field(shader);
452 texel = fetch_ycbcr(r, shader, field);
453
454 ureg_IF(shader, ureg_scalar(ureg_src(field), TGSI_SWIZZLE_Z), &label);
455 ureg_TEX(shader, ref, TGSI_TEXTURE_2D, tc[1], sampler);
456 ureg_ELSE(shader, &label);
457 ureg_TEX(shader, ref, TGSI_TEXTURE_2D, tc[0], sampler);
458 ureg_ENDIF(shader);
459
460 ureg_MAD(shader, fragment, ureg_src(texel), ureg_scalar(ureg_imm1f(shader, SCALE_FACTOR_16_TO_9), TGSI_SWIZZLE_X), ureg_src(ref));
461
462 ureg_release_temporary(shader, field);
463 ureg_release_temporary(shader, texel);
464 ureg_release_temporary(shader, ref);
465 ureg_END(shader);
466
467 return ureg_create_shader_and_destroy(shader, r->pipe);
468 }
469
470 static void *
471 create_frame_bi_pred_frag_shader(struct vl_mpeg12_mc_renderer *r)
472 {
473 struct ureg_program *shader;
474 struct ureg_src tc[2];
475 struct ureg_src sampler[2];
476 struct ureg_dst field, texel, ref[2];
477 struct ureg_dst fragment;
478 unsigned i;
479
480 shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
481 if (!shader)
482 return NULL;
483
484 for (i = 0; i < 2; ++i) {
485 tc[i] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_MV0 + i, TGSI_INTERPOLATE_LINEAR);
486 sampler[i] = ureg_DECL_sampler(shader, i + 3);
487 }
488
489 ref[0] = ureg_DECL_temporary(shader);
490 ref[1] = ureg_DECL_temporary(shader);
491 fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
492
493 /*
494 * texel = fetch_ycbcr()
495 * ref[0..1 = tex(tc[3..4], sampler[3..4])
496 * ref[0] = lerp(ref[0], ref[1], 0.5)
497 * fragment = texel * scale + ref[0]
498 */
499 field = calc_field(shader);
500 texel = fetch_ycbcr(r, shader, field);
501 ureg_TEX(shader, ref[0], TGSI_TEXTURE_2D, tc[0], sampler[0]);
502 ureg_TEX(shader, ref[1], TGSI_TEXTURE_2D, tc[1], sampler[1]);
503 ureg_LRP(shader, ref[0], ureg_scalar(ureg_imm1f(shader, 0.5f), TGSI_SWIZZLE_X), ureg_src(ref[0]), ureg_src(ref[1]));
504
505 ureg_MAD(shader, fragment, ureg_src(texel), ureg_scalar(ureg_imm1f(shader, SCALE_FACTOR_16_TO_9), TGSI_SWIZZLE_X), ureg_src(ref[0]));
506
507 ureg_release_temporary(shader, field);
508 ureg_release_temporary(shader, texel);
509 ureg_release_temporary(shader, ref[0]);
510 ureg_release_temporary(shader, ref[1]);
511 ureg_END(shader);
512
513 return ureg_create_shader_and_destroy(shader, r->pipe);
514 }
515
516 static void *
517 create_field_bi_pred_frag_shader(struct vl_mpeg12_mc_renderer *r)
518 {
519 struct ureg_program *shader;
520 struct ureg_src tc[4];
521 struct ureg_src sampler[2];
522 struct ureg_dst texel, ref[2], field;
523 struct ureg_dst fragment;
524 unsigned i, label;
525
526 shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
527 if (!shader)
528 return NULL;
529
530 for (i = 0; i < 4; ++i)
531 tc[i] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_MV0 + i, TGSI_INTERPOLATE_LINEAR);
532 for (i = 0; i < 2; ++i)
533 sampler[i] = ureg_DECL_sampler(shader, i + 3);
534
535 texel = ureg_DECL_temporary(shader);
536 ref[0] = ureg_DECL_temporary(shader);
537 ref[1] = ureg_DECL_temporary(shader);
538 fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
539
540 /*
541 * texel = fetch_ycbcr()
542 * if(field == 1)
543 * ref[0..1] = tex(tc[1|3], sampler[0..1])
544 * else
545 * ref[0..1] = tex(tc[0|2], sampler[0..1])
546 * ref[0] = lerp(ref[0], ref[1], 0.5)
547 * fragment = texel * scale + ref[0]
548 */
549 field = calc_field(shader);
550 texel = fetch_ycbcr(r, shader, field);
551
552 ureg_IF(shader, ureg_scalar(ureg_src(field), TGSI_SWIZZLE_Z), &label);
553 ureg_TEX(shader, ref[0], TGSI_TEXTURE_2D, tc[1], sampler[0]);
554 ureg_TEX(shader, ref[1], TGSI_TEXTURE_2D, tc[3], sampler[1]);
555 ureg_ELSE(shader, &label);
556 ureg_TEX(shader, ref[0], TGSI_TEXTURE_2D, tc[0], sampler[0]);
557 ureg_TEX(shader, ref[1], TGSI_TEXTURE_2D, tc[2], sampler[1]);
558 ureg_ENDIF(shader);
559
560 ureg_LRP(shader, ref[0], ureg_scalar(ureg_imm1f(shader, 0.5f), TGSI_SWIZZLE_X), ureg_src(ref[0]), ureg_src(ref[1]));
561
562 ureg_MAD(shader, fragment, ureg_src(texel), ureg_scalar(ureg_imm1f(shader, SCALE_FACTOR_16_TO_9), TGSI_SWIZZLE_X), ureg_src(ref[0]));
563
564 ureg_release_temporary(shader, field);
565 ureg_release_temporary(shader, texel);
566 ureg_release_temporary(shader, ref[0]);
567 ureg_release_temporary(shader, ref[1]);
568 ureg_END(shader);
569
570 return ureg_create_shader_and_destroy(shader, r->pipe);
571 }
572
573 static void
574 xfer_buffers_map(struct vl_mpeg12_mc_renderer *r)
575 {
576 unsigned i;
577
578 assert(r);
579
580 for (i = 0; i < 3; ++i) {
581 struct pipe_box rect =
582 {
583 0, 0, 0,
584 r->textures.all[i]->width0,
585 r->textures.all[i]->height0,
586 1
587 };
588
589 r->tex_transfer[i] = r->pipe->get_transfer
590 (
591 r->pipe, r->textures.all[i],
592 u_subresource(0, 0),
593 PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD,
594 &rect
595 );
596
597 r->texels[i] = r->pipe->transfer_map(r->pipe, r->tex_transfer[i]);
598 }
599 }
600
601 static void
602 xfer_buffers_unmap(struct vl_mpeg12_mc_renderer *r)
603 {
604 unsigned i;
605
606 assert(r);
607
608 for (i = 0; i < 3; ++i) {
609 r->pipe->transfer_unmap(r->pipe, r->tex_transfer[i]);
610 r->pipe->transfer_destroy(r->pipe, r->tex_transfer[i]);
611 }
612 }
613
614 static bool
615 init_pipe_state(struct vl_mpeg12_mc_renderer *r)
616 {
617 struct pipe_sampler_state sampler;
618 unsigned filters[5];
619 unsigned i;
620
621 assert(r);
622
623 r->viewport.scale[0] = r->pot_buffers ?
624 util_next_power_of_two(r->picture_width) : r->picture_width;
625 r->viewport.scale[1] = r->pot_buffers ?
626 util_next_power_of_two(r->picture_height) : r->picture_height;
627 r->viewport.scale[2] = 1;
628 r->viewport.scale[3] = 1;
629 r->viewport.translate[0] = 0;
630 r->viewport.translate[1] = 0;
631 r->viewport.translate[2] = 0;
632 r->viewport.translate[3] = 0;
633
634 r->fb_state.width = r->pot_buffers ?
635 util_next_power_of_two(r->picture_width) : r->picture_width;
636 r->fb_state.height = r->pot_buffers ?
637 util_next_power_of_two(r->picture_height) : r->picture_height;
638 r->fb_state.nr_cbufs = 1;
639 r->fb_state.zsbuf = NULL;
640
641 /* Luma filter */
642 filters[0] = PIPE_TEX_FILTER_NEAREST;
643 /* Chroma filters */
644 if (r->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_444 || true) { //TODO
645 filters[1] = PIPE_TEX_FILTER_NEAREST;
646 filters[2] = PIPE_TEX_FILTER_NEAREST;
647 }
648 else {
649 filters[1] = PIPE_TEX_FILTER_LINEAR;
650 filters[2] = PIPE_TEX_FILTER_LINEAR;
651 }
652 /* Fwd, bkwd ref filters */
653 filters[3] = PIPE_TEX_FILTER_LINEAR;
654 filters[4] = PIPE_TEX_FILTER_LINEAR;
655
656 for (i = 0; i < 5; ++i) {
657 memset(&sampler, 0, sizeof(sampler));
658 sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
659 sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
660 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_BORDER;
661 sampler.min_img_filter = filters[i];
662 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
663 sampler.mag_img_filter = filters[i];
664 sampler.compare_mode = PIPE_TEX_COMPARE_NONE;
665 sampler.compare_func = PIPE_FUNC_ALWAYS;
666 sampler.normalized_coords = 1;
667 /*sampler.shadow_ambient = ; */
668 /*sampler.lod_bias = ; */
669 sampler.min_lod = 0;
670 /*sampler.max_lod = ; */
671 sampler.border_color[0] = 0.0f;
672 sampler.border_color[1] = 0.0f;
673 sampler.border_color[2] = 0.0f;
674 sampler.border_color[3] = 0.0f;
675 /*sampler.max_anisotropy = ; */
676 r->samplers.all[i] = r->pipe->create_sampler_state(r->pipe, &sampler);
677 }
678
679 return true;
680 }
681
682 static void
683 cleanup_pipe_state(struct vl_mpeg12_mc_renderer *r)
684 {
685 unsigned i;
686
687 assert(r);
688
689 for (i = 0; i < 5; ++i)
690 r->pipe->delete_sampler_state(r->pipe, r->samplers.all[i]);
691 }
692
693 static bool
694 init_shaders(struct vl_mpeg12_mc_renderer *r)
695 {
696 assert(r);
697
698 assert(r->i_vs = create_vert_shader(r, 0, 0));
699 assert(r->i_fs = create_intra_frag_shader(r));
700
701 assert(r->p_vs[0] = create_vert_shader(r, 1, 1));
702 assert(r->p_vs[1] = create_vert_shader(r, 1, 2));
703 assert(r->p_fs[0] = create_frame_pred_frag_shader(r));
704 assert(r->p_fs[1] = create_field_pred_frag_shader(r));
705
706 assert(r->b_vs[0] = create_vert_shader(r, 2, 1));
707 assert(r->b_vs[1] = create_vert_shader(r, 2, 2));
708 assert(r->b_fs[0] = create_frame_bi_pred_frag_shader(r));
709 assert(r->b_fs[1] = create_field_bi_pred_frag_shader(r));
710
711 return true;
712 }
713
714 static void
715 cleanup_shaders(struct vl_mpeg12_mc_renderer *r)
716 {
717 assert(r);
718
719 r->pipe->delete_vs_state(r->pipe, r->i_vs);
720 r->pipe->delete_fs_state(r->pipe, r->i_fs);
721 r->pipe->delete_vs_state(r->pipe, r->p_vs[0]);
722 r->pipe->delete_vs_state(r->pipe, r->p_vs[1]);
723 r->pipe->delete_fs_state(r->pipe, r->p_fs[0]);
724 r->pipe->delete_fs_state(r->pipe, r->p_fs[1]);
725 r->pipe->delete_vs_state(r->pipe, r->b_vs[0]);
726 r->pipe->delete_vs_state(r->pipe, r->b_vs[1]);
727 r->pipe->delete_fs_state(r->pipe, r->b_fs[0]);
728 r->pipe->delete_fs_state(r->pipe, r->b_fs[1]);
729 }
730
731 static bool
732 init_buffers(struct vl_mpeg12_mc_renderer *r)
733 {
734 struct pipe_resource template;
735 struct pipe_vertex_element vertex_elems[NUM_VS_INPUTS];
736 struct pipe_sampler_view sampler_view;
737
738 const unsigned mbw =
739 align(r->picture_width, MACROBLOCK_WIDTH) / MACROBLOCK_WIDTH;
740 const unsigned mbh =
741 align(r->picture_height, MACROBLOCK_HEIGHT) / MACROBLOCK_HEIGHT;
742
743 unsigned i;
744
745 assert(r);
746
747 r->macroblocks_per_batch =
748 mbw * (r->bufmode == VL_MPEG12_MC_RENDERER_BUFFER_PICTURE ? mbh : 1);
749 r->num_macroblocks = 0;
750 r->macroblock_buf = MALLOC(r->macroblocks_per_batch * sizeof(struct pipe_mpeg12_macroblock));
751
752 memset(&template, 0, sizeof(struct pipe_resource));
753 template.target = PIPE_TEXTURE_3D;
754 /* TODO: Accomodate HW that can't do this and also for cases when this isn't precise enough */
755 template.format = PIPE_FORMAT_R16_SNORM;
756 template.last_level = 0;
757 template.width0 = r->pot_buffers ?
758 util_next_power_of_two(r->picture_width) : r->picture_width;
759 template.height0 = r->pot_buffers ?
760 util_next_power_of_two(r->picture_height) : r->picture_height;
761 template.depth0 = 1;
762 template.usage = PIPE_USAGE_DYNAMIC;
763 template.bind = PIPE_BIND_SAMPLER_VIEW;
764 template.flags = 0;
765
766 r->textures.individual.y = r->pipe->screen->resource_create(r->pipe->screen, &template);
767
768 if (r->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420) {
769 template.width0 = r->pot_buffers ?
770 util_next_power_of_two(r->picture_width / 2) :
771 r->picture_width / 2;
772 template.height0 = r->pot_buffers ?
773 util_next_power_of_two(r->picture_height / 2) :
774 r->picture_height / 2;
775 }
776 else if (r->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_422)
777 template.height0 = r->pot_buffers ?
778 util_next_power_of_two(r->picture_height / 2) :
779 r->picture_height / 2;
780
781 r->textures.individual.cb =
782 r->pipe->screen->resource_create(r->pipe->screen, &template);
783 r->textures.individual.cr =
784 r->pipe->screen->resource_create(r->pipe->screen, &template);
785
786 for (i = 0; i < 3; ++i) {
787 u_sampler_view_default_template(&sampler_view,
788 r->textures.all[i],
789 r->textures.all[i]->format);
790 r->sampler_views.all[i] = r->pipe->create_sampler_view(r->pipe, r->textures.all[i], &sampler_view);
791 }
792
793 r->vertex_bufs.individual.rect.stride = sizeof(struct vertex2f);
794 r->vertex_bufs.individual.rect.max_index = 4 * r->macroblocks_per_batch - 1;
795 r->vertex_bufs.individual.rect.buffer_offset = 0;
796 r->vertex_bufs.individual.rect.buffer = pipe_buffer_create
797 (
798 r->pipe->screen,
799 PIPE_BIND_VERTEX_BUFFER,
800 sizeof(struct vertex2f) * 4 * r->macroblocks_per_batch
801 );
802
803 r->vertex_bufs.individual.ycbcr.stride = sizeof(struct vert_stream_0);
804 r->vertex_bufs.individual.ycbcr.max_index = 4 * r->macroblocks_per_batch - 1;
805 r->vertex_bufs.individual.ycbcr.buffer_offset = 0;
806 /* XXX: Create with usage DYNAMIC or STREAM */
807 r->vertex_bufs.individual.ycbcr.buffer = pipe_buffer_create
808 (
809 r->pipe->screen,
810 PIPE_BIND_VERTEX_BUFFER,
811 sizeof(struct vert_stream_0) * 4 * r->macroblocks_per_batch
812 );
813
814 for (i = 0; i < 2; ++i) {
815 r->vertex_bufs.individual.ref[i].stride = sizeof(struct vertex2f) * 2;
816 r->vertex_bufs.individual.ref[i].max_index = 4 * r->macroblocks_per_batch - 1;
817 r->vertex_bufs.individual.ref[i].buffer_offset = 0;
818 /* XXX: Create with usage DYNAMIC or STREAM */
819 r->vertex_bufs.individual.ref[i].buffer = pipe_buffer_create
820 (
821 r->pipe->screen,
822 PIPE_BIND_VERTEX_BUFFER,
823 sizeof(struct vertex2f) * 2 * 4 * r->macroblocks_per_batch
824 );
825 }
826
827 memset(&vertex_elems, 0, sizeof(vertex_elems));
828
829 /* Rectangle element */
830 vertex_elems[VS_I_RECT].src_offset = 0;
831 vertex_elems[VS_I_RECT].instance_divisor = 0;
832 vertex_elems[VS_I_RECT].vertex_buffer_index = 0;
833 vertex_elems[VS_I_RECT].src_format = PIPE_FORMAT_R32G32_FLOAT;
834
835 /* Position element */
836 vertex_elems[VS_I_VPOS].src_offset = 0;
837 vertex_elems[VS_I_VPOS].instance_divisor = 0;
838 vertex_elems[VS_I_VPOS].vertex_buffer_index = 1;
839 vertex_elems[VS_I_VPOS].src_format = PIPE_FORMAT_R32G32_FLOAT;
840
841 /* y, cr, cb z-coordinate element top left block */
842 vertex_elems[VS_I_EB_0_0].src_offset = sizeof(struct vertex2f);
843 vertex_elems[VS_I_EB_0_0].instance_divisor = 0;
844 vertex_elems[VS_I_EB_0_0].vertex_buffer_index = 1;
845 vertex_elems[VS_I_EB_0_0].src_format = PIPE_FORMAT_R32G32B32_FLOAT;
846
847 /* y, cr, cb z-coordinate element top right block */
848 vertex_elems[VS_I_EB_0_1].src_offset = sizeof(struct vertex2f) + sizeof(float) * 3;
849 vertex_elems[VS_I_EB_0_1].instance_divisor = 0;
850 vertex_elems[VS_I_EB_0_1].vertex_buffer_index = 1;
851 vertex_elems[VS_I_EB_0_1].src_format = PIPE_FORMAT_R32G32B32_FLOAT;
852
853 /* y, cr, cb z-coordinate element bottom left block */
854 vertex_elems[VS_I_EB_1_0].src_offset = sizeof(struct vertex2f) + sizeof(float) * 6;
855 vertex_elems[VS_I_EB_1_0].instance_divisor = 0;
856 vertex_elems[VS_I_EB_1_0].vertex_buffer_index = 1;
857 vertex_elems[VS_I_EB_1_0].src_format = PIPE_FORMAT_R32G32B32_FLOAT;
858
859 /* y, cr, cb z-coordinate element bottom right block */
860 vertex_elems[VS_I_EB_1_1].src_offset = sizeof(struct vertex2f) + sizeof(float) * 9;
861 vertex_elems[VS_I_EB_1_1].instance_divisor = 0;
862 vertex_elems[VS_I_EB_1_1].vertex_buffer_index = 1;
863 vertex_elems[VS_I_EB_1_1].src_format = PIPE_FORMAT_R32G32B32_FLOAT;
864
865 /* progressive=1.0f interlaced=0.0f */
866 vertex_elems[VS_I_INTERLACED].src_offset = sizeof(struct vertex2f) + sizeof(float) * 12;
867 vertex_elems[VS_I_INTERLACED].instance_divisor = 0;
868 vertex_elems[VS_I_INTERLACED].vertex_buffer_index = 1;
869 vertex_elems[VS_I_INTERLACED].src_format = PIPE_FORMAT_R32_FLOAT;
870
871 /* First ref surface top field texcoord element */
872 vertex_elems[VS_I_MV0].src_offset = 0;
873 vertex_elems[VS_I_MV0].instance_divisor = 0;
874 vertex_elems[VS_I_MV0].vertex_buffer_index = 2;
875 vertex_elems[VS_I_MV0].src_format = PIPE_FORMAT_R32G32_FLOAT;
876
877 /* First ref surface bottom field texcoord element */
878 vertex_elems[VS_I_MV1].src_offset = sizeof(struct vertex2f);
879 vertex_elems[VS_I_MV1].instance_divisor = 0;
880 vertex_elems[VS_I_MV1].vertex_buffer_index = 2;
881 vertex_elems[VS_I_MV1].src_format = PIPE_FORMAT_R32G32_FLOAT;
882
883 /* Second ref surface top field texcoord element */
884 vertex_elems[VS_I_MV2].src_offset = 0;
885 vertex_elems[VS_I_MV2].instance_divisor = 0;
886 vertex_elems[VS_I_MV2].vertex_buffer_index = 3;
887 vertex_elems[VS_I_MV2].src_format = PIPE_FORMAT_R32G32_FLOAT;
888
889 /* Second ref surface bottom field texcoord element */
890 vertex_elems[VS_I_MV3].src_offset = sizeof(struct vertex2f);
891 vertex_elems[VS_I_MV3].instance_divisor = 0;
892 vertex_elems[VS_I_MV3].vertex_buffer_index = 3;
893 vertex_elems[VS_I_MV3].src_format = PIPE_FORMAT_R32G32_FLOAT;
894
895 r->vertex_elems_state.individual.i = r->pipe->create_vertex_elements_state(r->pipe, 7, vertex_elems);
896 r->vertex_elems_state.individual.p = r->pipe->create_vertex_elements_state(r->pipe, 9, vertex_elems);
897 r->vertex_elems_state.individual.b = r->pipe->create_vertex_elements_state(r->pipe, 11, vertex_elems);
898
899 r->vs_const_buf = pipe_buffer_create
900 (
901 r->pipe->screen,
902 PIPE_BIND_CONSTANT_BUFFER,
903 sizeof(struct vertex_shader_consts)
904 );
905
906 return true;
907 }
908
909 static bool
910 init_const_buffers(struct vl_mpeg12_mc_renderer *r)
911 {
912 struct pipe_transfer *buf_transfer;
913 struct vertex2f *rect;
914 unsigned i;
915
916 rect = pipe_buffer_map
917 (
918 r->pipe,
919 r->vertex_bufs.individual.rect.buffer,
920 PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD,
921 &buf_transfer
922 );
923
924 for ( i = 0; i < r->macroblocks_per_batch; ++i)
925 memcpy(rect + i * 4, &const_quad, sizeof(const_quad));
926
927 pipe_buffer_unmap(r->pipe, r->vertex_bufs.individual.rect.buffer, buf_transfer);
928
929 return true;
930 }
931
932 static void
933 cleanup_buffers(struct vl_mpeg12_mc_renderer *r)
934 {
935 unsigned i;
936
937 assert(r);
938
939 pipe_resource_reference(&r->vs_const_buf, NULL);
940
941 for (i = 0; i < 3; ++i) {
942 pipe_sampler_view_reference(&r->sampler_views.all[i], NULL);
943 r->pipe->delete_vertex_elements_state(r->pipe, r->vertex_elems_state.all[i]);
944 pipe_resource_reference(&r->vertex_bufs.all[i].buffer, NULL);
945 pipe_resource_reference(&r->textures.all[i], NULL);
946 }
947
948 FREE(r->macroblock_buf);
949 }
950
951 static enum MACROBLOCK_TYPE
952 get_macroblock_type(struct pipe_mpeg12_macroblock *mb)
953 {
954 assert(mb);
955
956 switch (mb->mb_type) {
957 case PIPE_MPEG12_MACROBLOCK_TYPE_INTRA:
958 return MACROBLOCK_TYPE_INTRA;
959 case PIPE_MPEG12_MACROBLOCK_TYPE_FWD:
960 return mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FRAME ?
961 MACROBLOCK_TYPE_FWD_FRAME_PRED : MACROBLOCK_TYPE_FWD_FIELD_PRED;
962 case PIPE_MPEG12_MACROBLOCK_TYPE_BKWD:
963 return mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FRAME ?
964 MACROBLOCK_TYPE_BKWD_FRAME_PRED : MACROBLOCK_TYPE_BKWD_FIELD_PRED;
965 case PIPE_MPEG12_MACROBLOCK_TYPE_BI:
966 return mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FRAME ?
967 MACROBLOCK_TYPE_BI_FRAME_PRED : MACROBLOCK_TYPE_BI_FIELD_PRED;
968 default:
969 assert(0);
970 }
971
972 /* Unreachable */
973 return -1;
974 }
975
976 void
977 gen_macroblock_verts(struct vl_mpeg12_mc_renderer *r,
978 struct pipe_mpeg12_macroblock *mb, unsigned pos,
979 struct vert_stream_0 *ycbcr_vb, struct vertex2f **ref_vb)
980 {
981 struct vertex2f mo_vec[2];
982
983 unsigned i;
984
985 assert(r);
986 assert(mb);
987 assert(ycbcr_vb);
988 assert(pos < r->macroblocks_per_batch);
989
990 mo_vec[1].x = 0;
991 mo_vec[1].y = 0;
992
993 switch (mb->mb_type) {
994 case PIPE_MPEG12_MACROBLOCK_TYPE_BI:
995 {
996 struct vertex2f *vb;
997
998 assert(ref_vb && ref_vb[1]);
999
1000 vb = ref_vb[1] + pos * 2 * 4;
1001
1002 mo_vec[0].x = mb->pmv[0][1][0];
1003 mo_vec[0].y = mb->pmv[0][1][1];
1004
1005 if (mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FRAME) {
1006 for (i = 0; i < 4 * 2; i += 2) {
1007 vb[i].x = mo_vec[0].x;
1008 vb[i].y = mo_vec[0].y;
1009 }
1010 }
1011 else {
1012 mo_vec[0].y = mb->pmv[0][1][1] - (mb->pmv[0][1][1] % 4);
1013
1014 mo_vec[1].x = mb->pmv[1][1][0];
1015 mo_vec[1].y = mb->pmv[1][1][1] - (mb->pmv[1][1][1] % 4);
1016
1017 if(mb->mvfs[0][1]) mo_vec[0].y += 2;
1018 if(!mb->mvfs[1][1]) mo_vec[1].y -= 2;
1019
1020 for (i = 0; i < 4 * 2; i += 2) {
1021 vb[i].x = mo_vec[0].x;
1022 vb[i].y = mo_vec[0].y;
1023 vb[i + 1].x = mo_vec[1].x;
1024 vb[i + 1].y = mo_vec[1].y;
1025 }
1026 }
1027
1028 /* fall-through */
1029 }
1030 case PIPE_MPEG12_MACROBLOCK_TYPE_FWD:
1031 case PIPE_MPEG12_MACROBLOCK_TYPE_BKWD:
1032 {
1033 struct vertex2f *vb;
1034
1035 assert(ref_vb && ref_vb[0]);
1036
1037 vb = ref_vb[0] + pos * 2 * 4;
1038
1039 if (mb->mb_type == PIPE_MPEG12_MACROBLOCK_TYPE_BKWD) {
1040 mo_vec[0].x = mb->pmv[0][1][0];
1041 mo_vec[0].y = mb->pmv[0][1][1];
1042
1043 if (mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FIELD) {
1044 mo_vec[0].y = mb->pmv[0][1][1] - (mb->pmv[0][1][1] % 4);
1045
1046 mo_vec[1].x = mb->pmv[1][1][0];
1047 mo_vec[1].y = mb->pmv[1][1][1] - (mb->pmv[1][1][1] % 4);
1048
1049 if(mb->mvfs[0][1]) mo_vec[0].y += 2;
1050 if(!mb->mvfs[1][1]) mo_vec[1].y -= 2;
1051 }
1052 }
1053 else {
1054 mo_vec[0].x = mb->pmv[0][0][0];
1055 mo_vec[0].y = mb->pmv[0][0][1];
1056
1057 if (mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FIELD) {
1058 mo_vec[0].y = mb->pmv[0][0][1] - (mb->pmv[0][0][1] % 4);
1059
1060 mo_vec[1].x = mb->pmv[1][0][0];
1061 mo_vec[1].y = mb->pmv[1][0][1] - (mb->pmv[1][0][1] % 4);
1062
1063 if(mb->mvfs[0][0]) mo_vec[0].y += 2;
1064 if(!mb->mvfs[1][0]) mo_vec[1].y -= 2;
1065 }
1066 }
1067
1068 if (mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FRAME) {
1069 for (i = 0; i < 4 * 2; i += 2) {
1070 vb[i].x = mo_vec[0].x;
1071 vb[i].y = mo_vec[0].y;
1072 }
1073 }
1074 else {
1075 for (i = 0; i < 4 * 2; i += 2) {
1076 vb[i].x = mo_vec[0].x;
1077 vb[i].y = mo_vec[0].y;
1078 vb[i + 1].x = mo_vec[1].x;
1079 vb[i + 1].y = mo_vec[1].y;
1080 }
1081 }
1082
1083 /* fall-through */
1084 }
1085 case PIPE_MPEG12_MACROBLOCK_TYPE_INTRA:
1086 {
1087 struct vert_stream_0 *vb = ycbcr_vb + pos * 4;
1088 struct vert_stream_0 v;
1089
1090 v.pos.x = mb->mbx;
1091 v.pos.y = mb->mby;
1092
1093 v.field[0][0].luma_eb = mb->cbp & 32 ? 0.0f : -1.0f;
1094 v.field[0][1].luma_eb = mb->cbp & 16 ? 0.0f : -1.0f;
1095 v.field[1][0].luma_eb = mb->cbp & 8 ? 0.0f : -1.0f;
1096 v.field[1][1].luma_eb = mb->cbp & 4 ? 0.0f : -1.0f;
1097
1098 v.field[0][0].cb_eb = mb->cbp & 2 ? 0.0f : -1.0f;
1099 v.field[0][1].cb_eb = mb->cbp & 2 ? 0.0f : -1.0f;
1100 v.field[1][0].cb_eb = mb->cbp & 2 ? 0.0f : -1.0f;
1101 v.field[1][1].cb_eb = mb->cbp & 2 ? 0.0f : -1.0f;
1102
1103 v.field[0][0].cr_eb = mb->cbp & 1 ? 0.0f : -1.0f;
1104 v.field[0][1].cr_eb = mb->cbp & 1 ? 0.0f : -1.0f;
1105 v.field[1][0].cr_eb = mb->cbp & 1 ? 0.0f : -1.0f;
1106 v.field[1][1].cr_eb = mb->cbp & 1 ? 0.0f : -1.0f;
1107
1108 v.interlaced = mb->dct_type == PIPE_MPEG12_DCT_TYPE_FIELD ? 1.0f : 0.0f;
1109
1110 for ( i = 0; i < 4; ++i )
1111 memcpy(vb + i, &v, sizeof(v));
1112
1113 break;
1114 }
1115 default:
1116 assert(0);
1117 }
1118 }
1119
1120 static void
1121 gen_macroblock_stream(struct vl_mpeg12_mc_renderer *r,
1122 unsigned *num_macroblocks)
1123 {
1124 unsigned offset[NUM_MACROBLOCK_TYPES];
1125 struct vert_stream_0 *ycbcr_vb;
1126 struct vertex2f *ref_vb[2];
1127 struct pipe_transfer *buf_transfer[3];
1128 unsigned i;
1129
1130 assert(r);
1131 assert(num_macroblocks);
1132
1133 for (i = 0; i < r->num_macroblocks; ++i) {
1134 enum MACROBLOCK_TYPE mb_type = get_macroblock_type(&r->macroblock_buf[i]);
1135 ++num_macroblocks[mb_type];
1136 }
1137
1138 offset[0] = 0;
1139
1140 for (i = 1; i < NUM_MACROBLOCK_TYPES; ++i)
1141 offset[i] = offset[i - 1] + num_macroblocks[i - 1];
1142
1143 ycbcr_vb = (struct vert_stream_0 *)pipe_buffer_map
1144 (
1145 r->pipe,
1146 r->vertex_bufs.individual.ycbcr.buffer,
1147 PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD,
1148 &buf_transfer[0]
1149 );
1150
1151 for (i = 0; i < 2; ++i)
1152 ref_vb[i] = (struct vertex2f *)pipe_buffer_map
1153 (
1154 r->pipe,
1155 r->vertex_bufs.individual.ref[i].buffer,
1156 PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD,
1157 &buf_transfer[i + 1]
1158 );
1159
1160 for (i = 0; i < r->num_macroblocks; ++i) {
1161 enum MACROBLOCK_TYPE mb_type = get_macroblock_type(&r->macroblock_buf[i]);
1162
1163 gen_macroblock_verts(r, &r->macroblock_buf[i], offset[mb_type],
1164 ycbcr_vb, ref_vb);
1165
1166 ++offset[mb_type];
1167 }
1168
1169 pipe_buffer_unmap(r->pipe, r->vertex_bufs.individual.ycbcr.buffer, buf_transfer[0]);
1170 for (i = 0; i < 2; ++i)
1171 pipe_buffer_unmap(r->pipe, r->vertex_bufs.individual.ref[i].buffer, buf_transfer[i + 1]);
1172 }
1173
1174 static struct pipe_sampler_view
1175 *find_or_create_sampler_view(struct vl_mpeg12_mc_renderer *r, struct pipe_surface *surface)
1176 {
1177 struct pipe_sampler_view *sampler_view;
1178 assert(r);
1179 assert(surface);
1180
1181 sampler_view = (struct pipe_sampler_view*)util_keymap_lookup(r->texview_map, &surface);
1182 if (!sampler_view) {
1183 struct pipe_sampler_view templat;
1184 boolean added_to_map;
1185
1186 u_sampler_view_default_template(&templat, surface->texture,
1187 surface->texture->format);
1188 sampler_view = r->pipe->create_sampler_view(r->pipe, surface->texture,
1189 &templat);
1190 if (!sampler_view)
1191 return NULL;
1192
1193 added_to_map = util_keymap_insert(r->texview_map, &surface,
1194 sampler_view, r->pipe);
1195 assert(added_to_map);
1196 }
1197
1198 return sampler_view;
1199 }
1200
1201 static void
1202 flush(struct vl_mpeg12_mc_renderer *r)
1203 {
1204 unsigned num_macroblocks[NUM_MACROBLOCK_TYPES] = { 0 };
1205 unsigned vb_start = 0;
1206
1207 assert(r);
1208 assert(r->num_macroblocks == r->macroblocks_per_batch);
1209
1210 xfer_buffers_unmap(r);
1211 gen_macroblock_stream(r, num_macroblocks);
1212
1213 if (num_macroblocks[MACROBLOCK_TYPE_INTRA] > 0) {
1214 r->pipe->set_vertex_buffers(r->pipe, 2, r->vertex_bufs.all);
1215 r->pipe->bind_vertex_elements_state(r->pipe, r->vertex_elems_state.individual.i);
1216 r->pipe->set_fragment_sampler_views(r->pipe, 3, r->sampler_views.all);
1217 r->pipe->bind_fragment_sampler_states(r->pipe, 3, r->samplers.all);
1218 r->pipe->bind_vs_state(r->pipe, r->i_vs);
1219 r->pipe->bind_fs_state(r->pipe, r->i_fs);
1220
1221 util_draw_arrays(r->pipe, PIPE_PRIM_QUADS, vb_start,
1222 num_macroblocks[MACROBLOCK_TYPE_INTRA] * 4);
1223 vb_start += num_macroblocks[MACROBLOCK_TYPE_INTRA] * 4;
1224 }
1225
1226 if (num_macroblocks[MACROBLOCK_TYPE_FWD_FRAME_PRED] > 0) {
1227 r->pipe->set_vertex_buffers(r->pipe, 3, r->vertex_bufs.all);
1228 r->pipe->bind_vertex_elements_state(r->pipe, r->vertex_elems_state.individual.p);
1229 r->textures.individual.ref[0] = r->past->texture;
1230 r->sampler_views.individual.ref[0] = find_or_create_sampler_view(r, r->past);
1231 r->pipe->set_fragment_sampler_views(r->pipe, 4, r->sampler_views.all);
1232 r->pipe->bind_fragment_sampler_states(r->pipe, 4, r->samplers.all);
1233 r->pipe->bind_vs_state(r->pipe, r->p_vs[0]);
1234 r->pipe->bind_fs_state(r->pipe, r->p_fs[0]);
1235
1236 util_draw_arrays(r->pipe, PIPE_PRIM_QUADS, vb_start,
1237 num_macroblocks[MACROBLOCK_TYPE_FWD_FRAME_PRED] * 4);
1238 vb_start += num_macroblocks[MACROBLOCK_TYPE_FWD_FRAME_PRED] * 4;
1239 }
1240
1241 if (num_macroblocks[MACROBLOCK_TYPE_FWD_FIELD_PRED] > 0) {
1242 r->pipe->set_vertex_buffers(r->pipe, 3, r->vertex_bufs.all);
1243 r->pipe->bind_vertex_elements_state(r->pipe, r->vertex_elems_state.individual.p);
1244 r->textures.individual.ref[0] = r->past->texture;
1245 r->sampler_views.individual.ref[0] = find_or_create_sampler_view(r, r->past);
1246 r->pipe->set_fragment_sampler_views(r->pipe, 4, r->sampler_views.all);
1247 r->pipe->bind_fragment_sampler_states(r->pipe, 4, r->samplers.all);
1248 r->pipe->bind_vs_state(r->pipe, r->p_vs[1]);
1249 r->pipe->bind_fs_state(r->pipe, r->p_fs[1]);
1250
1251 util_draw_arrays(r->pipe, PIPE_PRIM_QUADS, vb_start,
1252 num_macroblocks[MACROBLOCK_TYPE_FWD_FIELD_PRED] * 4);
1253 vb_start += num_macroblocks[MACROBLOCK_TYPE_FWD_FIELD_PRED] * 4;
1254 }
1255
1256 if (num_macroblocks[MACROBLOCK_TYPE_BKWD_FRAME_PRED] > 0) {
1257 r->pipe->set_vertex_buffers(r->pipe, 3, r->vertex_bufs.all);
1258 r->pipe->bind_vertex_elements_state(r->pipe, r->vertex_elems_state.individual.p);
1259 r->textures.individual.ref[0] = r->future->texture;
1260 r->sampler_views.individual.ref[0] = find_or_create_sampler_view(r, r->future);
1261 r->pipe->set_fragment_sampler_views(r->pipe, 4, r->sampler_views.all);
1262 r->pipe->bind_fragment_sampler_states(r->pipe, 4, r->samplers.all);
1263 r->pipe->bind_vs_state(r->pipe, r->p_vs[0]);
1264 r->pipe->bind_fs_state(r->pipe, r->p_fs[0]);
1265
1266 util_draw_arrays(r->pipe, PIPE_PRIM_QUADS, vb_start,
1267 num_macroblocks[MACROBLOCK_TYPE_BKWD_FRAME_PRED] * 4);
1268 vb_start += num_macroblocks[MACROBLOCK_TYPE_BKWD_FRAME_PRED] * 4;
1269 }
1270
1271 if (num_macroblocks[MACROBLOCK_TYPE_BKWD_FIELD_PRED] > 0) {
1272 r->pipe->set_vertex_buffers(r->pipe, 3, r->vertex_bufs.all);
1273 r->pipe->bind_vertex_elements_state(r->pipe, r->vertex_elems_state.individual.p);
1274 r->textures.individual.ref[0] = r->future->texture;
1275 r->sampler_views.individual.ref[0] = find_or_create_sampler_view(r, r->future);
1276 r->pipe->set_fragment_sampler_views(r->pipe, 4, r->sampler_views.all);
1277 r->pipe->bind_fragment_sampler_states(r->pipe, 4, r->samplers.all);
1278 r->pipe->bind_vs_state(r->pipe, r->p_vs[1]);
1279 r->pipe->bind_fs_state(r->pipe, r->p_fs[1]);
1280
1281 util_draw_arrays(r->pipe, PIPE_PRIM_QUADS, vb_start,
1282 num_macroblocks[MACROBLOCK_TYPE_BKWD_FIELD_PRED] * 4);
1283 vb_start += num_macroblocks[MACROBLOCK_TYPE_BKWD_FIELD_PRED] * 4;
1284 }
1285
1286 if (num_macroblocks[MACROBLOCK_TYPE_BI_FRAME_PRED] > 0) {
1287 r->pipe->set_vertex_buffers(r->pipe, 4, r->vertex_bufs.all);
1288 r->pipe->bind_vertex_elements_state(r->pipe, r->vertex_elems_state.individual.b);
1289 r->textures.individual.ref[0] = r->past->texture;
1290 r->textures.individual.ref[1] = r->future->texture;
1291 r->sampler_views.individual.ref[0] = find_or_create_sampler_view(r, r->past);
1292 r->sampler_views.individual.ref[1] = find_or_create_sampler_view(r, r->future);
1293 r->pipe->set_fragment_sampler_views(r->pipe, 5, r->sampler_views.all);
1294 r->pipe->bind_fragment_sampler_states(r->pipe, 5, r->samplers.all);
1295 r->pipe->bind_vs_state(r->pipe, r->b_vs[0]);
1296 r->pipe->bind_fs_state(r->pipe, r->b_fs[0]);
1297
1298 util_draw_arrays(r->pipe, PIPE_PRIM_QUADS, vb_start,
1299 num_macroblocks[MACROBLOCK_TYPE_BI_FRAME_PRED] * 4);
1300 vb_start += num_macroblocks[MACROBLOCK_TYPE_BI_FRAME_PRED] * 4;
1301 }
1302
1303 if (num_macroblocks[MACROBLOCK_TYPE_BI_FIELD_PRED] > 0) {
1304 r->pipe->set_vertex_buffers(r->pipe, 4, r->vertex_bufs.all);
1305 r->pipe->bind_vertex_elements_state(r->pipe, r->vertex_elems_state.individual.b);
1306 r->textures.individual.ref[0] = r->past->texture;
1307 r->textures.individual.ref[1] = r->future->texture;
1308 r->sampler_views.individual.ref[0] = find_or_create_sampler_view(r, r->past);
1309 r->sampler_views.individual.ref[1] = find_or_create_sampler_view(r, r->future);
1310 r->pipe->set_fragment_sampler_views(r->pipe, 5, r->sampler_views.all);
1311 r->pipe->bind_fragment_sampler_states(r->pipe, 5, r->samplers.all);
1312 r->pipe->bind_vs_state(r->pipe, r->b_vs[1]);
1313 r->pipe->bind_fs_state(r->pipe, r->b_fs[1]);
1314
1315 util_draw_arrays(r->pipe, PIPE_PRIM_QUADS, vb_start,
1316 num_macroblocks[MACROBLOCK_TYPE_BI_FIELD_PRED] * 4);
1317 vb_start += num_macroblocks[MACROBLOCK_TYPE_BI_FIELD_PRED] * 4;
1318 }
1319
1320 r->pipe->flush(r->pipe, PIPE_FLUSH_RENDER_CACHE, r->fence);
1321
1322 r->num_macroblocks = 0;
1323 xfer_buffers_map(r);
1324 }
1325
1326 static void
1327 update_render_target(struct vl_mpeg12_mc_renderer *r)
1328 {
1329 struct pipe_transfer *buf_transfer;
1330 struct vertex_shader_consts *vs_consts;
1331
1332 vs_consts = pipe_buffer_map
1333 (
1334 r->pipe, r->vs_const_buf,
1335 PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD,
1336 &buf_transfer
1337 );
1338
1339 vs_consts->norm.x = 1.0f / r->surface->width;
1340 vs_consts->norm.y = 1.0f / r->surface->height;
1341
1342 pipe_buffer_unmap(r->pipe, r->vs_const_buf, buf_transfer);
1343
1344 r->pipe->set_constant_buffer(r->pipe, PIPE_SHADER_VERTEX, 0,
1345 r->vs_const_buf);
1346
1347 r->fb_state.cbufs[0] = r->surface;
1348
1349 r->pipe->set_framebuffer_state(r->pipe, &r->fb_state);
1350 r->pipe->set_viewport_state(r->pipe, &r->viewport);
1351 }
1352
1353 static void
1354 grab_coded_block(short *src, short *dst, unsigned dst_pitch)
1355 {
1356 unsigned y;
1357
1358 assert(src);
1359 assert(dst);
1360
1361 for (y = 0; y < BLOCK_HEIGHT; ++y)
1362 memcpy(dst + y * dst_pitch, src + y * BLOCK_WIDTH, BLOCK_WIDTH * 2);
1363 }
1364
1365 static void
1366 grab_blocks(struct vl_mpeg12_mc_renderer *r, unsigned mbx, unsigned mby,
1367 enum pipe_mpeg12_dct_type dct_type, unsigned cbp, short *blocks)
1368 {
1369 unsigned tex_pitch;
1370 short *texels;
1371 unsigned tb = 0, sb = 0;
1372 unsigned mbpx = mbx * MACROBLOCK_WIDTH, mbpy = mby * MACROBLOCK_HEIGHT;
1373 unsigned x, y;
1374
1375 assert(r);
1376 assert(blocks);
1377
1378 tex_pitch = r->tex_transfer[0]->stride / util_format_get_blocksize(r->tex_transfer[0]->resource->format);
1379 texels = r->texels[0] + mbpy * tex_pitch + mbpx;
1380
1381 for (y = 0; y < 2; ++y) {
1382 for (x = 0; x < 2; ++x, ++tb) {
1383 if ((cbp >> (5 - tb)) & 1) {
1384 grab_coded_block(blocks + sb * BLOCK_WIDTH * BLOCK_HEIGHT,
1385 texels + y * tex_pitch * BLOCK_HEIGHT +
1386 x * BLOCK_WIDTH, tex_pitch);
1387 ++sb;
1388 }
1389 }
1390 }
1391
1392 /* TODO: Implement 422, 444 */
1393 assert(r->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420);
1394
1395 mbpx /= 2;
1396 mbpy /= 2;
1397
1398 for (tb = 0; tb < 2; ++tb) {
1399 tex_pitch = r->tex_transfer[tb + 1]->stride / util_format_get_blocksize(r->tex_transfer[tb + 1]->resource->format);
1400 texels = r->texels[tb + 1] + mbpy * tex_pitch + mbpx;
1401
1402 if ((cbp >> (1 - tb)) & 1) {
1403 grab_coded_block(blocks + sb * BLOCK_WIDTH * BLOCK_HEIGHT, texels, tex_pitch);
1404 ++sb;
1405 }
1406 }
1407 }
1408
1409 static void
1410 grab_macroblock(struct vl_mpeg12_mc_renderer *r,
1411 struct pipe_mpeg12_macroblock *mb)
1412 {
1413 assert(r);
1414 assert(mb);
1415 assert(mb->blocks);
1416 assert(r->num_macroblocks < r->macroblocks_per_batch);
1417
1418 memcpy(&r->macroblock_buf[r->num_macroblocks], mb,
1419 sizeof(struct pipe_mpeg12_macroblock));
1420
1421 grab_blocks(r, mb->mbx, mb->mby, mb->dct_type, mb->cbp, mb->blocks);
1422
1423 ++r->num_macroblocks;
1424 }
1425
1426 static void
1427 texview_map_delete(const struct keymap *map,
1428 const void *key, void *data,
1429 void *user)
1430 {
1431 struct pipe_sampler_view *sv = (struct pipe_sampler_view*)data;
1432
1433 assert(map);
1434 assert(key);
1435 assert(data);
1436 assert(user);
1437
1438 pipe_sampler_view_reference(&sv, NULL);
1439 }
1440
1441 bool
1442 vl_mpeg12_mc_renderer_init(struct vl_mpeg12_mc_renderer *renderer,
1443 struct pipe_context *pipe,
1444 unsigned picture_width,
1445 unsigned picture_height,
1446 enum pipe_video_chroma_format chroma_format,
1447 enum VL_MPEG12_MC_RENDERER_BUFFER_MODE bufmode,
1448 bool pot_buffers)
1449 {
1450 assert(renderer);
1451 assert(pipe);
1452 /* TODO: Implement other policies */
1453 assert(bufmode == VL_MPEG12_MC_RENDERER_BUFFER_PICTURE);
1454 /* TODO: Non-pot buffers untested, probably doesn't work without changes to texcoord generation, vert shader, etc */
1455 assert(pot_buffers);
1456
1457 memset(renderer, 0, sizeof(struct vl_mpeg12_mc_renderer));
1458
1459 renderer->pipe = pipe;
1460 renderer->picture_width = picture_width;
1461 renderer->picture_height = picture_height;
1462 renderer->chroma_format = chroma_format;
1463 renderer->bufmode = bufmode;
1464 renderer->pot_buffers = pot_buffers;
1465
1466 renderer->texview_map = util_new_keymap(sizeof(struct pipe_surface*), -1,
1467 texview_map_delete);
1468 if (!renderer->texview_map)
1469 return false;
1470
1471 if (!init_pipe_state(renderer)) {
1472 util_delete_keymap(renderer->texview_map, renderer->pipe);
1473 return false;
1474 }
1475 if (!init_shaders(renderer)) {
1476 util_delete_keymap(renderer->texview_map, renderer->pipe);
1477 cleanup_pipe_state(renderer);
1478 return false;
1479 }
1480 if (!init_buffers(renderer)) {
1481 util_delete_keymap(renderer->texview_map, renderer->pipe);
1482 cleanup_shaders(renderer);
1483 cleanup_pipe_state(renderer);
1484 return false;
1485 }
1486
1487 if (!init_const_buffers(renderer)) {
1488 util_delete_keymap(renderer->texview_map, renderer->pipe);
1489 cleanup_pipe_state(renderer);
1490 cleanup_shaders(renderer);
1491 cleanup_buffers(renderer);
1492 return false;
1493 }
1494
1495 renderer->surface = NULL;
1496 renderer->past = NULL;
1497 renderer->future = NULL;
1498 renderer->num_macroblocks = 0;
1499
1500 xfer_buffers_map(renderer);
1501
1502 return true;
1503 }
1504
1505 void
1506 vl_mpeg12_mc_renderer_cleanup(struct vl_mpeg12_mc_renderer *renderer)
1507 {
1508 assert(renderer);
1509
1510 xfer_buffers_unmap(renderer);
1511
1512 util_delete_keymap(renderer->texview_map, renderer->pipe);
1513 cleanup_pipe_state(renderer);
1514 cleanup_shaders(renderer);
1515 cleanup_buffers(renderer);
1516
1517 pipe_surface_reference(&renderer->surface, NULL);
1518 pipe_surface_reference(&renderer->past, NULL);
1519 pipe_surface_reference(&renderer->future, NULL);
1520 }
1521
1522 void
1523 vl_mpeg12_mc_renderer_render_macroblocks(struct vl_mpeg12_mc_renderer
1524 *renderer,
1525 struct pipe_surface *surface,
1526 struct pipe_surface *past,
1527 struct pipe_surface *future,
1528 unsigned num_macroblocks,
1529 struct pipe_mpeg12_macroblock
1530 *mpeg12_macroblocks,
1531 struct pipe_fence_handle **fence)
1532 {
1533 bool new_surface = false;
1534
1535 assert(renderer);
1536 assert(surface);
1537 assert(num_macroblocks);
1538 assert(mpeg12_macroblocks);
1539
1540 if (renderer->surface) {
1541 if (surface != renderer->surface) {
1542 if (renderer->num_macroblocks > 0) {
1543 flush(renderer);
1544 }
1545
1546 new_surface = true;
1547 }
1548
1549 /* If the surface we're rendering hasn't changed the ref frames shouldn't change. */
1550 assert(surface != renderer->surface || renderer->past == past);
1551 assert(surface != renderer->surface || renderer->future == future);
1552 }
1553 else
1554 new_surface = true;
1555
1556 if (new_surface) {
1557 pipe_surface_reference(&renderer->surface, surface);
1558 pipe_surface_reference(&renderer->past, past);
1559 pipe_surface_reference(&renderer->future, future);
1560 renderer->fence = fence;
1561 update_render_target(renderer);
1562 }
1563
1564 while (num_macroblocks) {
1565 unsigned left_in_batch = renderer->macroblocks_per_batch - renderer->num_macroblocks;
1566 unsigned num_to_submit = MIN2(num_macroblocks, left_in_batch);
1567 unsigned i;
1568
1569 for (i = 0; i < num_to_submit; ++i) {
1570 assert(mpeg12_macroblocks[i].base.codec == PIPE_VIDEO_CODEC_MPEG12);
1571 grab_macroblock(renderer, &mpeg12_macroblocks[i]);
1572 }
1573
1574 num_macroblocks -= num_to_submit;
1575
1576 if (renderer->num_macroblocks == renderer->macroblocks_per_batch) {
1577 flush(renderer);
1578 /* Next time we get this surface it may have new ref frames */
1579 pipe_surface_reference(&renderer->surface, NULL);
1580 pipe_surface_reference(&renderer->past, NULL);
1581 pipe_surface_reference(&renderer->future, NULL);
1582 }
1583 }
1584 }