5d3458afd27451916b98e71d5f3c118ac88302ac
[mesa.git] / src / gallium / auxiliary / vl / vl_compositor.c
1 #include "vl_compositor.h"
2 #include <assert.h>
3 #include <pipe/p_context.h>
4 #include <pipe/p_inlines.h>
5 #include <tgsi/tgsi_parse.h>
6 #include <tgsi/tgsi_build.h>
7 #include <util/u_memory.h>
8 #include "vl_csc.h"
9 #include "vl_shader_build.h"
10
11 struct vertex2f
12 {
13 float x, y;
14 };
15
16 struct vertex4f
17 {
18 float x, y, z, w;
19 };
20
21 struct vertex_shader_consts
22 {
23 struct vertex4f dst_scale;
24 struct vertex4f dst_trans;
25 struct vertex4f src_scale;
26 struct vertex4f src_trans;
27 };
28
29 struct fragment_shader_consts
30 {
31 float matrix[16];
32 };
33
34 /*
35 * Represents 2 triangles in a strip in normalized coords.
36 * Used to render the surface onto the frame buffer.
37 */
38 static const struct vertex2f surface_verts[4] =
39 {
40 {0.0f, 0.0f},
41 {0.0f, 1.0f},
42 {1.0f, 0.0f},
43 {1.0f, 1.0f}
44 };
45
46 /*
47 * Represents texcoords for the above. We can use the position values directly.
48 * TODO: Duplicate these in the shader, no need to create a buffer.
49 */
50 static const struct vertex2f *surface_texcoords = surface_verts;
51
52 static void
53 create_vert_shader(struct vl_compositor *c)
54 {
55 const unsigned max_tokens = 50;
56
57 struct pipe_shader_state vs;
58 struct tgsi_token *tokens;
59 struct tgsi_header *header;
60
61 struct tgsi_full_declaration decl;
62 struct tgsi_full_instruction inst;
63
64 unsigned ti;
65
66 unsigned i;
67
68 assert(c);
69
70 tokens = (struct tgsi_token*)MALLOC(max_tokens * sizeof(struct tgsi_token));
71 *(struct tgsi_version*)&tokens[0] = tgsi_build_version();
72 header = (struct tgsi_header*)&tokens[1];
73 *header = tgsi_build_header();
74 *(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_VERTEX, header);
75
76 ti = 3;
77
78 /*
79 * decl i0 ; Vertex pos
80 * decl i1 ; Vertex texcoords
81 */
82 for (i = 0; i < 2; i++) {
83 decl = vl_decl_input(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i);
84 ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
85 }
86
87 /*
88 * decl c0 ; Scaling vector to scale vertex pos rect to destination size
89 * decl c1 ; Translation vector to move vertex pos rect into position
90 * decl c2 ; Scaling vector to scale texcoord rect to source size
91 * decl c3 ; Translation vector to move texcoord rect into position
92 */
93 decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 3);
94 ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
95
96 /*
97 * decl o0 ; Vertex pos
98 * decl o1 ; Vertex texcoords
99 */
100 for (i = 0; i < 2; i++) {
101 decl = vl_decl_output(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i);
102 ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
103 }
104
105 /* decl t0, t1 */
106 decl = vl_decl_temps(0, 1);
107 ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
108
109 /*
110 * mad o0, i0, c0, c1 ; Scale and translate unit output rect to destination size and pos
111 * mad o1, i1, c2, c3 ; Scale and translate unit texcoord rect to source size and pos
112 */
113 for (i = 0; i < 2; ++i) {
114 inst = vl_inst4(TGSI_OPCODE_MAD, TGSI_FILE_OUTPUT, i, TGSI_FILE_INPUT, i, TGSI_FILE_CONSTANT, i * 2, TGSI_FILE_CONSTANT, i * 2 + 1);
115 ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
116 }
117
118 /* end */
119 inst = vl_end();
120 ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
121
122 assert(ti <= max_tokens);
123
124 vs.tokens = tokens;
125 c->vertex_shader = c->pipe->create_vs_state(c->pipe, &vs);
126 FREE(tokens);
127 }
128
129 static void
130 create_frag_shader(struct vl_compositor *c)
131 {
132 const unsigned max_tokens = 50;
133
134 struct pipe_shader_state fs;
135 struct tgsi_token *tokens;
136 struct tgsi_header *header;
137
138 struct tgsi_full_declaration decl;
139 struct tgsi_full_instruction inst;
140
141 unsigned ti;
142
143 unsigned i;
144
145 assert(c);
146
147 tokens = (struct tgsi_token*)MALLOC(max_tokens * sizeof(struct tgsi_token));
148 *(struct tgsi_version*)&tokens[0] = tgsi_build_version();
149 header = (struct tgsi_header*)&tokens[1];
150 *header = tgsi_build_header();
151 *(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_FRAGMENT, header);
152
153 ti = 3;
154
155 /* decl i0 ; Texcoords for s0 */
156 decl = vl_decl_interpolated_input(TGSI_SEMANTIC_GENERIC, 1, 0, 0, TGSI_INTERPOLATE_LINEAR);
157 ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
158
159 /*
160 * decl c0-c3 ; CSC matrix c0-c3
161 */
162 decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 3);
163 ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
164
165 /* decl o0 ; Fragment color */
166 decl = vl_decl_output(TGSI_SEMANTIC_COLOR, 0, 0, 0);
167 ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
168
169 /* decl t0 */
170 decl = vl_decl_temps(0, 0);
171 ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
172
173 /* decl s0 ; Sampler for tex containing picture to display */
174 decl = vl_decl_samplers(0, 0);
175 ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
176
177 /* tex2d t0, i0, s0 ; Read src pixel */
178 inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_INPUT, 0, TGSI_FILE_SAMPLER, 0);
179 ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
180
181 /*
182 * dp4 o0.x, t0, c0 ; Multiply pixel by the color conversion matrix
183 * dp4 o0.y, t0, c1
184 * dp4 o0.z, t0, c2
185 * dp4 o0.w, t0, c3
186 */
187 for (i = 0; i < 4; ++i) {
188 inst = vl_inst3(TGSI_OPCODE_DP4, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, i);
189 inst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i;
190 ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
191 }
192
193 /* end */
194 inst = vl_end();
195 ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
196
197 assert(ti <= max_tokens);
198
199 fs.tokens = tokens;
200 c->fragment_shader = c->pipe->create_fs_state(c->pipe, &fs);
201 FREE(tokens);
202 }
203
204 static bool
205 init_pipe_state(struct vl_compositor *c)
206 {
207 struct pipe_sampler_state sampler;
208
209 assert(c);
210
211 c->fb_state.nr_cbufs = 1;
212 c->fb_state.zsbuf = NULL;
213
214 sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
215 sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
216 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
217 sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR;
218 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
219 sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
220 sampler.compare_mode = PIPE_TEX_COMPARE_NONE;
221 sampler.compare_func = PIPE_FUNC_ALWAYS;
222 sampler.normalized_coords = 1;
223 /*sampler.prefilter = ;*/
224 /*sampler.lod_bias = ;*/
225 /*sampler.min_lod = ;*/
226 /*sampler.max_lod = ;*/
227 /*sampler.border_color[i] = ;*/
228 /*sampler.max_anisotropy = ;*/
229 c->sampler = c->pipe->create_sampler_state(c->pipe, &sampler);
230
231 return true;
232 }
233
234 static void cleanup_pipe_state(struct vl_compositor *c)
235 {
236 assert(c);
237
238 c->pipe->delete_sampler_state(c->pipe, c->sampler);
239 }
240
241 static bool
242 init_shaders(struct vl_compositor *c)
243 {
244 assert(c);
245
246 create_vert_shader(c);
247 create_frag_shader(c);
248
249 return true;
250 }
251
252 static void cleanup_shaders(struct vl_compositor *c)
253 {
254 assert(c);
255
256 c->pipe->delete_vs_state(c->pipe, c->vertex_shader);
257 c->pipe->delete_fs_state(c->pipe, c->fragment_shader);
258 }
259
260 static bool
261 init_buffers(struct vl_compositor *c)
262 {
263 struct fragment_shader_consts fsc;
264
265 assert(c);
266
267 /*
268 * Create our vertex buffer and vertex buffer element
269 * VB contains 4 vertices that render a quad covering the entire window
270 * to display a rendered surface
271 * Quad is rendered as a tri strip
272 */
273 c->vertex_bufs[0].stride = sizeof(struct vertex2f);
274 c->vertex_bufs[0].max_index = 3;
275 c->vertex_bufs[0].buffer_offset = 0;
276 c->vertex_bufs[0].buffer = pipe_buffer_create
277 (
278 c->pipe->screen,
279 1,
280 PIPE_BUFFER_USAGE_VERTEX,
281 sizeof(struct vertex2f) * 4
282 );
283
284 memcpy
285 (
286 pipe_buffer_map(c->pipe->screen, c->vertex_bufs[0].buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
287 surface_verts,
288 sizeof(struct vertex2f) * 4
289 );
290
291 pipe_buffer_unmap(c->pipe->screen, c->vertex_bufs[0].buffer);
292
293 c->vertex_elems[0].src_offset = 0;
294 c->vertex_elems[0].vertex_buffer_index = 0;
295 c->vertex_elems[0].nr_components = 2;
296 c->vertex_elems[0].src_format = PIPE_FORMAT_R32G32_FLOAT;
297
298 /*
299 * Create our texcoord buffer and texcoord buffer element
300 * Texcoord buffer contains the TCs for mapping the rendered surface to the 4 vertices
301 */
302 c->vertex_bufs[1].stride = sizeof(struct vertex2f);
303 c->vertex_bufs[1].max_index = 3;
304 c->vertex_bufs[1].buffer_offset = 0;
305 c->vertex_bufs[1].buffer = pipe_buffer_create
306 (
307 c->pipe->screen,
308 1,
309 PIPE_BUFFER_USAGE_VERTEX,
310 sizeof(struct vertex2f) * 4
311 );
312
313 memcpy
314 (
315 pipe_buffer_map(c->pipe->screen, c->vertex_bufs[1].buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
316 surface_texcoords,
317 sizeof(struct vertex2f) * 4
318 );
319
320 pipe_buffer_unmap(c->pipe->screen, c->vertex_bufs[1].buffer);
321
322 c->vertex_elems[1].src_offset = 0;
323 c->vertex_elems[1].vertex_buffer_index = 1;
324 c->vertex_elems[1].nr_components = 2;
325 c->vertex_elems[1].src_format = PIPE_FORMAT_R32G32_FLOAT;
326
327 /*
328 * Create our vertex shader's constant buffer
329 * Const buffer contains scaling and translation vectors
330 */
331 c->vs_const_buf.buffer = pipe_buffer_create
332 (
333 c->pipe->screen,
334 1,
335 PIPE_BUFFER_USAGE_CONSTANT | PIPE_BUFFER_USAGE_DISCARD,
336 sizeof(struct vertex_shader_consts)
337 );
338
339 /*
340 * Create our fragment shader's constant buffer
341 * Const buffer contains the color conversion matrix and bias vectors
342 */
343 c->fs_const_buf.buffer = pipe_buffer_create
344 (
345 c->pipe->screen,
346 1,
347 PIPE_BUFFER_USAGE_CONSTANT,
348 sizeof(struct fragment_shader_consts)
349 );
350
351 vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_IDENTITY, NULL, true, fsc.matrix);
352
353 vl_compositor_set_csc_matrix(c, fsc.matrix);
354
355 return true;
356 }
357
358 static void
359 cleanup_buffers(struct vl_compositor *c)
360 {
361 unsigned i;
362
363 assert(c);
364
365 for (i = 0; i < 2; ++i)
366 pipe_buffer_reference(&c->vertex_bufs[i].buffer, NULL);
367
368 pipe_buffer_reference(&c->vs_const_buf.buffer, NULL);
369 pipe_buffer_reference(&c->fs_const_buf.buffer, NULL);
370 }
371
372 bool vl_compositor_init(struct vl_compositor *compositor, struct pipe_context *pipe)
373 {
374 assert(compositor);
375
376 memset(compositor, 0, sizeof(struct vl_compositor));
377
378 compositor->pipe = pipe;
379
380 if (!init_pipe_state(compositor))
381 return false;
382 if (!init_shaders(compositor)) {
383 cleanup_pipe_state(compositor);
384 return false;
385 }
386 if (!init_buffers(compositor)) {
387 cleanup_shaders(compositor);
388 cleanup_pipe_state(compositor);
389 return false;
390 }
391
392 return true;
393 }
394
395 void vl_compositor_cleanup(struct vl_compositor *compositor)
396 {
397 assert(compositor);
398
399 cleanup_buffers(compositor);
400 cleanup_shaders(compositor);
401 cleanup_pipe_state(compositor);
402 }
403
404 void vl_compositor_render(struct vl_compositor *compositor,
405 /*struct pipe_texture *backround,
406 struct pipe_video_rect *backround_area,*/
407 struct pipe_texture *src_surface,
408 enum pipe_mpeg12_picture_type picture_type,
409 /*unsigned num_past_surfaces,
410 struct pipe_texture *past_surfaces,
411 unsigned num_future_surfaces,
412 struct pipe_texture *future_surfaces,*/
413 struct pipe_video_rect *src_area,
414 struct pipe_texture *dst_surface,
415 struct pipe_video_rect *dst_area,
416 /*unsigned num_layers,
417 struct pipe_texture *layers,
418 struct pipe_video_rect *layer_src_areas,
419 struct pipe_video_rect *layer_dst_areas*/
420 struct pipe_fence_handle **fence)
421 {
422 struct vertex_shader_consts *vs_consts;
423
424 assert(compositor);
425 assert(src_surface);
426 assert(src_area);
427 assert(dst_surface);
428 assert(dst_area);
429 assert(picture_type == PIPE_MPEG12_PICTURE_TYPE_FRAME);
430
431 compositor->fb_state.width = dst_surface->width[0];
432 compositor->fb_state.height = dst_surface->height[0];
433 compositor->fb_state.cbufs[0] = compositor->pipe->screen->get_tex_surface
434 (
435 compositor->pipe->screen,
436 dst_surface,
437 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE
438 );
439
440 compositor->viewport.scale[0] = compositor->fb_state.width;
441 compositor->viewport.scale[1] = compositor->fb_state.height;
442 compositor->viewport.scale[2] = 1;
443 compositor->viewport.scale[3] = 1;
444 compositor->viewport.translate[0] = 0;
445 compositor->viewport.translate[1] = 0;
446 compositor->viewport.translate[2] = 0;
447 compositor->viewport.translate[3] = 0;
448
449 compositor->pipe->set_framebuffer_state(compositor->pipe, &compositor->fb_state);
450 compositor->pipe->set_viewport_state(compositor->pipe, &compositor->viewport);
451 compositor->pipe->bind_sampler_states(compositor->pipe, 1, &compositor->sampler);
452 compositor->pipe->set_sampler_textures(compositor->pipe, 1, &src_surface);
453 compositor->pipe->bind_vs_state(compositor->pipe, compositor->vertex_shader);
454 compositor->pipe->bind_fs_state(compositor->pipe, compositor->fragment_shader);
455 compositor->pipe->set_vertex_buffers(compositor->pipe, 2, compositor->vertex_bufs);
456 compositor->pipe->set_vertex_elements(compositor->pipe, 2, compositor->vertex_elems);
457 compositor->pipe->set_constant_buffer(compositor->pipe, PIPE_SHADER_VERTEX, 0, &compositor->vs_const_buf);
458 compositor->pipe->set_constant_buffer(compositor->pipe, PIPE_SHADER_FRAGMENT, 0, &compositor->fs_const_buf);
459
460 vs_consts = pipe_buffer_map
461 (
462 compositor->pipe->screen,
463 compositor->vs_const_buf.buffer,
464 PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_DISCARD
465 );
466
467 vs_consts->dst_scale.x = dst_area->w / (float)compositor->fb_state.cbufs[0]->width;
468 vs_consts->dst_scale.y = dst_area->h / (float)compositor->fb_state.cbufs[0]->height;
469 vs_consts->dst_scale.z = 1;
470 vs_consts->dst_scale.w = 1;
471 vs_consts->dst_trans.x = dst_area->x / (float)compositor->fb_state.cbufs[0]->width;
472 vs_consts->dst_trans.y = dst_area->y / (float)compositor->fb_state.cbufs[0]->height;
473 vs_consts->dst_trans.z = 0;
474 vs_consts->dst_trans.w = 0;
475
476 vs_consts->src_scale.x = src_area->w / (float)src_surface->width[0];
477 vs_consts->src_scale.y = src_area->h / (float)src_surface->height[0];
478 vs_consts->src_scale.z = 1;
479 vs_consts->src_scale.w = 1;
480 vs_consts->src_trans.x = src_area->x / (float)src_surface->width[0];
481 vs_consts->src_trans.y = src_area->y / (float)src_surface->height[0];
482 vs_consts->src_trans.z = 0;
483 vs_consts->src_trans.w = 0;
484
485 pipe_buffer_unmap(compositor->pipe->screen, compositor->vs_const_buf.buffer);
486
487 compositor->pipe->draw_arrays(compositor->pipe, PIPE_PRIM_TRIANGLE_STRIP, 0, 4);
488 compositor->pipe->flush(compositor->pipe, PIPE_FLUSH_RENDER_CACHE, fence);
489
490 pipe_surface_reference(&compositor->fb_state.cbufs[0], NULL);
491 }
492
493 void vl_compositor_set_csc_matrix(struct vl_compositor *compositor, const float *mat)
494 {
495 assert(compositor);
496
497 memcpy
498 (
499 pipe_buffer_map(compositor->pipe->screen, compositor->fs_const_buf.buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
500 mat,
501 sizeof(struct fragment_shader_consts)
502 );
503
504 pipe_buffer_unmap(compositor->pipe->screen, compositor->fs_const_buf.buffer);
505 }