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