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