[g3dvl] give each mv an individual weight
[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 "vl_vertex_buffers.h"
30 #include "vl_defines.h"
31 #include "util/u_draw.h"
32 #include <assert.h>
33 #include <pipe/p_context.h>
34 #include <util/u_inlines.h>
35 #include <util/u_format.h>
36 #include <util/u_math.h>
37 #include <util/u_memory.h>
38 #include <util/u_keymap.h>
39 #include <util/u_sampler.h>
40 #include <util/u_draw.h>
41 #include <tgsi/tgsi_ureg.h>
42
43 enum VS_OUTPUT
44 {
45 VS_O_VPOS,
46 VS_O_LINE,
47 VS_O_TEX_TOP,
48 VS_O_TEX_BOTTOM,
49 VS_O_MV0_TOP,
50 VS_O_MV0_BOTTOM,
51 VS_O_MV1_TOP,
52 VS_O_MV1_BOTTOM
53 };
54
55 static void *
56 create_vert_shader(struct vl_mpeg12_mc_renderer *r)
57 {
58 struct ureg_program *shader;
59 struct ureg_src block_scale, mv_scale;
60 struct ureg_src vrect, vpos, eb, flags, vmv[2][2];
61 struct ureg_dst t_vpos, t_vtex, t_vmv;
62 struct ureg_dst o_vpos, o_line, o_vtex[2], o_vmv[2][2];
63 unsigned i, j, label;
64
65 shader = ureg_create(TGSI_PROCESSOR_VERTEX);
66 if (!shader)
67 return NULL;
68
69 t_vpos = ureg_DECL_temporary(shader);
70 t_vtex = ureg_DECL_temporary(shader);
71 t_vmv = ureg_DECL_temporary(shader);
72
73 vrect = ureg_DECL_vs_input(shader, VS_I_RECT);
74 vpos = ureg_DECL_vs_input(shader, VS_I_VPOS);
75 eb = ureg_DECL_vs_input(shader, VS_I_EB);
76 flags = ureg_DECL_vs_input(shader, VS_I_FLAGS);
77 vmv[0][0] = ureg_DECL_vs_input(shader, VS_I_MV0_TOP);
78 vmv[0][1] = ureg_DECL_vs_input(shader, VS_I_MV0_BOTTOM);
79 vmv[1][0] = ureg_DECL_vs_input(shader, VS_I_MV1_TOP);
80 vmv[1][1] = ureg_DECL_vs_input(shader, VS_I_MV1_BOTTOM);
81
82 o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, VS_O_VPOS);
83 o_line = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_LINE);
84 o_vtex[0] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_TEX_TOP);
85 o_vtex[1] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_TEX_BOTTOM);
86 o_vmv[0][0] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_MV0_TOP);
87 o_vmv[0][1] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_MV0_BOTTOM);
88 o_vmv[1][0] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_MV1_TOP);
89 o_vmv[1][1] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_MV1_BOTTOM);
90
91 /*
92 * block_scale = (MACROBLOCK_WIDTH, MACROBLOCK_HEIGHT) / (dst.width, dst.height)
93 * mv_scale = 0.5 / (dst.width, dst.height);
94 *
95 * t_vpos = (vpos + vrect) * block_scale
96 * o_vpos.xy = t_vpos
97 * o_vpos.zw = vpos
98 *
99 * o_eb[0..1] = vrect.x ? eb[0..1][1] : eb[0..1][0]
100 *
101 * o_frame_pred = frame_pred
102 * o_info.x = not_intra
103 * o_info.y = ref_weight / 2
104 *
105 * // Apply motion vectors
106 * o_vmv[0..3] = t_vpos + vmv[0..3] * mv_scale
107 *
108 * o_line.xy = vrect * 8
109 * o_line.z = interlaced
110 *
111 * if(eb[0][0].w) { //interlaced
112 * t_vtex.x = vrect.x
113 * t_vtex.y = vrect.y * 0.5
114 * t_vtex += vpos
115 *
116 * o_vtex[0].xy = t_vtex * block_scale
117 *
118 * t_vtex.y += 0.5
119 * o_vtex[1].xy = t_vtex * block_scale
120 * } else {
121 * o_vtex[0..1].xy = t_vpos
122 * }
123 * o_vtex[2].xy = t_vpos
124 *
125 */
126 block_scale = ureg_imm2f(shader,
127 (float)MACROBLOCK_WIDTH / r->buffer_width,
128 (float)MACROBLOCK_HEIGHT / r->buffer_height);
129
130 mv_scale = ureg_imm2f(shader,
131 0.5f / r->buffer_width,
132 0.5f / r->buffer_height);
133
134 ureg_ADD(shader, ureg_writemask(t_vpos, TGSI_WRITEMASK_XY), vpos, vrect);
135 ureg_MUL(shader, ureg_writemask(t_vpos, TGSI_WRITEMASK_XY), ureg_src(t_vpos), block_scale);
136 ureg_MOV(shader, ureg_writemask(o_vpos, TGSI_WRITEMASK_XY), ureg_src(t_vpos));
137 ureg_MOV(shader, ureg_writemask(o_vpos, TGSI_WRITEMASK_ZW), vpos);
138
139 for (i = 0; i < 2; ++i)
140 for (j = 0; j < 2; ++j) {
141 ureg_MAD(shader, ureg_writemask(o_vmv[i][j], TGSI_WRITEMASK_XY), mv_scale, vmv[i][j], ureg_src(t_vpos));
142 ureg_MOV(shader, ureg_writemask(o_vmv[i][j], TGSI_WRITEMASK_Z), ureg_scalar(flags, TGSI_SWIZZLE_Z + i));
143 }
144
145 ureg_MOV(shader, ureg_writemask(o_vtex[0], TGSI_WRITEMASK_XY), ureg_src(t_vpos));
146 ureg_CMP(shader, ureg_writemask(o_vtex[0], TGSI_WRITEMASK_Z),
147 ureg_negate(ureg_scalar(vrect, TGSI_SWIZZLE_X)),
148 ureg_scalar(eb, TGSI_SWIZZLE_Y),
149 ureg_scalar(eb, TGSI_SWIZZLE_X));
150
151 ureg_MOV(shader, ureg_writemask(o_vtex[1], TGSI_WRITEMASK_XY), ureg_src(t_vpos));
152 ureg_CMP(shader, ureg_writemask(o_vtex[1], TGSI_WRITEMASK_Z),
153 ureg_negate(ureg_scalar(vrect, TGSI_SWIZZLE_X)),
154 ureg_scalar(eb, TGSI_SWIZZLE_W),
155 ureg_scalar(eb, TGSI_SWIZZLE_Z));
156
157 ureg_MOV(shader, ureg_writemask(o_line, TGSI_WRITEMASK_X), ureg_scalar(vrect, TGSI_SWIZZLE_Y));
158 ureg_MUL(shader, ureg_writemask(o_line, TGSI_WRITEMASK_Y),
159 vrect, ureg_imm1f(shader, MACROBLOCK_HEIGHT / 2));
160 ureg_MOV(shader, ureg_writemask(o_line, TGSI_WRITEMASK_Z),
161 ureg_scalar(flags, TGSI_SWIZZLE_Y));
162
163 ureg_IF(shader, ureg_scalar(flags, TGSI_SWIZZLE_X), &label);
164
165 ureg_MOV(shader, ureg_writemask(t_vtex, TGSI_WRITEMASK_X), vrect);
166 ureg_MUL(shader, ureg_writemask(t_vtex, TGSI_WRITEMASK_Y), vrect, ureg_imm1f(shader, 0.5f));
167 ureg_ADD(shader, ureg_writemask(t_vtex, TGSI_WRITEMASK_XY), vpos, ureg_src(t_vtex));
168 ureg_MUL(shader, ureg_writemask(o_vtex[0], TGSI_WRITEMASK_XY), ureg_src(t_vtex), block_scale);
169 ureg_ADD(shader, ureg_writemask(t_vtex, TGSI_WRITEMASK_Y), ureg_src(t_vtex), ureg_imm1f(shader, 0.5f));
170 ureg_MUL(shader, ureg_writemask(o_vtex[1], TGSI_WRITEMASK_XY), ureg_src(t_vtex), block_scale);
171
172 ureg_MUL(shader, ureg_writemask(o_line, TGSI_WRITEMASK_X),
173 ureg_scalar(vrect, TGSI_SWIZZLE_Y),
174 ureg_imm1f(shader, MACROBLOCK_HEIGHT / 2));
175
176 ureg_fixup_label(shader, label, ureg_get_instruction_number(shader));
177 ureg_ENDIF(shader);
178
179 ureg_release_temporary(shader, t_vtex);
180 ureg_release_temporary(shader, t_vpos);
181 ureg_release_temporary(shader, t_vmv);
182
183 ureg_END(shader);
184
185 return ureg_create_shader_and_destroy(shader, r->pipe);
186 }
187
188 static struct ureg_dst
189 calc_field(struct ureg_program *shader)
190 {
191 struct ureg_dst tmp;
192 struct ureg_src line;
193
194 tmp = ureg_DECL_temporary(shader);
195
196 line = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_LINE, TGSI_INTERPOLATE_LINEAR);
197
198 /*
199 * line.x going from 0 to 1 if not interlaced
200 * line.x going from 0 to 8 in steps of 0.5 if interlaced
201 * line.y going from 0 to 8 in steps of 0.5
202 * line.z is flag for intra frames
203 *
204 * tmp.xy = fraction(line)
205 * tmp.xy = tmp.xy >= 0.5 ? 1 : 0
206 */
207 ureg_FRC(shader, ureg_writemask(tmp, TGSI_WRITEMASK_XY), line);
208 ureg_SGE(shader, ureg_writemask(tmp, TGSI_WRITEMASK_XY), ureg_src(tmp), ureg_imm1f(shader, 0.5f));
209 ureg_MOV(shader, ureg_writemask(tmp, TGSI_WRITEMASK_Z), line);
210
211 return tmp;
212 }
213
214 static struct ureg_dst
215 fetch_ycbcr(struct vl_mpeg12_mc_renderer *r, struct ureg_program *shader, struct ureg_dst field, float scale)
216 {
217 struct ureg_src tc[2], sampler;
218 struct ureg_dst texel, t_tc;
219 unsigned label;
220
221 texel = ureg_DECL_temporary(shader);
222 t_tc = ureg_DECL_temporary(shader);
223
224 tc[0] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_TEX_TOP, TGSI_INTERPOLATE_LINEAR);
225 tc[1] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_TEX_BOTTOM, TGSI_INTERPOLATE_LINEAR);
226
227 sampler = ureg_DECL_sampler(shader, 0);
228
229 /*
230 * texel.y = tex(field.y ? tc[1] : tc[0], sampler[0])
231 * texel.cb = tex(tc[2], sampler[1])
232 * texel.cr = tex(tc[2], sampler[2])
233 */
234
235 ureg_CMP(shader, ureg_writemask(t_tc, TGSI_WRITEMASK_XYZ),
236 ureg_negate(ureg_scalar(ureg_src(field), TGSI_SWIZZLE_X)),
237 tc[1], tc[0]);
238
239 ureg_SLT(shader, ureg_writemask(t_tc, TGSI_WRITEMASK_Z), ureg_src(t_tc), ureg_imm1f(shader, 0.5f));
240
241 ureg_MOV(shader, ureg_writemask(texel, TGSI_WRITEMASK_XYZ), ureg_imm1f(shader, 0.0f));
242 ureg_IF(shader, ureg_scalar(ureg_src(t_tc), TGSI_SWIZZLE_Z), &label);
243
244 ureg_TEX(shader, texel, TGSI_TEXTURE_3D, ureg_src(t_tc), sampler);
245
246 ureg_fixup_label(shader, label, ureg_get_instruction_number(shader));
247 ureg_ENDIF(shader);
248
249 if (scale != 1.0f)
250 ureg_MUL(shader, texel, ureg_src(texel), ureg_imm1f(shader, scale));
251
252 ureg_release_temporary(shader, t_tc);
253
254 return texel;
255 }
256
257 static struct ureg_dst
258 fetch_ref(struct ureg_program *shader, struct ureg_dst field)
259 {
260 struct ureg_src tc[2][2], sampler[2];
261 struct ureg_dst ref[2], result;
262 unsigned i, intra_label;
263
264 tc[0][0] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_MV0_TOP, TGSI_INTERPOLATE_LINEAR);
265 tc[0][1] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_MV0_BOTTOM, TGSI_INTERPOLATE_LINEAR);
266 tc[1][0] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_MV1_TOP, TGSI_INTERPOLATE_LINEAR);
267 tc[1][1] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_MV1_BOTTOM, TGSI_INTERPOLATE_LINEAR);
268
269 for (i = 0; i < 2; ++i) {
270 sampler[i] = ureg_DECL_sampler(shader, i + 1);
271 ref[i] = ureg_DECL_temporary(shader);
272 }
273
274 result = ureg_DECL_temporary(shader);
275
276 ureg_MOV(shader, result, ureg_imm1f(shader, 0.5f));
277
278 ureg_IF(shader, ureg_scalar(ureg_src(field), TGSI_SWIZZLE_Z), &intra_label);
279 /*
280 * if (field.z)
281 * ref[0..1] = tex(tc[0..1], sampler[0..1])
282 * else
283 * ref[0..1] = tex(tc[2..3], sampler[0..1])
284 * result = LRP(info.y, ref[0..1])
285 */
286 ureg_CMP(shader, ureg_writemask(ref[0], TGSI_WRITEMASK_XY),
287 ureg_negate(ureg_scalar(ureg_src(field), TGSI_SWIZZLE_Y)),
288 tc[0][1], tc[0][0]);
289 ureg_CMP(shader, ureg_writemask(ref[1], TGSI_WRITEMASK_XY),
290 ureg_negate(ureg_scalar(ureg_src(field), TGSI_SWIZZLE_Y)),
291 tc[1][1], tc[1][0]);
292
293 ureg_TEX(shader, ref[0], TGSI_TEXTURE_2D, ureg_src(ref[0]), sampler[0]);
294 ureg_TEX(shader, ref[1], TGSI_TEXTURE_2D, ureg_src(ref[1]), sampler[1]);
295
296 ureg_LRP(shader, ref[0],
297 ureg_scalar(tc[0][0], TGSI_SWIZZLE_Z),
298 ureg_src(ref[0]), ureg_imm1f(shader, 0.0f));
299
300 ureg_LRP(shader, ref[1],
301 ureg_scalar(tc[1][0], TGSI_SWIZZLE_Z),
302 ureg_src(ref[1]), ureg_imm1f(shader, 0.0f));
303
304 ureg_ADD(shader, result, ureg_src(ref[0]), ureg_src(ref[1]));
305
306 ureg_fixup_label(shader, intra_label, ureg_get_instruction_number(shader));
307 ureg_ENDIF(shader);
308
309 for (i = 0; i < 2; ++i)
310 ureg_release_temporary(shader, ref[i]);
311
312 return result;
313 }
314
315 static void *
316 create_frag_shader(struct vl_mpeg12_mc_renderer *r, float scale)
317 {
318 struct ureg_program *shader;
319 struct ureg_dst result;
320 struct ureg_dst field, texel;
321 struct ureg_dst fragment;
322
323 shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
324 if (!shader)
325 return NULL;
326
327 fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
328
329 field = calc_field(shader);
330 texel = fetch_ycbcr(r, shader, field, scale);
331
332 result = fetch_ref(shader, field);
333
334 ureg_ADD(shader, fragment, ureg_src(texel), ureg_src(result));
335
336 ureg_release_temporary(shader, field);
337 ureg_release_temporary(shader, texel);
338 ureg_release_temporary(shader, result);
339 ureg_END(shader);
340
341 return ureg_create_shader_and_destroy(shader, r->pipe);
342 }
343
344 static bool
345 init_pipe_state(struct vl_mpeg12_mc_renderer *r)
346 {
347 struct pipe_sampler_state sampler;
348 struct pipe_rasterizer_state rs_state;
349 unsigned filters[3];
350 unsigned i;
351
352 assert(r);
353
354 r->viewport.scale[2] = 1;
355 r->viewport.scale[3] = 1;
356 r->viewport.translate[0] = 0;
357 r->viewport.translate[1] = 0;
358 r->viewport.translate[2] = 0;
359 r->viewport.translate[3] = 0;
360
361 r->fb_state.nr_cbufs = 1;
362 r->fb_state.zsbuf = NULL;
363
364 /* source filter */
365 filters[0] = PIPE_TEX_FILTER_NEAREST;
366
367 /* Fwd, bkwd ref filters */
368 filters[1] = PIPE_TEX_FILTER_LINEAR;
369 filters[2] = PIPE_TEX_FILTER_LINEAR;
370
371 for (i = 0; i < 3; ++i) {
372 memset(&sampler, 0, sizeof(sampler));
373 sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
374 sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
375 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_BORDER;
376 sampler.min_img_filter = filters[i];
377 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
378 sampler.mag_img_filter = filters[i];
379 sampler.compare_mode = PIPE_TEX_COMPARE_NONE;
380 sampler.compare_func = PIPE_FUNC_ALWAYS;
381 sampler.normalized_coords = 1;
382 /*sampler.shadow_ambient = ; */
383 /*sampler.lod_bias = ; */
384 sampler.min_lod = 0;
385 /*sampler.max_lod = ; */
386 sampler.border_color[0] = 0.0f;
387 sampler.border_color[1] = 0.0f;
388 sampler.border_color[2] = 0.0f;
389 sampler.border_color[3] = 0.0f;
390 /*sampler.max_anisotropy = ; */
391 r->samplers.all[i] = r->pipe->create_sampler_state(r->pipe, &sampler);
392 if (!r->samplers.all[i])
393 goto error_samplers;
394 }
395
396 memset(&rs_state, 0, sizeof(rs_state));
397 /*rs_state.sprite_coord_enable */
398 rs_state.sprite_coord_mode = PIPE_SPRITE_COORD_UPPER_LEFT;
399 rs_state.point_quad_rasterization = true;
400 rs_state.point_size = BLOCK_WIDTH;
401 rs_state.gl_rasterization_rules = true;
402 r->rs_state = r->pipe->create_rasterizer_state(r->pipe, &rs_state);
403 if (!r->rs_state)
404 goto error_samplers;
405
406 return true;
407
408 error_samplers:
409 for (i = 0; i < 5; ++i)
410 r->pipe->delete_sampler_state(r->pipe, r->samplers.all[i]);
411
412 return false;
413 }
414
415 static void
416 cleanup_pipe_state(struct vl_mpeg12_mc_renderer *r)
417 {
418 unsigned i;
419
420 assert(r);
421
422 for (i = 0; i < 3; ++i)
423 r->pipe->delete_sampler_state(r->pipe, r->samplers.all[i]);
424
425 r->pipe->delete_rasterizer_state(r->pipe, r->rs_state);
426 }
427
428 bool
429 vl_mpeg12_mc_renderer_init(struct vl_mpeg12_mc_renderer *renderer,
430 struct pipe_context *pipe,
431 unsigned buffer_width,
432 unsigned buffer_height,
433 float scale)
434 {
435 struct pipe_resource tex_templ, *tex_dummy;
436 struct pipe_sampler_view sampler_view;
437
438 assert(renderer);
439 assert(pipe);
440
441 memset(renderer, 0, sizeof(struct vl_mpeg12_mc_renderer));
442
443 renderer->pipe = pipe;
444 renderer->buffer_width = buffer_width;
445 renderer->buffer_height = buffer_height;
446
447 if (!init_pipe_state(renderer))
448 goto error_pipe_state;
449
450 renderer->vs = create_vert_shader(renderer);
451 if (!renderer->vs)
452 goto error_vs_shaders;
453
454 renderer->fs = create_frag_shader(renderer, scale);
455 if (!renderer->fs)
456 goto error_fs_shaders;
457
458 /* create a dummy sampler */
459 memset(&tex_templ, 0, sizeof(tex_templ));
460 tex_templ.bind = PIPE_BIND_SAMPLER_VIEW;
461 tex_templ.flags = 0;
462
463 tex_templ.target = PIPE_TEXTURE_2D;
464 tex_templ.format = PIPE_FORMAT_R8_SNORM;
465 tex_templ.width0 = 1;
466 tex_templ.height0 = 1;
467 tex_templ.depth0 = 1;
468 tex_templ.array_size = 1;
469 tex_templ.last_level = 0;
470 tex_templ.usage = PIPE_USAGE_STATIC;
471 tex_dummy = pipe->screen->resource_create(pipe->screen, &tex_templ);
472 if (!tex_dummy)
473 goto error_dummy;
474
475 memset(&sampler_view, 0, sizeof(sampler_view));
476 u_sampler_view_default_template(&sampler_view, tex_dummy, tex_dummy->format);
477 renderer->dummy = pipe->create_sampler_view(pipe, tex_dummy, &sampler_view);
478 pipe_resource_reference(&tex_dummy, NULL);
479 if (!renderer->dummy)
480 goto error_dummy;
481
482 return true;
483
484 error_dummy:
485 renderer->pipe->delete_fs_state(renderer->pipe, renderer->fs);
486
487 error_fs_shaders:
488 renderer->pipe->delete_vs_state(renderer->pipe, renderer->vs);
489
490 error_vs_shaders:
491 cleanup_pipe_state(renderer);
492
493 error_pipe_state:
494 return false;
495 }
496
497 void
498 vl_mpeg12_mc_renderer_cleanup(struct vl_mpeg12_mc_renderer *renderer)
499 {
500 assert(renderer);
501
502 pipe_sampler_view_reference(&renderer->dummy, NULL);
503
504 cleanup_pipe_state(renderer);
505
506 renderer->pipe->delete_vs_state(renderer->pipe, renderer->vs);
507 renderer->pipe->delete_fs_state(renderer->pipe, renderer->fs);
508 }
509
510 bool
511 vl_mpeg12_mc_init_buffer(struct vl_mpeg12_mc_renderer *renderer, struct vl_mpeg12_mc_buffer *buffer,
512 struct pipe_sampler_view *source)
513 {
514 assert(renderer && buffer);
515 assert(source);
516
517 pipe_sampler_view_reference(&buffer->sampler_views.individual.source, source);
518
519 return true;
520 }
521
522 void
523 vl_mpeg12_mc_cleanup_buffer(struct vl_mpeg12_mc_buffer *buffer)
524 {
525 unsigned i;
526
527 assert(buffer);
528
529 for (i = 0; i < 3; ++i)
530 pipe_sampler_view_reference(&buffer->sampler_views.all[i], NULL);
531 }
532
533 void
534 vl_mpeg12_mc_renderer_flush(struct vl_mpeg12_mc_renderer *renderer, struct vl_mpeg12_mc_buffer *buffer,
535 struct pipe_surface *surface, struct pipe_sampler_view *ref[2],
536 unsigned not_empty_start_instance, unsigned not_empty_num_instances,
537 unsigned empty_start_instance, unsigned empty_num_instances,
538 struct pipe_fence_handle **fence)
539 {
540 assert(renderer && buffer);
541 assert(surface && ref);
542
543 if (not_empty_num_instances == 0 && empty_num_instances == 0)
544 return;
545
546 renderer->viewport.scale[0] = surface->width;
547 renderer->viewport.scale[1] = surface->height;
548
549 renderer->fb_state.width = surface->width;
550 renderer->fb_state.height = surface->height;
551 renderer->fb_state.cbufs[0] = surface;
552
553
554 renderer->pipe->bind_rasterizer_state(renderer->pipe, renderer->rs_state);
555 renderer->pipe->set_framebuffer_state(renderer->pipe, &renderer->fb_state);
556 renderer->pipe->set_viewport_state(renderer->pipe, &renderer->viewport);
557
558 /* if no reference frame provided use a dummy sampler instead */
559 pipe_sampler_view_reference(&buffer->sampler_views.individual.ref[0],
560 ref[0] ? ref[0] : renderer->dummy);
561 pipe_sampler_view_reference(&buffer->sampler_views.individual.ref[1],
562 ref[1] ? ref[1] : renderer->dummy);
563
564 renderer->pipe->set_fragment_sampler_views(renderer->pipe, 3, buffer->sampler_views.all);
565 renderer->pipe->bind_fragment_sampler_states(renderer->pipe, 3, renderer->samplers.all);
566
567 renderer->pipe->bind_vs_state(renderer->pipe, renderer->vs);
568 renderer->pipe->bind_fs_state(renderer->pipe, renderer->fs);
569
570 if (not_empty_num_instances > 0)
571 util_draw_arrays_instanced(renderer->pipe, PIPE_PRIM_QUADS, 0, 4,
572 not_empty_start_instance, not_empty_num_instances);
573
574 if (empty_num_instances > 0)
575 util_draw_arrays_instanced(renderer->pipe, PIPE_PRIM_QUADS, 0, 4,
576 empty_start_instance, empty_num_instances);
577
578 renderer->pipe->flush(renderer->pipe, fence);
579 }