g3dvl: Reduce number of input vert streams by copying, reusing in shaders.
[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
11 static int vlGrabBlocks
12 (
13 struct VL_CONTEXT *context,
14 unsigned int coded_block_pattern,
15 enum VL_DCT_TYPE dct_type,
16 enum VL_SAMPLE_TYPE sample_type,
17 short *blocks
18 )
19 {
20 struct pipe_surface *tex_surface;
21 short *texels;
22 unsigned int b, x, y, y2;
23
24 assert(context);
25 assert(blocks);
26
27 tex_surface = context->pipe->screen->get_tex_surface
28 (
29 context->pipe->screen,
30 context->states.mc.textures[0],
31 0, 0, 0, PIPE_BUFFER_USAGE_CPU_WRITE
32 );
33
34 texels = pipe_surface_map(tex_surface, 0);
35
36 for (b = 0; b < 4; ++b)
37 {
38 if ((coded_block_pattern >> b) & 1)
39 {
40 if (dct_type == VL_DCT_FRAME_CODED)
41 {
42 if (sample_type == VL_FULL_SAMPLE)
43 {
44 for (y = VL_BLOCK_HEIGHT * b; y < VL_BLOCK_HEIGHT * (b + 1); ++y)
45 memcpy
46 (
47 texels + y * tex_surface->pitch,
48 blocks + y * VL_BLOCK_WIDTH,
49 VL_BLOCK_WIDTH * 2
50 );
51 }
52 else
53 {
54 for (y = VL_BLOCK_HEIGHT * b; y < VL_BLOCK_HEIGHT * (b + 1); ++y)
55 for (x = 0; x < VL_BLOCK_WIDTH; ++x)
56 texels[y * tex_surface->pitch + x] =
57 blocks[y * VL_BLOCK_WIDTH + x] + 0x100;
58 }
59 }
60 else
61 {
62 if (sample_type == VL_FULL_SAMPLE)
63 {
64 for
65 (
66 y = VL_BLOCK_HEIGHT * (b % 2), y2 = VL_BLOCK_HEIGHT * b;
67 y < VL_BLOCK_HEIGHT * ((b % 2) + 1);
68 y += 2, ++y2
69 )
70 memcpy
71 (
72 texels + y * tex_surface->pitch,
73 blocks + y2 * VL_BLOCK_WIDTH,
74 VL_BLOCK_WIDTH * 2
75 );
76 for
77 (
78 y = VL_BLOCK_HEIGHT * ((b % 2) + 2);
79 y < VL_BLOCK_HEIGHT * (((b % 2) + 2) + 1);
80 y += 2, ++y2
81 )
82 memcpy
83 (
84 texels + y * tex_surface->pitch,
85 blocks + y2 * VL_BLOCK_WIDTH,
86 VL_BLOCK_WIDTH * 2
87 );
88 }
89 else
90 {
91 for
92 (
93 y = VL_BLOCK_HEIGHT * (b % 2), y2 = VL_BLOCK_HEIGHT * b;
94 y < VL_BLOCK_HEIGHT * ((b % 2) + 1);
95 y += 2, ++y2
96 )
97 for (x = 0; x < VL_BLOCK_WIDTH; ++x)
98 texels[y * tex_surface->pitch + x] =
99 blocks[y2 * VL_BLOCK_WIDTH + x] + 0x100;
100 for
101 (
102 y = VL_BLOCK_HEIGHT * ((b % 2) + 2);
103 y < VL_BLOCK_HEIGHT * (((b % 2) + 2) + 1);
104 y += 2, ++y2
105 )
106 for (x = 0; x < VL_BLOCK_WIDTH; ++x)
107 texels[y * tex_surface->pitch + x] =
108 blocks[y2 * VL_BLOCK_WIDTH + x] + 0x100;
109 }
110 }
111 }
112 else
113 {
114 for (y = VL_BLOCK_HEIGHT * b; y < VL_BLOCK_HEIGHT * (b + 1); ++y)
115 {
116 for (x = 0; x < VL_BLOCK_WIDTH; ++x)
117 texels[y * tex_surface->pitch + x] = 0x100;
118 }
119 }
120 }
121
122 pipe_surface_unmap(tex_surface);
123
124 /* TODO: Implement 422, 444 */
125 for (b = 0; b < 2; ++b)
126 {
127 tex_surface = context->pipe->screen->get_tex_surface
128 (
129 context->pipe->screen,
130 context->states.mc.textures[b + 1],
131 0, 0, 0, PIPE_BUFFER_USAGE_CPU_WRITE
132 );
133
134 texels = pipe_surface_map(tex_surface, 0);
135
136 if ((coded_block_pattern >> (b + 4)) & 1)
137 {
138 if (sample_type == VL_FULL_SAMPLE)
139 {
140 for (y = 0; y < tex_surface->height; ++y)
141 memcpy
142 (
143 texels + y * tex_surface->pitch,
144 blocks + VL_BLOCK_SIZE * (b + 4) + y * VL_BLOCK_WIDTH,
145 VL_BLOCK_WIDTH * 2
146 );
147 }
148 else
149 {
150 for (y = 0; y < tex_surface->height; ++y)
151 for (x = 0; x < VL_BLOCK_WIDTH; ++x)
152 texels[y * tex_surface->pitch + x] =
153 blocks[VL_BLOCK_SIZE * (b + 4) + y * VL_BLOCK_WIDTH + x] + 0x100;
154 }
155 }
156 else
157 {
158 for (y = 0; y < tex_surface->height; ++y)
159 {
160 for (x = 0; x < VL_BLOCK_WIDTH; ++x)
161 texels[y * tex_surface->pitch + x] = 0x100;
162 }
163 }
164
165 pipe_surface_unmap(tex_surface);
166 }
167
168 return 0;
169 }
170
171 int vlCreateSurface(struct VL_CONTEXT *context, struct VL_SURFACE **surface)
172 {
173 struct pipe_context *pipe;
174 struct pipe_texture template;
175 struct VL_SURFACE *sfc;
176
177 assert(context);
178 assert(surface);
179
180 pipe = context->pipe;
181
182 sfc = calloc(1, sizeof(struct VL_SURFACE));
183
184 sfc->context = context;
185 sfc->width = context->video_width;
186 sfc->height = context->video_height;
187 sfc->format = context->video_format;
188
189 memset(&template, 0, sizeof(struct pipe_texture));
190 template.target = PIPE_TEXTURE_2D;
191 template.format = PIPE_FORMAT_A8R8G8B8_UNORM;
192 template.last_level = 0;
193 template.width[0] = sfc->width;
194 template.height[0] = sfc->height;
195 template.depth[0] = 1;
196 template.compressed = 0;
197 template.cpp = 4;
198
199 sfc->texture = pipe->screen->texture_create(pipe->screen, &template);
200
201 *surface = sfc;
202
203 return 0;
204 }
205
206 int vlDestroySurface(struct VL_SURFACE *surface)
207 {
208 assert(surface);
209 pipe_texture_release(&surface->texture);
210 free(surface);
211
212 return 0;
213 }
214
215 int vlRenderIMacroBlock
216 (
217 enum VL_PICTURE picture_type,
218 enum VL_FIELD_ORDER field_order,
219 unsigned int mbx,
220 unsigned int mby,
221 unsigned int coded_block_pattern,
222 enum VL_DCT_TYPE dct_type,
223 short *blocks,
224 struct VL_SURFACE *surface
225 )
226 {
227 struct pipe_context *pipe;
228 struct VL_MC_VS_CONSTS *vscbdata;
229
230 assert(blocks);
231 assert(surface);
232
233 /* TODO: Implement interlaced rendering */
234 /*assert(picture_type == VL_FRAME_PICTURE);*/
235 if (picture_type != VL_FRAME_PICTURE)
236 {
237 /*fprintf(stderr, "field picture (I) unimplemented, ignoring\n");*/
238 return 0;
239 }
240
241 pipe = surface->context->pipe;
242
243 vscbdata = pipe->winsys->buffer_map
244 (
245 pipe->winsys,
246 surface->context->states.mc.vs_const_buf.buffer,
247 PIPE_BUFFER_USAGE_CPU_WRITE
248 );
249
250 vscbdata->scale.x = VL_MACROBLOCK_WIDTH / (float)surface->width;
251 vscbdata->scale.y = VL_MACROBLOCK_HEIGHT / (float)surface->height;
252 vscbdata->scale.z = 1.0f;
253 vscbdata->scale.w = 1.0f;
254 vscbdata->mb_pos_trans.x = (mbx * VL_MACROBLOCK_WIDTH) / (float)surface->width;
255 vscbdata->mb_pos_trans.y = (mby * VL_MACROBLOCK_HEIGHT) / (float)surface->height;
256 vscbdata->mb_pos_trans.z = 0.0f;
257 vscbdata->mb_pos_trans.w = 0.0f;
258
259 pipe->winsys->buffer_unmap(pipe->winsys, surface->context->states.mc.vs_const_buf.buffer);
260
261 vlGrabBlocks(surface->context, coded_block_pattern, dct_type, VL_FULL_SAMPLE, blocks);
262
263 surface->context->states.mc.render_target.cbufs[0] = pipe->screen->get_tex_surface
264 (
265 pipe->screen,
266 surface->texture,
267 0, 0, 0, PIPE_BUFFER_USAGE_CPU_READ | PIPE_BUFFER_USAGE_CPU_WRITE
268 );
269 pipe->set_framebuffer_state(pipe, &surface->context->states.mc.render_target);
270 pipe->set_sampler_textures(pipe, 3, surface->context->states.mc.textures);
271 pipe->bind_sampler_states(pipe, 3, (void**)surface->context->states.mc.samplers);
272 pipe->bind_vs_state(pipe, surface->context->states.mc.i_vs);
273 pipe->bind_fs_state(pipe, surface->context->states.mc.i_fs);
274
275 pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, 0, 24);
276
277 return 0;
278 }
279
280 int vlRenderPMacroBlock
281 (
282 enum VL_PICTURE picture_type,
283 enum VL_FIELD_ORDER field_order,
284 unsigned int mbx,
285 unsigned int mby,
286 enum VL_MC_TYPE mc_type,
287 struct VL_MOTION_VECTOR *motion_vector,
288 unsigned int coded_block_pattern,
289 enum VL_DCT_TYPE dct_type,
290 short *blocks,
291 struct VL_SURFACE *ref_surface,
292 struct VL_SURFACE *surface
293 )
294 {
295 struct pipe_context *pipe;
296 struct VL_MC_VS_CONSTS *vscbdata;
297
298 assert(motion_vectors);
299 assert(blocks);
300 assert(ref_surface);
301 assert(surface);
302
303 /* TODO: Implement interlaced rendering */
304 /*assert(picture_type == VL_FRAME_PICTURE);*/
305 if (picture_type != VL_FRAME_PICTURE)
306 {
307 /*fprintf(stderr, "field picture (P) unimplemented, ignoring\n");*/
308 return 0;
309 }
310 /* TODO: Implement field based motion compensation */
311 /*assert(mc_type == VL_FRAME_MC);*/
312 if (mc_type != VL_FRAME_MC)
313 {
314 /*fprintf(stderr, "field MC (P) unimplemented, ignoring\n");*/
315 return 0;
316 }
317
318 pipe = surface->context->pipe;
319
320 vscbdata = pipe->winsys->buffer_map
321 (
322 pipe->winsys,
323 surface->context->states.mc.vs_const_buf.buffer,
324 PIPE_BUFFER_USAGE_CPU_WRITE
325 );
326
327 vscbdata->scale.x = VL_MACROBLOCK_WIDTH / (float)surface->width;
328 vscbdata->scale.y = VL_MACROBLOCK_HEIGHT / (float)surface->height;
329 vscbdata->scale.z = 1.0f;
330 vscbdata->scale.w = 1.0f;
331 vscbdata->mb_pos_trans.x = (mbx * VL_MACROBLOCK_WIDTH) / (float)surface->width;
332 vscbdata->mb_pos_trans.y = (mby * VL_MACROBLOCK_HEIGHT) / (float)surface->height;
333 vscbdata->mb_pos_trans.z = 0.0f;
334 vscbdata->mb_pos_trans.w = 0.0f;
335 vscbdata->mb_tc_trans[0].x = (mbx * VL_MACROBLOCK_WIDTH + motion_vector->top_field.x * 0.5f) / (float)surface->width;
336 vscbdata->mb_tc_trans[0].y = (mby * VL_MACROBLOCK_HEIGHT + motion_vector->top_field.y * 0.5f) / (float)surface->height;
337 vscbdata->mb_tc_trans[0].z = 0.0f;
338 vscbdata->mb_tc_trans[0].w = 0.0f;
339
340 pipe->winsys->buffer_unmap(pipe->winsys, surface->context->states.mc.vs_const_buf.buffer);
341
342 vlGrabBlocks(surface->context, coded_block_pattern, dct_type, VL_DIFFERENCE_SAMPLE, blocks);
343
344 surface->context->states.mc.render_target.cbufs[0] = pipe->screen->get_tex_surface
345 (
346 pipe->screen,
347 surface->texture,
348 0, 0, 0, PIPE_BUFFER_USAGE_CPU_READ | PIPE_BUFFER_USAGE_CPU_WRITE
349 );
350 pipe->set_framebuffer_state(pipe, &surface->context->states.mc.render_target);
351
352 surface->context->states.mc.textures[3] = ref_surface->texture;
353 pipe->set_sampler_textures(pipe, 4, surface->context->states.mc.textures);
354 pipe->bind_sampler_states(pipe, 4, (void**)surface->context->states.mc.samplers);
355 pipe->bind_vs_state(pipe, surface->context->states.mc.p_vs);
356 pipe->bind_fs_state(pipe, surface->context->states.mc.p_fs);
357
358 pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, 0, 24);
359
360 return 0;
361 }
362
363 int vlRenderBMacroBlock
364 (
365 enum VL_PICTURE picture_type,
366 enum VL_FIELD_ORDER field_order,
367 unsigned int mbx,
368 unsigned int mby,
369 enum VL_MC_TYPE mc_type,
370 struct VL_MOTION_VECTOR *motion_vector,
371 unsigned int coded_block_pattern,
372 enum VL_DCT_TYPE dct_type,
373 short *blocks,
374 struct VL_SURFACE *past_surface,
375 struct VL_SURFACE *future_surface,
376 struct VL_SURFACE *surface
377 )
378 {
379 struct pipe_context *pipe;
380 struct VL_MC_VS_CONSTS *vscbdata;
381
382 assert(motion_vectors);
383 assert(blocks);
384 assert(ref_surface);
385 assert(surface);
386
387 /* TODO: Implement interlaced rendering */
388 /*assert(picture_type == VL_FRAME_PICTURE);*/
389 if (picture_type != VL_FRAME_PICTURE)
390 {
391 /*fprintf(stderr, "field picture (B) unimplemented, ignoring\n");*/
392 return 0;
393 }
394 /* TODO: Implement field based motion compensation */
395 /*assert(mc_type == VL_FRAME_MC);*/
396 if (mc_type != VL_FRAME_MC)
397 {
398 /*fprintf(stderr, "field MC (B) unimplemented, ignoring\n");*/
399 return 0;
400 }
401
402 pipe = surface->context->pipe;
403
404 vscbdata = pipe->winsys->buffer_map
405 (
406 pipe->winsys,
407 surface->context->states.mc.vs_const_buf.buffer,
408 PIPE_BUFFER_USAGE_CPU_WRITE
409 );
410
411 vscbdata->scale.x = VL_MACROBLOCK_WIDTH / (float)surface->width;
412 vscbdata->scale.y = VL_MACROBLOCK_HEIGHT / (float)surface->height;
413 vscbdata->scale.z = 1.0f;
414 vscbdata->scale.w = 1.0f;
415 vscbdata->mb_pos_trans.x = (mbx * VL_MACROBLOCK_WIDTH) / (float)surface->width;
416 vscbdata->mb_pos_trans.y = (mby * VL_MACROBLOCK_HEIGHT) / (float)surface->height;
417 vscbdata->mb_pos_trans.z = 0.0f;
418 vscbdata->mb_pos_trans.w = 0.0f;
419 vscbdata->mb_tc_trans[0].x = (mbx * VL_MACROBLOCK_WIDTH + motion_vector[0].top_field.x * 0.5f) / (float)surface->width;
420 vscbdata->mb_tc_trans[0].y = (mby * VL_MACROBLOCK_HEIGHT + motion_vector[0].top_field.y * 0.5f) / (float)surface->height;
421 vscbdata->mb_tc_trans[0].z = 0.0f;
422 vscbdata->mb_tc_trans[0].w = 0.0f;
423 vscbdata->mb_tc_trans[1].x = (mbx * VL_MACROBLOCK_WIDTH + motion_vector[1].top_field.x * 0.5f) / (float)surface->width;
424 vscbdata->mb_tc_trans[1].y = (mby * VL_MACROBLOCK_HEIGHT + motion_vector[1].top_field.y * 0.5f) / (float)surface->height;
425 vscbdata->mb_tc_trans[1].z = 0.0f;
426 vscbdata->mb_tc_trans[1].w = 0.0f;
427
428 pipe->winsys->buffer_unmap(pipe->winsys, surface->context->states.mc.vs_const_buf.buffer);
429
430 vlGrabBlocks(surface->context, coded_block_pattern, dct_type, VL_DIFFERENCE_SAMPLE, blocks);
431
432 surface->context->states.mc.render_target.cbufs[0] = pipe->screen->get_tex_surface
433 (
434 pipe->screen,
435 surface->texture,
436 0, 0, 0, PIPE_BUFFER_USAGE_CPU_READ | PIPE_BUFFER_USAGE_CPU_WRITE
437 );
438 pipe->set_framebuffer_state(pipe, &surface->context->states.mc.render_target);
439
440 surface->context->states.mc.textures[3] = past_surface->texture;
441 surface->context->states.mc.textures[4] = future_surface->texture;
442 pipe->set_sampler_textures(pipe, 5, surface->context->states.mc.textures);
443 pipe->bind_sampler_states(pipe, 5, (void**)surface->context->states.mc.samplers);
444 pipe->bind_vs_state(pipe, surface->context->states.mc.b_vs);
445 pipe->bind_fs_state(pipe, surface->context->states.mc.b_fs);
446
447 pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, 0, 24);
448
449 return 0;
450 }
451
452 int vlPutSurface
453 (
454 struct VL_SURFACE *surface,
455 Drawable drawable,
456 unsigned int srcx,
457 unsigned int srcy,
458 unsigned int srcw,
459 unsigned int srch,
460 unsigned int destx,
461 unsigned int desty,
462 unsigned int destw,
463 unsigned int desth,
464 enum VL_PICTURE picture_type
465 )
466 {
467 unsigned int create_fb = 0;
468 struct pipe_context *pipe;
469
470 assert(surface);
471
472 pipe = surface->context->pipe;
473
474 if (!surface->context->states.csc.framebuffer.cbufs[0])
475 create_fb = 1;
476 else if
477 (
478 surface->context->states.csc.framebuffer.width != destw ||
479 surface->context->states.csc.framebuffer.height != desth
480 )
481 {
482 pipe->winsys->surface_release
483 (
484 pipe->winsys,
485 &surface->context->states.csc.framebuffer.cbufs[0]
486 );
487
488 create_fb = 1;
489 }
490
491 if (create_fb)
492 {
493 surface->context->states.csc.viewport.scale[0] = destw;
494 surface->context->states.csc.viewport.scale[1] = desth;
495 surface->context->states.csc.viewport.scale[2] = 1;
496 surface->context->states.csc.viewport.scale[3] = 1;
497 surface->context->states.csc.viewport.translate[0] = 0;
498 surface->context->states.csc.viewport.translate[1] = 0;
499 surface->context->states.csc.viewport.translate[2] = 0;
500 surface->context->states.csc.viewport.translate[3] = 0;
501
502 surface->context->states.csc.framebuffer.width = destw;
503 surface->context->states.csc.framebuffer.height = desth;
504 surface->context->states.csc.framebuffer.cbufs[0] = pipe->winsys->surface_alloc(pipe->winsys);
505 pipe->winsys->surface_alloc_storage
506 (
507 pipe->winsys,
508 surface->context->states.csc.framebuffer.cbufs[0],
509 destw,
510 desth,
511 PIPE_FORMAT_A8R8G8B8_UNORM,
512 PIPE_BUFFER_USAGE_CPU_READ | PIPE_BUFFER_USAGE_CPU_WRITE,
513 0
514 );
515 }
516
517 vlEndRender(surface->context);
518
519 pipe->set_sampler_textures(pipe, 1, &surface->texture);
520 pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLE_STRIP, 0, 4);
521 pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
522 pipe->winsys->flush_frontbuffer
523 (
524 pipe->winsys,
525 surface->context->states.csc.framebuffer.cbufs[0],
526 &drawable
527 );
528
529 vlBeginRender(surface->context);
530
531 return 0;
532 }
533