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