145ea32892ad17d8ec0680ea6d62ef748b08352d
[mesa.git] / src / gallium / state_trackers / g3dvl / vl_surface.c
1 #include "vl_surface.h"
2 #include <assert.h>
3 #include <stdlib.h>
4 #include <pipe/p_context.h>
5 #include <pipe/p_state.h>
6 #include <pipe/p_format.h>
7 #include <pipe/p_inlines.h>
8 #include "vl_context.h"
9 #include "vl_defs.h"
10 #include "vl_util.h"
11
12 static int vlTransformBlock(short *src, short *dst, short bias)
13 {
14 static const float basis[8][8] =
15 {
16 {0.3536, 0.4904, 0.4619, 0.4157, 0.3536, 0.2778, 0.1913, 0.0975},
17 {0.3536, 0.4157, 0.1913, -0.0975, -0.3536, -0.4904, -0.4619, -0.2778},
18 {0.3536, 0.2778, -0.1913, -0.4904, -0.3536, 0.0975, 0.4619, 0.4157},
19 {0.3536, 0.0975, -0.4619, -0.2778, 0.3536, 0.4157, -0.1913, -0.4904},
20 {0.3536, -0.0975, -0.4619, 0.2778, 0.3536, -0.4157, -0.1913, 0.4904},
21 {0.3536, -0.2778, -0.1913, 0.4904, -0.3536, -0.0975, 0.4619, -0.4157},
22 {0.3536, -0.4157, 0.1913, 0.0975, -0.3536, 0.4904, -0.4619, 0.2778},
23 {0.3536, -0.4904, 0.4619, -0.4157, 0.3536, -0.2778, 0.1913, -0.0975}
24 };
25
26 unsigned int x, y;
27 short tmp[64];
28
29 for (y = 0; y < VL_BLOCK_HEIGHT; ++y)
30 for (x = 0; x < VL_BLOCK_WIDTH; ++x)
31 tmp[y * VL_BLOCK_WIDTH + x] = (short)
32 (
33 src[y * VL_BLOCK_WIDTH + 0] * basis[x][0] +
34 src[y * VL_BLOCK_WIDTH + 1] * basis[x][1] +
35 src[y * VL_BLOCK_WIDTH + 2] * basis[x][2] +
36 src[y * VL_BLOCK_WIDTH + 3] * basis[x][3] +
37 src[y * VL_BLOCK_WIDTH + 4] * basis[x][4] +
38 src[y * VL_BLOCK_WIDTH + 5] * basis[x][5] +
39 src[y * VL_BLOCK_WIDTH + 6] * basis[x][6] +
40 src[y * VL_BLOCK_WIDTH + 7] * basis[x][7]
41 );
42
43 for (x = 0; x < VL_BLOCK_WIDTH; ++x)
44 for (y = 0; y < VL_BLOCK_HEIGHT; ++y)
45 {
46 dst[y * VL_BLOCK_WIDTH + x] = bias + (short)
47 (
48 tmp[0 * VL_BLOCK_WIDTH + x] * basis[y][0] +
49 tmp[1 * VL_BLOCK_WIDTH + x] * basis[y][1] +
50 tmp[2 * VL_BLOCK_WIDTH + x] * basis[y][2] +
51 tmp[3 * VL_BLOCK_WIDTH + x] * basis[y][3] +
52 tmp[4 * VL_BLOCK_WIDTH + x] * basis[y][4] +
53 tmp[5 * VL_BLOCK_WIDTH + x] * basis[y][5] +
54 tmp[6 * VL_BLOCK_WIDTH + x] * basis[y][6] +
55 tmp[7 * VL_BLOCK_WIDTH + x] * basis[y][7]
56 );
57 if (dst[y * VL_BLOCK_WIDTH + x] > 255)
58 dst[y * VL_BLOCK_WIDTH + x] = 255;
59 else if (bias > 0 && dst[y * VL_BLOCK_WIDTH + x] < 0)
60 dst[y * VL_BLOCK_WIDTH + x] = 0;
61 }
62 return 0;
63 }
64
65 static int vlGrabFrameCodedFullBlock(short *src, short *dst, unsigned int dst_pitch)
66 {
67 unsigned int y;
68
69 for (y = 0; y < VL_BLOCK_HEIGHT; ++y)
70 memcpy
71 (
72 dst + y * dst_pitch,
73 src + y * VL_BLOCK_WIDTH,
74 VL_BLOCK_WIDTH * 2
75 );
76
77 return 0;
78 }
79
80 static int vlGrabFrameCodedDiffBlock(short *src, short *dst, unsigned int dst_pitch)
81 {
82 unsigned int x, y;
83
84 for (y = 0; y < VL_BLOCK_HEIGHT; ++y)
85 for (x = 0; x < VL_BLOCK_WIDTH; ++x)
86 dst[y * dst_pitch + x] = src[y * VL_BLOCK_WIDTH + x] + 0x100;
87
88 return 0;
89 }
90
91 static int vlGrabFieldCodedFullBlock(short *src, short *dst, unsigned int dst_pitch)
92 {
93 unsigned int y;
94
95 for (y = 0; y < VL_BLOCK_HEIGHT / 2; ++y)
96 memcpy
97 (
98 dst + y * dst_pitch * 2,
99 src + y * VL_BLOCK_WIDTH,
100 VL_BLOCK_WIDTH * 2
101 );
102
103 dst += VL_BLOCK_HEIGHT * dst_pitch;
104
105 for (; y < VL_BLOCK_HEIGHT; ++y)
106 memcpy
107 (
108 dst + y * dst_pitch * 2,
109 src + y * VL_BLOCK_WIDTH,
110 VL_BLOCK_WIDTH * 2
111 );
112
113 return 0;
114 }
115
116 static int vlGrabFieldCodedDiffBlock(short *src, short *dst, unsigned int dst_pitch)
117 {
118 unsigned int x, y;
119
120 for (y = 0; y < VL_BLOCK_HEIGHT / 2; ++y)
121 for (x = 0; x < VL_BLOCK_WIDTH; ++x)
122 dst[y * dst_pitch * 2 + x] = src[y * VL_BLOCK_WIDTH + x] + 0x100;
123
124 dst += VL_BLOCK_HEIGHT * dst_pitch;
125
126 for (; y < VL_BLOCK_HEIGHT; ++y)
127 for (x = 0; x < VL_BLOCK_WIDTH; ++x)
128 dst[y * dst_pitch * 2 + x] = src[y * VL_BLOCK_WIDTH + x] + 0x100;
129
130 return 0;
131 }
132
133 static int vlGrabNoBlock(short *dst, unsigned int dst_pitch)
134 {
135 unsigned int x, y;
136
137 for (y = 0; y < VL_BLOCK_HEIGHT; ++y)
138 for (x = 0; x < VL_BLOCK_WIDTH; ++x)
139 dst[y * dst_pitch + x] = 0x100;
140
141 return 0;
142 }
143
144 static int vlGrabBlocks
145 (
146 struct VL_CONTEXT *context,
147 unsigned int coded_block_pattern,
148 enum VL_DCT_TYPE dct_type,
149 enum VL_SAMPLE_TYPE sample_type,
150 short *blocks
151 )
152 {
153 struct pipe_surface *tex_surface;
154 short *texels;
155 unsigned int tex_pitch;
156 unsigned int tb, sb = 0;
157
158 const int do_idct = 1;
159 short temp_block[64];
160
161 assert(context);
162 assert(blocks);
163
164 tex_surface = context->pipe->screen->get_tex_surface
165 (
166 context->pipe->screen,
167 context->states.mc.textures[0],
168 0, 0, 0, PIPE_BUFFER_USAGE_CPU_WRITE
169 );
170
171 texels = pipe_surface_map(tex_surface, PIPE_BUFFER_USAGE_CPU_WRITE);
172 tex_pitch = tex_surface->stride / tex_surface->block.size;
173
174 for (tb = 0; tb < 4; ++tb)
175 {
176 if ((coded_block_pattern >> (5 - tb)) & 1)
177 {
178 if (dct_type == VL_DCT_FRAME_CODED)
179 if (sample_type == VL_FULL_SAMPLE)
180 if (do_idct)
181 {
182 vlTransformBlock(blocks + sb * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT, temp_block, 128);
183 vlGrabFrameCodedFullBlock
184 (
185 temp_block,
186 texels + tb * tex_pitch * VL_BLOCK_HEIGHT,
187 tex_pitch
188 );
189 }
190 else
191 vlGrabFrameCodedFullBlock
192 (
193 blocks + sb * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT,
194 texels + tb * tex_pitch * VL_BLOCK_HEIGHT,
195 tex_pitch
196 );
197 else
198 if (do_idct)
199 {
200 vlTransformBlock(blocks + sb * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT, temp_block, 0);
201 vlGrabFrameCodedDiffBlock
202 (
203 temp_block,
204 texels + tb * tex_pitch * VL_BLOCK_HEIGHT,
205 tex_pitch
206 );
207 }
208 else
209 vlGrabFrameCodedDiffBlock
210 (
211 blocks + sb * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT,
212 texels + tb * tex_pitch * VL_BLOCK_HEIGHT,
213 tex_pitch
214 );
215 else
216 if (sample_type == VL_FULL_SAMPLE)
217 if (do_idct)
218 {
219 vlTransformBlock(blocks + sb * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT, temp_block, 128);
220 vlGrabFieldCodedFullBlock
221 (
222 temp_block,
223 texels + (tb % 2) * tex_pitch * VL_BLOCK_HEIGHT + (tb / 2) * tex_pitch,
224 tex_pitch
225 );
226 }
227 else
228 vlGrabFieldCodedFullBlock
229 (
230 blocks + sb * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT,
231 texels + (tb % 2) * tex_pitch * VL_BLOCK_HEIGHT + (tb / 2) * tex_pitch,
232 tex_pitch
233 );
234 else
235 if (do_idct)
236 {
237 vlTransformBlock(blocks + sb * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT, temp_block, 0);
238 vlGrabFieldCodedDiffBlock
239 (
240 temp_block,
241 texels + (tb % 2) * tex_pitch * VL_BLOCK_HEIGHT + (tb / 2) * tex_pitch,
242 tex_pitch
243 );
244 }
245 else
246 vlGrabFieldCodedDiffBlock
247 (
248 blocks + sb * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT,
249 texels + (tb % 2) * tex_pitch * VL_BLOCK_HEIGHT + (tb / 2) * tex_pitch,
250 tex_pitch
251 );
252 ++sb;
253 }
254 else
255 vlGrabNoBlock(texels + tb * tex_pitch * VL_BLOCK_HEIGHT, tex_pitch);
256 }
257
258 pipe_surface_unmap(tex_surface);
259
260 /* TODO: Implement 422, 444 */
261 for (tb = 0; tb < 2; ++tb)
262 {
263 tex_surface = context->pipe->screen->get_tex_surface
264 (
265 context->pipe->screen,
266 context->states.mc.textures[tb + 1],
267 0, 0, 0, PIPE_BUFFER_USAGE_CPU_WRITE
268 );
269
270 texels = pipe_surface_map(tex_surface, PIPE_BUFFER_USAGE_CPU_WRITE);
271 tex_pitch = tex_surface->stride / tex_surface->block.size;
272
273 if ((coded_block_pattern >> (1 - tb)) & 1)
274 {
275 if (sample_type == VL_FULL_SAMPLE)
276 if (do_idct)
277 {
278 vlTransformBlock(blocks + sb * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT, temp_block, 128);
279 vlGrabFrameCodedFullBlock
280 (
281 temp_block,
282 texels,
283 tex_pitch
284 );
285 }
286 else
287 vlGrabFrameCodedFullBlock
288 (
289 blocks + sb * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT,
290 texels,
291 tex_pitch
292 );
293 else
294 if (do_idct)
295 {
296 vlTransformBlock(blocks + sb * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT, temp_block, 0);
297 vlGrabFrameCodedDiffBlock
298 (
299 temp_block,
300 texels,
301 tex_pitch
302 );
303 }
304 else
305 vlGrabFrameCodedDiffBlock
306 (
307 blocks + sb * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT,
308 texels,
309 tex_pitch
310 );
311
312 ++sb;
313 }
314 else
315 vlGrabNoBlock(texels, tex_pitch);
316
317 pipe_surface_unmap(tex_surface);
318 }
319
320 return 0;
321 }
322
323 int vlCreateSurface(struct VL_CONTEXT *context, struct VL_SURFACE **surface)
324 {
325 struct pipe_context *pipe;
326 struct pipe_texture template;
327 struct VL_SURFACE *sfc;
328
329 assert(context);
330 assert(surface);
331
332 pipe = context->pipe;
333
334 sfc = calloc(1, sizeof(struct VL_SURFACE));
335
336 sfc->context = context;
337 sfc->width = vlRoundUpPOT(context->video_width);
338 sfc->height = vlRoundUpPOT(context->video_height);
339 sfc->format = context->video_format;
340
341 memset(&template, 0, sizeof(struct pipe_texture));
342 template.target = PIPE_TEXTURE_2D;
343 template.format = PIPE_FORMAT_A8R8G8B8_UNORM;
344 template.last_level = 0;
345 template.width[0] = sfc->width;
346 template.height[0] = sfc->height;
347 template.depth[0] = 1;
348 template.compressed = 0;
349 pf_get_block(template.format, &template.block);
350 /* XXX: Needed? */
351 template.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER | PIPE_TEXTURE_USAGE_RENDER_TARGET;
352
353 sfc->texture = pipe->screen->texture_create(pipe->screen, &template);
354
355 *surface = sfc;
356
357 return 0;
358 }
359
360 int vlDestroySurface(struct VL_SURFACE *surface)
361 {
362 assert(surface);
363 pipe_texture_release(&surface->texture);
364 free(surface);
365
366 return 0;
367 }
368
369 int vlRenderIMacroBlock
370 (
371 enum VL_PICTURE picture_type,
372 enum VL_FIELD_ORDER field_order,
373 unsigned int mbx,
374 unsigned int mby,
375 unsigned int coded_block_pattern,
376 enum VL_DCT_TYPE dct_type,
377 short *blocks,
378 struct VL_SURFACE *surface
379 )
380 {
381 struct pipe_context *pipe;
382 struct VL_MC_VS_CONSTS *vs_consts;
383
384 assert(blocks);
385 assert(surface);
386
387 /* TODO: Implement interlaced rendering */
388 if (picture_type != VL_FRAME_PICTURE)
389 return 0;
390
391 vlGrabBlocks(surface->context, coded_block_pattern, dct_type, VL_FULL_SAMPLE, blocks);
392
393 pipe = surface->context->pipe;
394
395 vs_consts = pipe->winsys->buffer_map
396 (
397 pipe->winsys,
398 surface->context->states.mc.vs_const_buf.buffer,
399 PIPE_BUFFER_USAGE_CPU_WRITE
400 );
401
402 vs_consts->scale.x = VL_MACROBLOCK_WIDTH / (float)surface->width;
403 vs_consts->scale.y = VL_MACROBLOCK_HEIGHT / (float)surface->height;
404 vs_consts->scale.z = 1.0f;
405 vs_consts->scale.w = 1.0f;
406 vs_consts->mb_pos_trans.x = (mbx * VL_MACROBLOCK_WIDTH) / (float)surface->width;
407 vs_consts->mb_pos_trans.y = (mby * VL_MACROBLOCK_HEIGHT) / (float)surface->height;
408 vs_consts->mb_pos_trans.z = 0.0f;
409 vs_consts->mb_pos_trans.w = 0.0f;
410
411 pipe->winsys->buffer_unmap(pipe->winsys, surface->context->states.mc.vs_const_buf.buffer);
412
413 surface->context->states.mc.render_target.cbufs[0] = pipe->screen->get_tex_surface
414 (
415 pipe->screen,
416 surface->texture,
417 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE
418 );
419 pipe->set_framebuffer_state(pipe, &surface->context->states.mc.render_target);
420 pipe->set_sampler_textures(pipe, 3, surface->context->states.mc.textures);
421 pipe->bind_sampler_states(pipe, 3, (void**)surface->context->states.mc.samplers);
422 pipe->bind_vs_state(pipe, surface->context->states.mc.i_vs);
423 pipe->bind_fs_state(pipe, surface->context->states.mc.i_fs);
424
425 pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, 0, 24);
426
427 return 0;
428 }
429
430 int vlRenderPMacroBlock
431 (
432 enum VL_PICTURE picture_type,
433 enum VL_FIELD_ORDER field_order,
434 unsigned int mbx,
435 unsigned int mby,
436 enum VL_MC_TYPE mc_type,
437 struct VL_MOTION_VECTOR *motion_vector,
438 unsigned int coded_block_pattern,
439 enum VL_DCT_TYPE dct_type,
440 short *blocks,
441 struct VL_SURFACE *ref_surface,
442 struct VL_SURFACE *surface
443 )
444 {
445 struct pipe_context *pipe;
446 struct VL_MC_VS_CONSTS *vs_consts;
447
448 assert(motion_vectors);
449 assert(blocks);
450 assert(ref_surface);
451 assert(surface);
452
453 /* TODO: Implement interlaced rendering */
454 if (picture_type != VL_FRAME_PICTURE)
455 return 0;
456 /* TODO: Implement other MC types */
457 if (mc_type != VL_FRAME_MC && mc_type != VL_FIELD_MC)
458 return 0;
459
460 vlGrabBlocks(surface->context, coded_block_pattern, dct_type, VL_DIFFERENCE_SAMPLE, blocks);
461
462 pipe = surface->context->pipe;
463
464 vs_consts = pipe->winsys->buffer_map
465 (
466 pipe->winsys,
467 surface->context->states.mc.vs_const_buf.buffer,
468 PIPE_BUFFER_USAGE_CPU_WRITE
469 );
470
471 vs_consts->scale.x = VL_MACROBLOCK_WIDTH / (float)surface->width;
472 vs_consts->scale.y = VL_MACROBLOCK_HEIGHT / (float)surface->height;
473 vs_consts->scale.z = 1.0f;
474 vs_consts->scale.w = 1.0f;
475 vs_consts->mb_pos_trans.x = (mbx * VL_MACROBLOCK_WIDTH) / (float)surface->width;
476 vs_consts->mb_pos_trans.y = (mby * VL_MACROBLOCK_HEIGHT) / (float)surface->height;
477 vs_consts->mb_pos_trans.z = 0.0f;
478 vs_consts->mb_pos_trans.w = 0.0f;
479 vs_consts->mb_tc_trans[0].top_field.x = (mbx * VL_MACROBLOCK_WIDTH + motion_vector->top_field.x * 0.5f) / (float)surface->width;
480 vs_consts->mb_tc_trans[0].top_field.y = (mby * VL_MACROBLOCK_HEIGHT + motion_vector->top_field.y * 0.5f) / (float)surface->height;
481 vs_consts->mb_tc_trans[0].top_field.z = 0.0f;
482 vs_consts->mb_tc_trans[0].top_field.w = 0.0f;
483
484 if (mc_type == VL_FIELD_MC)
485 {
486 vs_consts->denorm.x = (float)surface->width;
487 vs_consts->denorm.y = (float)surface->height;
488
489 vs_consts->mb_tc_trans[0].bottom_field.x = (mbx * VL_MACROBLOCK_WIDTH + motion_vector->bottom_field.x * 0.5f) / (float)surface->width;
490 vs_consts->mb_tc_trans[0].bottom_field.y = (mby * VL_MACROBLOCK_HEIGHT + motion_vector->bottom_field.y * 0.5f) / (float)surface->height;
491 vs_consts->mb_tc_trans[0].bottom_field.z = 0.0f;
492 vs_consts->mb_tc_trans[0].bottom_field.w = 0.0f;
493
494 pipe->bind_vs_state(pipe, surface->context->states.mc.p_vs[1]);
495 pipe->bind_fs_state(pipe, surface->context->states.mc.p_fs[1]);
496 }
497 else
498 {
499 pipe->bind_vs_state(pipe, surface->context->states.mc.p_vs[0]);
500 pipe->bind_fs_state(pipe, surface->context->states.mc.p_fs[0]);
501 }
502
503 pipe->winsys->buffer_unmap(pipe->winsys, surface->context->states.mc.vs_const_buf.buffer);
504
505 surface->context->states.mc.render_target.cbufs[0] = pipe->screen->get_tex_surface
506 (
507 pipe->screen,
508 surface->texture,
509 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE
510 );
511 pipe->set_framebuffer_state(pipe, &surface->context->states.mc.render_target);
512
513 surface->context->states.mc.textures[3] = ref_surface->texture;
514 pipe->set_sampler_textures(pipe, 4, surface->context->states.mc.textures);
515 pipe->bind_sampler_states(pipe, 4, (void**)surface->context->states.mc.samplers);
516
517 pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, 0, 24);
518
519 return 0;
520 }
521
522 int vlRenderBMacroBlock
523 (
524 enum VL_PICTURE picture_type,
525 enum VL_FIELD_ORDER field_order,
526 unsigned int mbx,
527 unsigned int mby,
528 enum VL_MC_TYPE mc_type,
529 struct VL_MOTION_VECTOR *motion_vector,
530 unsigned int coded_block_pattern,
531 enum VL_DCT_TYPE dct_type,
532 short *blocks,
533 struct VL_SURFACE *past_surface,
534 struct VL_SURFACE *future_surface,
535 struct VL_SURFACE *surface
536 )
537 {
538 struct pipe_context *pipe;
539 struct VL_MC_VS_CONSTS *vs_consts;
540
541 assert(motion_vectors);
542 assert(blocks);
543 assert(ref_surface);
544 assert(surface);
545
546 /* TODO: Implement interlaced rendering */
547 if (picture_type != VL_FRAME_PICTURE)
548 return 0;
549 /* TODO: Implement other MC types */
550 if (mc_type != VL_FRAME_MC && mc_type != VL_FIELD_MC)
551 return 0;
552
553 vlGrabBlocks(surface->context, coded_block_pattern, dct_type, VL_DIFFERENCE_SAMPLE, blocks);
554
555 pipe = surface->context->pipe;
556
557 vs_consts = pipe->winsys->buffer_map
558 (
559 pipe->winsys,
560 surface->context->states.mc.vs_const_buf.buffer,
561 PIPE_BUFFER_USAGE_CPU_WRITE
562 );
563
564 vs_consts->scale.x = VL_MACROBLOCK_WIDTH / (float)surface->width;
565 vs_consts->scale.y = VL_MACROBLOCK_HEIGHT / (float)surface->height;
566 vs_consts->scale.z = 1.0f;
567 vs_consts->scale.w = 1.0f;
568 vs_consts->mb_pos_trans.x = (mbx * VL_MACROBLOCK_WIDTH) / (float)surface->width;
569 vs_consts->mb_pos_trans.y = (mby * VL_MACROBLOCK_HEIGHT) / (float)surface->height;
570 vs_consts->mb_pos_trans.z = 0.0f;
571 vs_consts->mb_pos_trans.w = 0.0f;
572 vs_consts->mb_tc_trans[0].top_field.x = (mbx * VL_MACROBLOCK_WIDTH + motion_vector[0].top_field.x * 0.5f) / (float)surface->width;
573 vs_consts->mb_tc_trans[0].top_field.y = (mby * VL_MACROBLOCK_HEIGHT + motion_vector[0].top_field.y * 0.5f) / (float)surface->height;
574 vs_consts->mb_tc_trans[0].top_field.z = 0.0f;
575 vs_consts->mb_tc_trans[0].top_field.w = 0.0f;
576 vs_consts->mb_tc_trans[1].top_field.x = (mbx * VL_MACROBLOCK_WIDTH + motion_vector[1].top_field.x * 0.5f) / (float)surface->width;
577 vs_consts->mb_tc_trans[1].top_field.y = (mby * VL_MACROBLOCK_HEIGHT + motion_vector[1].top_field.y * 0.5f) / (float)surface->height;
578 vs_consts->mb_tc_trans[1].top_field.z = 0.0f;
579 vs_consts->mb_tc_trans[1].top_field.w = 0.0f;
580
581 if (mc_type == VL_FIELD_MC)
582 {
583 vs_consts->denorm.x = (float)surface->width;
584 vs_consts->denorm.y = (float)surface->height;
585
586 vs_consts->mb_tc_trans[0].bottom_field.x = (mbx * VL_MACROBLOCK_WIDTH + motion_vector[0].bottom_field.x * 0.5f) / (float)surface->width;
587 vs_consts->mb_tc_trans[0].bottom_field.y = (mby * VL_MACROBLOCK_HEIGHT + motion_vector[0].bottom_field.y * 0.5f) / (float)surface->height;
588 vs_consts->mb_tc_trans[0].bottom_field.z = 0.0f;
589 vs_consts->mb_tc_trans[0].bottom_field.w = 0.0f;
590 vs_consts->mb_tc_trans[1].bottom_field.x = (mbx * VL_MACROBLOCK_WIDTH + motion_vector[1].bottom_field.x * 0.5f) / (float)surface->width;
591 vs_consts->mb_tc_trans[1].bottom_field.y = (mby * VL_MACROBLOCK_HEIGHT + motion_vector[1].bottom_field.y * 0.5f) / (float)surface->height;
592 vs_consts->mb_tc_trans[1].bottom_field.z = 0.0f;
593 vs_consts->mb_tc_trans[1].bottom_field.w = 0.0f;
594
595 pipe->bind_vs_state(pipe, surface->context->states.mc.b_vs[1]);
596 pipe->bind_fs_state(pipe, surface->context->states.mc.b_fs[1]);
597 }
598 else
599 {
600 pipe->bind_vs_state(pipe, surface->context->states.mc.b_vs[0]);
601 pipe->bind_fs_state(pipe, surface->context->states.mc.b_fs[0]);
602 }
603
604 pipe->winsys->buffer_unmap(pipe->winsys, surface->context->states.mc.vs_const_buf.buffer);
605
606 surface->context->states.mc.render_target.cbufs[0] = pipe->screen->get_tex_surface
607 (
608 pipe->screen,
609 surface->texture,
610 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE
611 );
612 pipe->set_framebuffer_state(pipe, &surface->context->states.mc.render_target);
613
614 surface->context->states.mc.textures[3] = past_surface->texture;
615 surface->context->states.mc.textures[4] = future_surface->texture;
616 pipe->set_sampler_textures(pipe, 5, surface->context->states.mc.textures);
617 pipe->bind_sampler_states(pipe, 5, (void**)surface->context->states.mc.samplers);
618
619 pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, 0, 24);
620
621 return 0;
622 }
623
624 int vlPutSurface
625 (
626 struct VL_SURFACE *surface,
627 Drawable drawable,
628 unsigned int srcx,
629 unsigned int srcy,
630 unsigned int srcw,
631 unsigned int srch,
632 unsigned int destx,
633 unsigned int desty,
634 unsigned int destw,
635 unsigned int desth,
636 enum VL_PICTURE picture_type
637 )
638 {
639 unsigned int create_fb = 0;
640 struct pipe_context *pipe;
641 struct VL_CSC_VS_CONSTS *vs_consts;
642
643 assert(surface);
644
645 pipe = surface->context->pipe;
646
647 if (!surface->context->states.csc.framebuffer.cbufs[0])
648 create_fb = 1;
649 else if
650 (
651 surface->context->states.csc.framebuffer.width != destw ||
652 surface->context->states.csc.framebuffer.height != desth
653 )
654 {
655 pipe->winsys->surface_release
656 (
657 pipe->winsys,
658 &surface->context->states.csc.framebuffer.cbufs[0]
659 );
660
661 create_fb = 1;
662 }
663
664 if (create_fb)
665 {
666 surface->context->states.csc.viewport.scale[0] = destw;
667 surface->context->states.csc.viewport.scale[1] = desth;
668 surface->context->states.csc.viewport.scale[2] = 1;
669 surface->context->states.csc.viewport.scale[3] = 1;
670 surface->context->states.csc.viewport.translate[0] = 0;
671 surface->context->states.csc.viewport.translate[1] = 0;
672 surface->context->states.csc.viewport.translate[2] = 0;
673 surface->context->states.csc.viewport.translate[3] = 0;
674
675 surface->context->states.csc.framebuffer.width = destw;
676 surface->context->states.csc.framebuffer.height = desth;
677 surface->context->states.csc.framebuffer.cbufs[0] = pipe->winsys->surface_alloc(pipe->winsys);
678 pipe->winsys->surface_alloc_storage
679 (
680 pipe->winsys,
681 surface->context->states.csc.framebuffer.cbufs[0],
682 destw,
683 desth,
684 PIPE_FORMAT_A8R8G8B8_UNORM,
685 /* XXX: SoftPipe doesn't change GPU usage to CPU like it does for textures */
686 PIPE_BUFFER_USAGE_CPU_READ | PIPE_BUFFER_USAGE_CPU_WRITE,
687 0
688 );
689 }
690
691 vlEndRender(surface->context);
692
693 vs_consts = pipe->winsys->buffer_map
694 (
695 pipe->winsys,
696 surface->context->states.csc.vs_const_buf.buffer,
697 PIPE_BUFFER_USAGE_CPU_WRITE
698 );
699
700 vs_consts->src_scale.x = srcw / (float)surface->width;
701 vs_consts->src_scale.y = srch / (float)surface->height;
702 vs_consts->src_scale.z = 1;
703 vs_consts->src_scale.w = 1;
704 vs_consts->src_trans.x = srcx / (float)surface->width;
705 vs_consts->src_trans.y = srcy / (float)surface->height;
706 vs_consts->src_trans.z = 0;
707 vs_consts->src_trans.w = 0;
708
709 pipe->winsys->buffer_unmap(pipe->winsys, surface->context->states.csc.vs_const_buf.buffer);
710
711 pipe->set_sampler_textures(pipe, 1, &surface->texture);
712 pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLE_STRIP, 0, 4);
713 pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
714 /* TODO: Need to take destx, desty into consideration */
715 pipe->winsys->flush_frontbuffer
716 (
717 pipe->winsys,
718 surface->context->states.csc.framebuffer.cbufs[0],
719 &drawable
720 );
721
722 vlBeginRender(surface->context);
723
724 return 0;
725 }
726