gallium: remove TGSI_OPCODE_SUB
[mesa.git] / src / gallium / auxiliary / vl / vl_compositor.c
1 /**************************************************************************
2 *
3 * Copyright 2009 Younes Manton.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #include <assert.h>
29
30 #include "pipe/p_compiler.h"
31 #include "pipe/p_context.h"
32
33 #include "util/u_memory.h"
34 #include "util/u_draw.h"
35 #include "util/u_surface.h"
36 #include "util/u_upload_mgr.h"
37
38 #include "tgsi/tgsi_ureg.h"
39
40 #include "vl_csc.h"
41 #include "vl_types.h"
42 #include "vl_compositor.h"
43
44 #define MIN_DIRTY (0)
45 #define MAX_DIRTY (1 << 15)
46
47 enum VS_OUTPUT
48 {
49 VS_O_VPOS = 0,
50 VS_O_COLOR = 0,
51 VS_O_VTEX = 0,
52 VS_O_VTOP,
53 VS_O_VBOTTOM,
54 };
55
56 static void *
57 create_vert_shader(struct vl_compositor *c)
58 {
59 struct ureg_program *shader;
60 struct ureg_src vpos, vtex, color;
61 struct ureg_dst tmp;
62 struct ureg_dst o_vpos, o_vtex, o_color;
63 struct ureg_dst o_vtop, o_vbottom;
64
65 shader = ureg_create(PIPE_SHADER_VERTEX);
66 if (!shader)
67 return false;
68
69 vpos = ureg_DECL_vs_input(shader, 0);
70 vtex = ureg_DECL_vs_input(shader, 1);
71 color = ureg_DECL_vs_input(shader, 2);
72 tmp = ureg_DECL_temporary(shader);
73 o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, VS_O_VPOS);
74 o_color = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, VS_O_COLOR);
75 o_vtex = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX);
76 o_vtop = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTOP);
77 o_vbottom = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VBOTTOM);
78
79 /*
80 * o_vpos = vpos
81 * o_vtex = vtex
82 * o_color = color
83 */
84 ureg_MOV(shader, o_vpos, vpos);
85 ureg_MOV(shader, o_vtex, vtex);
86 ureg_MOV(shader, o_color, color);
87
88 /*
89 * tmp.x = vtex.w / 2
90 * tmp.y = vtex.w / 4
91 *
92 * o_vtop.x = vtex.x
93 * o_vtop.y = vtex.y * tmp.x + 0.25f
94 * o_vtop.z = vtex.y * tmp.y + 0.25f
95 * o_vtop.w = 1 / tmp.x
96 *
97 * o_vbottom.x = vtex.x
98 * o_vbottom.y = vtex.y * tmp.x - 0.25f
99 * o_vbottom.z = vtex.y * tmp.y - 0.25f
100 * o_vbottom.w = 1 / tmp.y
101 */
102 ureg_MUL(shader, ureg_writemask(tmp, TGSI_WRITEMASK_X),
103 ureg_scalar(vtex, TGSI_SWIZZLE_W), ureg_imm1f(shader, 0.5f));
104 ureg_MUL(shader, ureg_writemask(tmp, TGSI_WRITEMASK_Y),
105 ureg_scalar(vtex, TGSI_SWIZZLE_W), ureg_imm1f(shader, 0.25f));
106
107 ureg_MOV(shader, ureg_writemask(o_vtop, TGSI_WRITEMASK_X), vtex);
108 ureg_MAD(shader, ureg_writemask(o_vtop, TGSI_WRITEMASK_Y), ureg_scalar(vtex, TGSI_SWIZZLE_Y),
109 ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X), ureg_imm1f(shader, 0.25f));
110 ureg_MAD(shader, ureg_writemask(o_vtop, TGSI_WRITEMASK_Z), ureg_scalar(vtex, TGSI_SWIZZLE_Y),
111 ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_Y), ureg_imm1f(shader, 0.25f));
112 ureg_RCP(shader, ureg_writemask(o_vtop, TGSI_WRITEMASK_W),
113 ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X));
114
115 ureg_MOV(shader, ureg_writemask(o_vbottom, TGSI_WRITEMASK_X), vtex);
116 ureg_MAD(shader, ureg_writemask(o_vbottom, TGSI_WRITEMASK_Y), ureg_scalar(vtex, TGSI_SWIZZLE_Y),
117 ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X), ureg_imm1f(shader, -0.25f));
118 ureg_MAD(shader, ureg_writemask(o_vbottom, TGSI_WRITEMASK_Z), ureg_scalar(vtex, TGSI_SWIZZLE_Y),
119 ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_Y), ureg_imm1f(shader, -0.25f));
120 ureg_RCP(shader, ureg_writemask(o_vbottom, TGSI_WRITEMASK_W),
121 ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_Y));
122
123 ureg_END(shader);
124
125 return ureg_create_shader_and_destroy(shader, c->pipe);
126 }
127
128 static void
129 create_frag_shader_weave(struct ureg_program *shader, struct ureg_dst fragment)
130 {
131 struct ureg_src i_tc[2];
132 struct ureg_src sampler[3];
133 struct ureg_dst t_tc[2];
134 struct ureg_dst t_texel[2];
135 unsigned i, j;
136
137 i_tc[0] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTOP, TGSI_INTERPOLATE_LINEAR);
138 i_tc[1] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VBOTTOM, TGSI_INTERPOLATE_LINEAR);
139
140 for (i = 0; i < 3; ++i)
141 sampler[i] = ureg_DECL_sampler(shader, i);
142
143 for (i = 0; i < 2; ++i) {
144 t_tc[i] = ureg_DECL_temporary(shader);
145 t_texel[i] = ureg_DECL_temporary(shader);
146 }
147
148 /* calculate the texture offsets
149 * t_tc.x = i_tc.x
150 * t_tc.y = (round(i_tc.y - 0.5) + 0.5) / height * 2
151 */
152 for (i = 0; i < 2; ++i) {
153 ureg_MOV(shader, ureg_writemask(t_tc[i], TGSI_WRITEMASK_X), i_tc[i]);
154 ureg_ADD(shader, ureg_writemask(t_tc[i], TGSI_WRITEMASK_YZ),
155 i_tc[i], ureg_imm1f(shader, -0.5f));
156 ureg_ROUND(shader, ureg_writemask(t_tc[i], TGSI_WRITEMASK_YZ), ureg_src(t_tc[i]));
157 ureg_MOV(shader, ureg_writemask(t_tc[i], TGSI_WRITEMASK_W),
158 ureg_imm1f(shader, i ? 1.0f : 0.0f));
159 ureg_ADD(shader, ureg_writemask(t_tc[i], TGSI_WRITEMASK_YZ),
160 ureg_src(t_tc[i]), ureg_imm1f(shader, 0.5f));
161 ureg_MUL(shader, ureg_writemask(t_tc[i], TGSI_WRITEMASK_Y),
162 ureg_src(t_tc[i]), ureg_scalar(i_tc[0], TGSI_SWIZZLE_W));
163 ureg_MUL(shader, ureg_writemask(t_tc[i], TGSI_WRITEMASK_Z),
164 ureg_src(t_tc[i]), ureg_scalar(i_tc[1], TGSI_SWIZZLE_W));
165 }
166
167 /* fetch the texels
168 * texel[0..1].x = tex(t_tc[0..1][0])
169 * texel[0..1].y = tex(t_tc[0..1][1])
170 * texel[0..1].z = tex(t_tc[0..1][2])
171 */
172 for (i = 0; i < 2; ++i)
173 for (j = 0; j < 3; ++j) {
174 struct ureg_src src = ureg_swizzle(ureg_src(t_tc[i]),
175 TGSI_SWIZZLE_X, j ? TGSI_SWIZZLE_Z : TGSI_SWIZZLE_Y, TGSI_SWIZZLE_W, TGSI_SWIZZLE_W);
176
177 ureg_TEX(shader, ureg_writemask(t_texel[i], TGSI_WRITEMASK_X << j),
178 TGSI_TEXTURE_2D_ARRAY, src, sampler[j]);
179 }
180
181 /* calculate linear interpolation factor
182 * factor = |round(i_tc.y) - i_tc.y| * 2
183 */
184 ureg_ROUND(shader, ureg_writemask(t_tc[0], TGSI_WRITEMASK_YZ), i_tc[0]);
185 ureg_ADD(shader, ureg_writemask(t_tc[0], TGSI_WRITEMASK_YZ),
186 ureg_src(t_tc[0]), ureg_negate(i_tc[0]));
187 ureg_MUL(shader, ureg_writemask(t_tc[0], TGSI_WRITEMASK_YZ),
188 ureg_abs(ureg_src(t_tc[0])), ureg_imm1f(shader, 2.0f));
189 ureg_LRP(shader, fragment, ureg_swizzle(ureg_src(t_tc[0]),
190 TGSI_SWIZZLE_Y, TGSI_SWIZZLE_Z, TGSI_SWIZZLE_Z, TGSI_SWIZZLE_Z),
191 ureg_src(t_texel[0]), ureg_src(t_texel[1]));
192
193 for (i = 0; i < 2; ++i) {
194 ureg_release_temporary(shader, t_texel[i]);
195 ureg_release_temporary(shader, t_tc[i]);
196 }
197 }
198
199 static void
200 create_frag_shader_csc(struct ureg_program *shader, struct ureg_dst texel,
201 struct ureg_dst fragment)
202 {
203 struct ureg_src csc[3];
204 struct ureg_src lumakey;
205 struct ureg_dst temp[2];
206 unsigned i;
207
208 for (i = 0; i < 3; ++i)
209 csc[i] = ureg_DECL_constant(shader, i);
210
211 lumakey = ureg_DECL_constant(shader, 3);
212
213 for (i = 0; i < 2; ++i)
214 temp[i] = ureg_DECL_temporary(shader);
215
216 ureg_MOV(shader, ureg_writemask(texel, TGSI_WRITEMASK_W),
217 ureg_imm1f(shader, 1.0f));
218
219 for (i = 0; i < 3; ++i)
220 ureg_DP4(shader, ureg_writemask(fragment, TGSI_WRITEMASK_X << i), csc[i],
221 ureg_src(texel));
222
223 ureg_MOV(shader, ureg_writemask(temp[0], TGSI_WRITEMASK_W),
224 ureg_scalar(ureg_src(texel), TGSI_SWIZZLE_Z));
225 ureg_SLE(shader, ureg_writemask(temp[1],TGSI_WRITEMASK_W),
226 ureg_src(temp[0]), ureg_scalar(lumakey, TGSI_SWIZZLE_X));
227 ureg_SGT(shader, ureg_writemask(temp[0],TGSI_WRITEMASK_W),
228 ureg_src(temp[0]), ureg_scalar(lumakey, TGSI_SWIZZLE_Y));
229 ureg_MAX(shader, ureg_writemask(fragment, TGSI_WRITEMASK_W),
230 ureg_src(temp[0]), ureg_src(temp[1]));
231
232 for (i = 0; i < 2; ++i)
233 ureg_release_temporary(shader, temp[i]);
234 }
235
236 static void *
237 create_frag_shader_video_buffer(struct vl_compositor *c)
238 {
239 struct ureg_program *shader;
240 struct ureg_src tc;
241 struct ureg_src sampler[3];
242 struct ureg_dst texel;
243 struct ureg_dst fragment;
244 unsigned i;
245
246 shader = ureg_create(PIPE_SHADER_FRAGMENT);
247 if (!shader)
248 return false;
249
250 tc = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX, TGSI_INTERPOLATE_LINEAR);
251 for (i = 0; i < 3; ++i)
252 sampler[i] = ureg_DECL_sampler(shader, i);
253
254 texel = ureg_DECL_temporary(shader);
255 fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
256
257 /*
258 * texel.xyz = tex(tc, sampler[i])
259 * fragment = csc * texel
260 */
261 for (i = 0; i < 3; ++i)
262 ureg_TEX(shader, ureg_writemask(texel, TGSI_WRITEMASK_X << i), TGSI_TEXTURE_2D_ARRAY, tc, sampler[i]);
263
264 create_frag_shader_csc(shader, texel, fragment);
265
266 ureg_release_temporary(shader, texel);
267 ureg_END(shader);
268
269 return ureg_create_shader_and_destroy(shader, c->pipe);
270 }
271
272 static void *
273 create_frag_shader_weave_rgb(struct vl_compositor *c)
274 {
275 struct ureg_program *shader;
276 struct ureg_dst texel, fragment;
277
278 shader = ureg_create(PIPE_SHADER_FRAGMENT);
279 if (!shader)
280 return false;
281
282 texel = ureg_DECL_temporary(shader);
283 fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
284
285 create_frag_shader_weave(shader, texel);
286 create_frag_shader_csc(shader, texel, fragment);
287
288 ureg_release_temporary(shader, texel);
289
290 ureg_END(shader);
291
292 return ureg_create_shader_and_destroy(shader, c->pipe);
293 }
294
295 static void *
296 create_frag_shader_weave_yuv(struct vl_compositor *c, bool y)
297 {
298 struct ureg_program *shader;
299 struct ureg_dst texel, fragment;
300
301 shader = ureg_create(PIPE_SHADER_FRAGMENT);
302 if (!shader)
303 return false;
304
305 texel = ureg_DECL_temporary(shader);
306 fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
307
308 create_frag_shader_weave(shader, texel);
309
310 if (y)
311 ureg_MOV(shader, ureg_writemask(fragment, TGSI_WRITEMASK_X), ureg_src(texel));
312 else
313 ureg_MOV(shader, ureg_writemask(fragment, TGSI_WRITEMASK_XY),
314 ureg_swizzle(ureg_src(texel), TGSI_SWIZZLE_Y,
315 TGSI_SWIZZLE_Z, TGSI_SWIZZLE_W, TGSI_SWIZZLE_W));
316
317 ureg_release_temporary(shader, texel);
318
319 ureg_END(shader);
320
321 return ureg_create_shader_and_destroy(shader, c->pipe);
322 }
323
324 static void *
325 create_frag_shader_palette(struct vl_compositor *c, bool include_cc)
326 {
327 struct ureg_program *shader;
328 struct ureg_src csc[3];
329 struct ureg_src tc;
330 struct ureg_src sampler;
331 struct ureg_src palette;
332 struct ureg_dst texel;
333 struct ureg_dst fragment;
334 unsigned i;
335
336 shader = ureg_create(PIPE_SHADER_FRAGMENT);
337 if (!shader)
338 return false;
339
340 for (i = 0; include_cc && i < 3; ++i)
341 csc[i] = ureg_DECL_constant(shader, i);
342
343 tc = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX, TGSI_INTERPOLATE_LINEAR);
344 sampler = ureg_DECL_sampler(shader, 0);
345 palette = ureg_DECL_sampler(shader, 1);
346
347 texel = ureg_DECL_temporary(shader);
348 fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
349
350 /*
351 * texel = tex(tc, sampler)
352 * fragment.xyz = tex(texel, palette) * csc
353 * fragment.a = texel.a
354 */
355 ureg_TEX(shader, texel, TGSI_TEXTURE_2D, tc, sampler);
356 ureg_MOV(shader, ureg_writemask(fragment, TGSI_WRITEMASK_W), ureg_src(texel));
357
358 if (include_cc) {
359 ureg_TEX(shader, texel, TGSI_TEXTURE_1D, ureg_src(texel), palette);
360 for (i = 0; i < 3; ++i)
361 ureg_DP4(shader, ureg_writemask(fragment, TGSI_WRITEMASK_X << i), csc[i], ureg_src(texel));
362 } else {
363 ureg_TEX(shader, ureg_writemask(fragment, TGSI_WRITEMASK_XYZ),
364 TGSI_TEXTURE_1D, ureg_src(texel), palette);
365 }
366
367 ureg_release_temporary(shader, texel);
368 ureg_END(shader);
369
370 return ureg_create_shader_and_destroy(shader, c->pipe);
371 }
372
373 static void *
374 create_frag_shader_rgba(struct vl_compositor *c)
375 {
376 struct ureg_program *shader;
377 struct ureg_src tc, color, sampler;
378 struct ureg_dst texel, fragment;
379
380 shader = ureg_create(PIPE_SHADER_FRAGMENT);
381 if (!shader)
382 return false;
383
384 tc = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX, TGSI_INTERPOLATE_LINEAR);
385 color = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_COLOR, VS_O_COLOR, TGSI_INTERPOLATE_LINEAR);
386 sampler = ureg_DECL_sampler(shader, 0);
387 texel = ureg_DECL_temporary(shader);
388 fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
389
390 /*
391 * fragment = tex(tc, sampler)
392 */
393 ureg_TEX(shader, texel, TGSI_TEXTURE_2D, tc, sampler);
394 ureg_MUL(shader, fragment, ureg_src(texel), color);
395 ureg_END(shader);
396
397 return ureg_create_shader_and_destroy(shader, c->pipe);
398 }
399
400 static bool
401 init_shaders(struct vl_compositor *c)
402 {
403 assert(c);
404
405 c->vs = create_vert_shader(c);
406 if (!c->vs) {
407 debug_printf("Unable to create vertex shader.\n");
408 return false;
409 }
410
411 c->fs_video_buffer = create_frag_shader_video_buffer(c);
412 if (!c->fs_video_buffer) {
413 debug_printf("Unable to create YCbCr-to-RGB fragment shader.\n");
414 return false;
415 }
416
417 c->fs_weave_rgb = create_frag_shader_weave_rgb(c);
418 if (!c->fs_weave_rgb) {
419 debug_printf("Unable to create YCbCr-to-RGB weave fragment shader.\n");
420 return false;
421 }
422
423 c->fs_weave_yuv.y = create_frag_shader_weave_yuv(c, true);
424 c->fs_weave_yuv.uv = create_frag_shader_weave_yuv(c, false);
425 if (!c->fs_weave_yuv.y || !c->fs_weave_yuv.uv) {
426 debug_printf("Unable to create YCbCr i-to-YCbCr p weave fragment shader.\n");
427 return false;
428 }
429
430 c->fs_palette.yuv = create_frag_shader_palette(c, true);
431 if (!c->fs_palette.yuv) {
432 debug_printf("Unable to create YUV-Palette-to-RGB fragment shader.\n");
433 return false;
434 }
435
436 c->fs_palette.rgb = create_frag_shader_palette(c, false);
437 if (!c->fs_palette.rgb) {
438 debug_printf("Unable to create RGB-Palette-to-RGB fragment shader.\n");
439 return false;
440 }
441
442 c->fs_rgba = create_frag_shader_rgba(c);
443 if (!c->fs_rgba) {
444 debug_printf("Unable to create RGB-to-RGB fragment shader.\n");
445 return false;
446 }
447
448 return true;
449 }
450
451 static void cleanup_shaders(struct vl_compositor *c)
452 {
453 assert(c);
454
455 c->pipe->delete_vs_state(c->pipe, c->vs);
456 c->pipe->delete_fs_state(c->pipe, c->fs_video_buffer);
457 c->pipe->delete_fs_state(c->pipe, c->fs_weave_rgb);
458 c->pipe->delete_fs_state(c->pipe, c->fs_weave_yuv.y);
459 c->pipe->delete_fs_state(c->pipe, c->fs_weave_yuv.uv);
460 c->pipe->delete_fs_state(c->pipe, c->fs_palette.yuv);
461 c->pipe->delete_fs_state(c->pipe, c->fs_palette.rgb);
462 c->pipe->delete_fs_state(c->pipe, c->fs_rgba);
463 }
464
465 static bool
466 init_pipe_state(struct vl_compositor *c)
467 {
468 struct pipe_rasterizer_state rast;
469 struct pipe_sampler_state sampler;
470 struct pipe_blend_state blend;
471 struct pipe_depth_stencil_alpha_state dsa;
472 unsigned i;
473
474 assert(c);
475
476 c->fb_state.nr_cbufs = 1;
477 c->fb_state.zsbuf = NULL;
478
479 memset(&sampler, 0, sizeof(sampler));
480 sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
481 sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
482 sampler.wrap_r = PIPE_TEX_WRAP_REPEAT;
483 sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR;
484 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
485 sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
486 sampler.compare_mode = PIPE_TEX_COMPARE_NONE;
487 sampler.compare_func = PIPE_FUNC_ALWAYS;
488 sampler.normalized_coords = 1;
489
490 c->sampler_linear = c->pipe->create_sampler_state(c->pipe, &sampler);
491
492 sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
493 sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
494 c->sampler_nearest = c->pipe->create_sampler_state(c->pipe, &sampler);
495
496 memset(&blend, 0, sizeof blend);
497 blend.independent_blend_enable = 0;
498 blend.rt[0].blend_enable = 0;
499 blend.logicop_enable = 0;
500 blend.logicop_func = PIPE_LOGICOP_CLEAR;
501 blend.rt[0].colormask = PIPE_MASK_RGBA;
502 blend.dither = 0;
503 c->blend_clear = c->pipe->create_blend_state(c->pipe, &blend);
504
505 blend.rt[0].blend_enable = 1;
506 blend.rt[0].rgb_func = PIPE_BLEND_ADD;
507 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
508 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
509 blend.rt[0].alpha_func = PIPE_BLEND_ADD;
510 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
511 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
512 c->blend_add = c->pipe->create_blend_state(c->pipe, &blend);
513
514 memset(&rast, 0, sizeof rast);
515 rast.flatshade = 0;
516 rast.front_ccw = 1;
517 rast.cull_face = PIPE_FACE_NONE;
518 rast.fill_back = PIPE_POLYGON_MODE_FILL;
519 rast.fill_front = PIPE_POLYGON_MODE_FILL;
520 rast.scissor = 1;
521 rast.line_width = 1;
522 rast.point_size_per_vertex = 1;
523 rast.offset_units = 1;
524 rast.offset_scale = 1;
525 rast.half_pixel_center = 1;
526 rast.bottom_edge_rule = 1;
527 rast.depth_clip = 1;
528
529 c->rast = c->pipe->create_rasterizer_state(c->pipe, &rast);
530
531 memset(&dsa, 0, sizeof dsa);
532 dsa.depth.enabled = 0;
533 dsa.depth.writemask = 0;
534 dsa.depth.func = PIPE_FUNC_ALWAYS;
535 for (i = 0; i < 2; ++i) {
536 dsa.stencil[i].enabled = 0;
537 dsa.stencil[i].func = PIPE_FUNC_ALWAYS;
538 dsa.stencil[i].fail_op = PIPE_STENCIL_OP_KEEP;
539 dsa.stencil[i].zpass_op = PIPE_STENCIL_OP_KEEP;
540 dsa.stencil[i].zfail_op = PIPE_STENCIL_OP_KEEP;
541 dsa.stencil[i].valuemask = 0;
542 dsa.stencil[i].writemask = 0;
543 }
544 dsa.alpha.enabled = 0;
545 dsa.alpha.func = PIPE_FUNC_ALWAYS;
546 dsa.alpha.ref_value = 0;
547 c->dsa = c->pipe->create_depth_stencil_alpha_state(c->pipe, &dsa);
548 c->pipe->bind_depth_stencil_alpha_state(c->pipe, c->dsa);
549
550 return true;
551 }
552
553 static void cleanup_pipe_state(struct vl_compositor *c)
554 {
555 assert(c);
556
557 /* Asserted in softpipe_delete_fs_state() for some reason */
558 c->pipe->bind_vs_state(c->pipe, NULL);
559 c->pipe->bind_fs_state(c->pipe, NULL);
560
561 c->pipe->delete_depth_stencil_alpha_state(c->pipe, c->dsa);
562 c->pipe->delete_sampler_state(c->pipe, c->sampler_linear);
563 c->pipe->delete_sampler_state(c->pipe, c->sampler_nearest);
564 c->pipe->delete_blend_state(c->pipe, c->blend_clear);
565 c->pipe->delete_blend_state(c->pipe, c->blend_add);
566 c->pipe->delete_rasterizer_state(c->pipe, c->rast);
567 }
568
569 static bool
570 init_buffers(struct vl_compositor *c)
571 {
572 struct pipe_vertex_element vertex_elems[3];
573
574 assert(c);
575
576 /*
577 * Create our vertex buffer and vertex buffer elements
578 */
579 c->vertex_buf.stride = sizeof(struct vertex2f) + sizeof(struct vertex4f) * 2;
580 c->vertex_buf.buffer_offset = 0;
581 c->vertex_buf.buffer = NULL;
582
583 vertex_elems[0].src_offset = 0;
584 vertex_elems[0].instance_divisor = 0;
585 vertex_elems[0].vertex_buffer_index = 0;
586 vertex_elems[0].src_format = PIPE_FORMAT_R32G32_FLOAT;
587 vertex_elems[1].src_offset = sizeof(struct vertex2f);
588 vertex_elems[1].instance_divisor = 0;
589 vertex_elems[1].vertex_buffer_index = 0;
590 vertex_elems[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
591 vertex_elems[2].src_offset = sizeof(struct vertex2f) + sizeof(struct vertex4f);
592 vertex_elems[2].instance_divisor = 0;
593 vertex_elems[2].vertex_buffer_index = 0;
594 vertex_elems[2].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
595 c->vertex_elems_state = c->pipe->create_vertex_elements_state(c->pipe, 3, vertex_elems);
596
597 return true;
598 }
599
600 static void
601 cleanup_buffers(struct vl_compositor *c)
602 {
603 assert(c);
604
605 c->pipe->delete_vertex_elements_state(c->pipe, c->vertex_elems_state);
606 pipe_resource_reference(&c->vertex_buf.buffer, NULL);
607 }
608
609 static inline struct u_rect
610 default_rect(struct vl_compositor_layer *layer)
611 {
612 struct pipe_resource *res = layer->sampler_views[0]->texture;
613 struct u_rect rect = { 0, res->width0, 0, res->height0 * res->array_size };
614 return rect;
615 }
616
617 static inline struct vertex2f
618 calc_topleft(struct vertex2f size, struct u_rect rect)
619 {
620 struct vertex2f res = { rect.x0 / size.x, rect.y0 / size.y };
621 return res;
622 }
623
624 static inline struct vertex2f
625 calc_bottomright(struct vertex2f size, struct u_rect rect)
626 {
627 struct vertex2f res = { rect.x1 / size.x, rect.y1 / size.y };
628 return res;
629 }
630
631 static inline void
632 calc_src_and_dst(struct vl_compositor_layer *layer, unsigned width, unsigned height,
633 struct u_rect src, struct u_rect dst)
634 {
635 struct vertex2f size = { width, height };
636
637 layer->src.tl = calc_topleft(size, src);
638 layer->src.br = calc_bottomright(size, src);
639 layer->dst.tl = calc_topleft(size, dst);
640 layer->dst.br = calc_bottomright(size, dst);
641 layer->zw.x = 0.0f;
642 layer->zw.y = size.y;
643 }
644
645 static void
646 gen_rect_verts(struct vertex2f *vb, struct vl_compositor_layer *layer)
647 {
648 struct vertex2f tl, tr, br, bl;
649
650 assert(vb && layer);
651
652 switch (layer->rotate) {
653 default:
654 case VL_COMPOSITOR_ROTATE_0:
655 tl = layer->dst.tl;
656 tr.x = layer->dst.br.x;
657 tr.y = layer->dst.tl.y;
658 br = layer->dst.br;
659 bl.x = layer->dst.tl.x;
660 bl.y = layer->dst.br.y;
661 break;
662 case VL_COMPOSITOR_ROTATE_90:
663 tl.x = layer->dst.br.x;
664 tl.y = layer->dst.tl.y;
665 tr = layer->dst.br;
666 br.x = layer->dst.tl.x;
667 br.y = layer->dst.br.y;
668 bl = layer->dst.tl;
669 break;
670 case VL_COMPOSITOR_ROTATE_180:
671 tl = layer->dst.br;
672 tr.x = layer->dst.tl.x;
673 tr.y = layer->dst.br.y;
674 br = layer->dst.tl;
675 bl.x = layer->dst.br.x;
676 bl.y = layer->dst.tl.y;
677 break;
678 case VL_COMPOSITOR_ROTATE_270:
679 tl.x = layer->dst.tl.x;
680 tl.y = layer->dst.br.y;
681 tr = layer->dst.tl;
682 br.x = layer->dst.br.x;
683 br.y = layer->dst.tl.y;
684 bl = layer->dst.br;
685 break;
686 }
687
688 vb[ 0].x = tl.x;
689 vb[ 0].y = tl.y;
690 vb[ 1].x = layer->src.tl.x;
691 vb[ 1].y = layer->src.tl.y;
692 vb[ 2] = layer->zw;
693 vb[ 3].x = layer->colors[0].x;
694 vb[ 3].y = layer->colors[0].y;
695 vb[ 4].x = layer->colors[0].z;
696 vb[ 4].y = layer->colors[0].w;
697
698 vb[ 5].x = tr.x;
699 vb[ 5].y = tr.y;
700 vb[ 6].x = layer->src.br.x;
701 vb[ 6].y = layer->src.tl.y;
702 vb[ 7] = layer->zw;
703 vb[ 8].x = layer->colors[1].x;
704 vb[ 8].y = layer->colors[1].y;
705 vb[ 9].x = layer->colors[1].z;
706 vb[ 9].y = layer->colors[1].w;
707
708 vb[10].x = br.x;
709 vb[10].y = br.y;
710 vb[11].x = layer->src.br.x;
711 vb[11].y = layer->src.br.y;
712 vb[12] = layer->zw;
713 vb[13].x = layer->colors[2].x;
714 vb[13].y = layer->colors[2].y;
715 vb[14].x = layer->colors[2].z;
716 vb[14].y = layer->colors[2].w;
717
718 vb[15].x = bl.x;
719 vb[15].y = bl.y;
720 vb[16].x = layer->src.tl.x;
721 vb[16].y = layer->src.br.y;
722 vb[17] = layer->zw;
723 vb[18].x = layer->colors[3].x;
724 vb[18].y = layer->colors[3].y;
725 vb[19].x = layer->colors[3].z;
726 vb[19].y = layer->colors[3].w;
727 }
728
729 static inline struct u_rect
730 calc_drawn_area(struct vl_compositor_state *s, struct vl_compositor_layer *layer)
731 {
732 struct vertex2f tl, br;
733 struct u_rect result;
734
735 assert(s && layer);
736
737 // rotate
738 switch (layer->rotate) {
739 default:
740 case VL_COMPOSITOR_ROTATE_0:
741 tl = layer->dst.tl;
742 br = layer->dst.br;
743 break;
744 case VL_COMPOSITOR_ROTATE_90:
745 tl.x = layer->dst.br.x;
746 tl.y = layer->dst.tl.y;
747 br.x = layer->dst.tl.x;
748 br.y = layer->dst.br.y;
749 break;
750 case VL_COMPOSITOR_ROTATE_180:
751 tl = layer->dst.br;
752 br = layer->dst.tl;
753 break;
754 case VL_COMPOSITOR_ROTATE_270:
755 tl.x = layer->dst.tl.x;
756 tl.y = layer->dst.br.y;
757 br.x = layer->dst.br.x;
758 br.y = layer->dst.tl.y;
759 break;
760 }
761
762 // scale
763 result.x0 = tl.x * layer->viewport.scale[0] + layer->viewport.translate[0];
764 result.y0 = tl.y * layer->viewport.scale[1] + layer->viewport.translate[1];
765 result.x1 = br.x * layer->viewport.scale[0] + layer->viewport.translate[0];
766 result.y1 = br.y * layer->viewport.scale[1] + layer->viewport.translate[1];
767
768 // and clip
769 result.x0 = MAX2(result.x0, s->scissor.minx);
770 result.y0 = MAX2(result.y0, s->scissor.miny);
771 result.x1 = MIN2(result.x1, s->scissor.maxx);
772 result.y1 = MIN2(result.y1, s->scissor.maxy);
773 return result;
774 }
775
776 static void
777 gen_vertex_data(struct vl_compositor *c, struct vl_compositor_state *s, struct u_rect *dirty)
778 {
779 struct vertex2f *vb;
780 unsigned i;
781
782 assert(c);
783
784 /* Allocate new memory for vertices. */
785 u_upload_alloc(c->upload, 0,
786 c->vertex_buf.stride * VL_COMPOSITOR_MAX_LAYERS * 4, /* size */
787 4, /* alignment */
788 &c->vertex_buf.buffer_offset, &c->vertex_buf.buffer,
789 (void**)&vb);
790
791 for (i = 0; i < VL_COMPOSITOR_MAX_LAYERS; i++) {
792 if (s->used_layers & (1 << i)) {
793 struct vl_compositor_layer *layer = &s->layers[i];
794 gen_rect_verts(vb, layer);
795 vb += 20;
796
797 if (!layer->viewport_valid) {
798 layer->viewport.scale[0] = c->fb_state.width;
799 layer->viewport.scale[1] = c->fb_state.height;
800 layer->viewport.translate[0] = 0;
801 layer->viewport.translate[1] = 0;
802 }
803
804 if (dirty && layer->clearing) {
805 struct u_rect drawn = calc_drawn_area(s, layer);
806 if (
807 dirty->x0 >= drawn.x0 &&
808 dirty->y0 >= drawn.y0 &&
809 dirty->x1 <= drawn.x1 &&
810 dirty->y1 <= drawn.y1) {
811
812 // We clear the dirty area anyway, no need for clear_render_target
813 dirty->x0 = dirty->y0 = MAX_DIRTY;
814 dirty->x1 = dirty->y1 = MIN_DIRTY;
815 }
816 }
817 }
818 }
819
820 u_upload_unmap(c->upload);
821 }
822
823 static void
824 draw_layers(struct vl_compositor *c, struct vl_compositor_state *s, struct u_rect *dirty)
825 {
826 unsigned vb_index, i;
827
828 assert(c);
829
830 for (i = 0, vb_index = 0; i < VL_COMPOSITOR_MAX_LAYERS; ++i) {
831 if (s->used_layers & (1 << i)) {
832 struct vl_compositor_layer *layer = &s->layers[i];
833 struct pipe_sampler_view **samplers = &layer->sampler_views[0];
834 unsigned num_sampler_views = !samplers[1] ? 1 : !samplers[2] ? 2 : 3;
835 void *blend = layer->blend ? layer->blend : i ? c->blend_add : c->blend_clear;
836
837 c->pipe->bind_blend_state(c->pipe, blend);
838 c->pipe->set_viewport_states(c->pipe, 0, 1, &layer->viewport);
839 c->pipe->bind_fs_state(c->pipe, layer->fs);
840 c->pipe->bind_sampler_states(c->pipe, PIPE_SHADER_FRAGMENT, 0,
841 num_sampler_views, layer->samplers);
842 c->pipe->set_sampler_views(c->pipe, PIPE_SHADER_FRAGMENT, 0,
843 num_sampler_views, samplers);
844
845 util_draw_arrays(c->pipe, PIPE_PRIM_QUADS, vb_index * 4, 4);
846 vb_index++;
847
848 if (dirty) {
849 // Remember the currently drawn area as dirty for the next draw command
850 struct u_rect drawn = calc_drawn_area(s, layer);
851 dirty->x0 = MIN2(drawn.x0, dirty->x0);
852 dirty->y0 = MIN2(drawn.y0, dirty->y0);
853 dirty->x1 = MAX2(drawn.x1, dirty->x1);
854 dirty->y1 = MAX2(drawn.y1, dirty->y1);
855 }
856 }
857 }
858 }
859
860 void
861 vl_compositor_reset_dirty_area(struct u_rect *dirty)
862 {
863 assert(dirty);
864
865 dirty->x0 = dirty->y0 = MIN_DIRTY;
866 dirty->x1 = dirty->y1 = MAX_DIRTY;
867 }
868
869 void
870 vl_compositor_set_clear_color(struct vl_compositor_state *s, union pipe_color_union *color)
871 {
872 assert(s);
873 assert(color);
874
875 s->clear_color = *color;
876 }
877
878 void
879 vl_compositor_get_clear_color(struct vl_compositor_state *s, union pipe_color_union *color)
880 {
881 assert(s);
882 assert(color);
883
884 *color = s->clear_color;
885 }
886
887 void
888 vl_compositor_clear_layers(struct vl_compositor_state *s)
889 {
890 unsigned i, j;
891
892 assert(s);
893
894 s->used_layers = 0;
895 for ( i = 0; i < VL_COMPOSITOR_MAX_LAYERS; ++i) {
896 struct vertex4f v_one = { 1.0f, 1.0f, 1.0f, 1.0f };
897 s->layers[i].clearing = i ? false : true;
898 s->layers[i].blend = NULL;
899 s->layers[i].fs = NULL;
900 s->layers[i].viewport.scale[2] = 1;
901 s->layers[i].viewport.translate[2] = 0;
902 s->layers[i].rotate = VL_COMPOSITOR_ROTATE_0;
903
904 for ( j = 0; j < 3; j++)
905 pipe_sampler_view_reference(&s->layers[i].sampler_views[j], NULL);
906 for ( j = 0; j < 4; ++j)
907 s->layers[i].colors[j] = v_one;
908 }
909 }
910
911 void
912 vl_compositor_cleanup(struct vl_compositor *c)
913 {
914 assert(c);
915
916 u_upload_destroy(c->upload);
917 cleanup_buffers(c);
918 cleanup_shaders(c);
919 cleanup_pipe_state(c);
920 }
921
922 bool
923 vl_compositor_set_csc_matrix(struct vl_compositor_state *s,
924 vl_csc_matrix const *matrix,
925 float luma_min, float luma_max)
926 {
927 struct pipe_transfer *buf_transfer;
928
929 assert(s);
930
931 float *ptr = pipe_buffer_map(s->pipe, s->csc_matrix,
932 PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE,
933 &buf_transfer);
934
935 if (!ptr)
936 return false;
937
938 memcpy(ptr, matrix, sizeof(vl_csc_matrix));
939
940 ptr += sizeof(vl_csc_matrix)/sizeof(float);
941 ptr[0] = luma_min;
942 ptr[1] = luma_max;
943
944 pipe_buffer_unmap(s->pipe, buf_transfer);
945
946 return true;
947 }
948
949 void
950 vl_compositor_set_dst_clip(struct vl_compositor_state *s, struct u_rect *dst_clip)
951 {
952 assert(s);
953
954 s->scissor_valid = dst_clip != NULL;
955 if (dst_clip) {
956 s->scissor.minx = dst_clip->x0;
957 s->scissor.miny = dst_clip->y0;
958 s->scissor.maxx = dst_clip->x1;
959 s->scissor.maxy = dst_clip->y1;
960 }
961 }
962
963 void
964 vl_compositor_set_layer_blend(struct vl_compositor_state *s,
965 unsigned layer, void *blend,
966 bool is_clearing)
967 {
968 assert(s && blend);
969
970 assert(layer < VL_COMPOSITOR_MAX_LAYERS);
971
972 s->layers[layer].clearing = is_clearing;
973 s->layers[layer].blend = blend;
974 }
975
976 void
977 vl_compositor_set_layer_dst_area(struct vl_compositor_state *s,
978 unsigned layer, struct u_rect *dst_area)
979 {
980 assert(s);
981
982 assert(layer < VL_COMPOSITOR_MAX_LAYERS);
983
984 s->layers[layer].viewport_valid = dst_area != NULL;
985 if (dst_area) {
986 s->layers[layer].viewport.scale[0] = dst_area->x1 - dst_area->x0;
987 s->layers[layer].viewport.scale[1] = dst_area->y1 - dst_area->y0;
988 s->layers[layer].viewport.translate[0] = dst_area->x0;
989 s->layers[layer].viewport.translate[1] = dst_area->y0;
990 }
991 }
992
993 void
994 vl_compositor_set_buffer_layer(struct vl_compositor_state *s,
995 struct vl_compositor *c,
996 unsigned layer,
997 struct pipe_video_buffer *buffer,
998 struct u_rect *src_rect,
999 struct u_rect *dst_rect,
1000 enum vl_compositor_deinterlace deinterlace)
1001 {
1002 struct pipe_sampler_view **sampler_views;
1003 unsigned i;
1004
1005 assert(s && c && buffer);
1006
1007 assert(layer < VL_COMPOSITOR_MAX_LAYERS);
1008
1009 s->used_layers |= 1 << layer;
1010 sampler_views = buffer->get_sampler_view_components(buffer);
1011 for (i = 0; i < 3; ++i) {
1012 s->layers[layer].samplers[i] = c->sampler_linear;
1013 pipe_sampler_view_reference(&s->layers[layer].sampler_views[i], sampler_views[i]);
1014 }
1015
1016 calc_src_and_dst(&s->layers[layer], buffer->width, buffer->height,
1017 src_rect ? *src_rect : default_rect(&s->layers[layer]),
1018 dst_rect ? *dst_rect : default_rect(&s->layers[layer]));
1019
1020 if (buffer->interlaced) {
1021 float half_a_line = 0.5f / s->layers[layer].zw.y;
1022 switch(deinterlace) {
1023 case VL_COMPOSITOR_WEAVE:
1024 s->layers[layer].fs = c->fs_weave_rgb;
1025 break;
1026
1027 case VL_COMPOSITOR_BOB_TOP:
1028 s->layers[layer].zw.x = 0.0f;
1029 s->layers[layer].src.tl.y += half_a_line;
1030 s->layers[layer].src.br.y += half_a_line;
1031 s->layers[layer].fs = c->fs_video_buffer;
1032 break;
1033
1034 case VL_COMPOSITOR_BOB_BOTTOM:
1035 s->layers[layer].zw.x = 1.0f;
1036 s->layers[layer].src.tl.y -= half_a_line;
1037 s->layers[layer].src.br.y -= half_a_line;
1038 s->layers[layer].fs = c->fs_video_buffer;
1039 break;
1040 }
1041
1042 } else
1043 s->layers[layer].fs = c->fs_video_buffer;
1044 }
1045
1046 void
1047 vl_compositor_set_palette_layer(struct vl_compositor_state *s,
1048 struct vl_compositor *c,
1049 unsigned layer,
1050 struct pipe_sampler_view *indexes,
1051 struct pipe_sampler_view *palette,
1052 struct u_rect *src_rect,
1053 struct u_rect *dst_rect,
1054 bool include_color_conversion)
1055 {
1056 assert(s && c && indexes && palette);
1057
1058 assert(layer < VL_COMPOSITOR_MAX_LAYERS);
1059
1060 s->used_layers |= 1 << layer;
1061
1062 s->layers[layer].fs = include_color_conversion ?
1063 c->fs_palette.yuv : c->fs_palette.rgb;
1064
1065 s->layers[layer].samplers[0] = c->sampler_linear;
1066 s->layers[layer].samplers[1] = c->sampler_nearest;
1067 s->layers[layer].samplers[2] = NULL;
1068 pipe_sampler_view_reference(&s->layers[layer].sampler_views[0], indexes);
1069 pipe_sampler_view_reference(&s->layers[layer].sampler_views[1], palette);
1070 pipe_sampler_view_reference(&s->layers[layer].sampler_views[2], NULL);
1071 calc_src_and_dst(&s->layers[layer], indexes->texture->width0, indexes->texture->height0,
1072 src_rect ? *src_rect : default_rect(&s->layers[layer]),
1073 dst_rect ? *dst_rect : default_rect(&s->layers[layer]));
1074 }
1075
1076 void
1077 vl_compositor_set_rgba_layer(struct vl_compositor_state *s,
1078 struct vl_compositor *c,
1079 unsigned layer,
1080 struct pipe_sampler_view *rgba,
1081 struct u_rect *src_rect,
1082 struct u_rect *dst_rect,
1083 struct vertex4f *colors)
1084 {
1085 unsigned i;
1086
1087 assert(s && c && rgba);
1088
1089 assert(layer < VL_COMPOSITOR_MAX_LAYERS);
1090
1091 s->used_layers |= 1 << layer;
1092 s->layers[layer].fs = c->fs_rgba;
1093 s->layers[layer].samplers[0] = c->sampler_linear;
1094 s->layers[layer].samplers[1] = NULL;
1095 s->layers[layer].samplers[2] = NULL;
1096 pipe_sampler_view_reference(&s->layers[layer].sampler_views[0], rgba);
1097 pipe_sampler_view_reference(&s->layers[layer].sampler_views[1], NULL);
1098 pipe_sampler_view_reference(&s->layers[layer].sampler_views[2], NULL);
1099 calc_src_and_dst(&s->layers[layer], rgba->texture->width0, rgba->texture->height0,
1100 src_rect ? *src_rect : default_rect(&s->layers[layer]),
1101 dst_rect ? *dst_rect : default_rect(&s->layers[layer]));
1102
1103 if (colors)
1104 for (i = 0; i < 4; ++i)
1105 s->layers[layer].colors[i] = colors[i];
1106 }
1107
1108 void
1109 vl_compositor_set_layer_rotation(struct vl_compositor_state *s,
1110 unsigned layer,
1111 enum vl_compositor_rotation rotate)
1112 {
1113 assert(s);
1114 assert(layer < VL_COMPOSITOR_MAX_LAYERS);
1115 s->layers[layer].rotate = rotate;
1116 }
1117
1118 void
1119 vl_compositor_set_yuv_layer(struct vl_compositor_state *s,
1120 struct vl_compositor *c,
1121 unsigned layer,
1122 struct pipe_video_buffer *buffer,
1123 struct u_rect *src_rect,
1124 struct u_rect *dst_rect,
1125 bool y)
1126 {
1127 struct pipe_sampler_view **sampler_views;
1128 unsigned i;
1129
1130 assert(s && c && buffer);
1131
1132 assert(layer < VL_COMPOSITOR_MAX_LAYERS);
1133
1134 s->used_layers |= 1 << layer;
1135 sampler_views = buffer->get_sampler_view_components(buffer);
1136 for (i = 0; i < 3; ++i) {
1137 s->layers[layer].samplers[i] = c->sampler_linear;
1138 pipe_sampler_view_reference(&s->layers[layer].sampler_views[i], sampler_views[i]);
1139 }
1140
1141 calc_src_and_dst(&s->layers[layer], buffer->width, buffer->height,
1142 src_rect ? *src_rect : default_rect(&s->layers[layer]),
1143 dst_rect ? *dst_rect : default_rect(&s->layers[layer]));
1144
1145 s->layers[layer].fs = (y) ? c->fs_weave_yuv.y : c->fs_weave_yuv.uv;
1146 }
1147
1148 void
1149 vl_compositor_render(struct vl_compositor_state *s,
1150 struct vl_compositor *c,
1151 struct pipe_surface *dst_surface,
1152 struct u_rect *dirty_area,
1153 bool clear_dirty)
1154 {
1155 assert(c);
1156 assert(dst_surface);
1157
1158 c->fb_state.width = dst_surface->width;
1159 c->fb_state.height = dst_surface->height;
1160 c->fb_state.cbufs[0] = dst_surface;
1161
1162 if (!s->scissor_valid) {
1163 s->scissor.minx = 0;
1164 s->scissor.miny = 0;
1165 s->scissor.maxx = dst_surface->width;
1166 s->scissor.maxy = dst_surface->height;
1167 }
1168 c->pipe->set_scissor_states(c->pipe, 0, 1, &s->scissor);
1169
1170 gen_vertex_data(c, s, dirty_area);
1171
1172 if (clear_dirty && dirty_area &&
1173 (dirty_area->x0 < dirty_area->x1 || dirty_area->y0 < dirty_area->y1)) {
1174
1175 c->pipe->clear_render_target(c->pipe, dst_surface, &s->clear_color,
1176 0, 0, dst_surface->width, dst_surface->height, false);
1177 dirty_area->x0 = dirty_area->y0 = MAX_DIRTY;
1178 dirty_area->x1 = dirty_area->y1 = MIN_DIRTY;
1179 }
1180
1181 c->pipe->set_framebuffer_state(c->pipe, &c->fb_state);
1182 c->pipe->bind_vs_state(c->pipe, c->vs);
1183 c->pipe->set_vertex_buffers(c->pipe, 0, 1, &c->vertex_buf);
1184 c->pipe->bind_vertex_elements_state(c->pipe, c->vertex_elems_state);
1185 pipe_set_constant_buffer(c->pipe, PIPE_SHADER_FRAGMENT, 0, s->csc_matrix);
1186 c->pipe->bind_rasterizer_state(c->pipe, c->rast);
1187
1188 draw_layers(c, s, dirty_area);
1189 }
1190
1191 bool
1192 vl_compositor_init(struct vl_compositor *c, struct pipe_context *pipe)
1193 {
1194 assert(c);
1195
1196 memset(c, 0, sizeof(*c));
1197
1198 c->pipe = pipe;
1199
1200 c->upload = u_upload_create(pipe, 128 * 1024, PIPE_BIND_VERTEX_BUFFER,
1201 PIPE_USAGE_STREAM);
1202
1203 if (!c->upload)
1204 return false;
1205
1206 if (!init_pipe_state(c)) {
1207 u_upload_destroy(c->upload);
1208 return false;
1209 }
1210
1211 if (!init_shaders(c)) {
1212 u_upload_destroy(c->upload);
1213 cleanup_pipe_state(c);
1214 return false;
1215 }
1216
1217 if (!init_buffers(c)) {
1218 u_upload_destroy(c->upload);
1219 cleanup_shaders(c);
1220 cleanup_pipe_state(c);
1221 return false;
1222 }
1223
1224 return true;
1225 }
1226
1227 bool
1228 vl_compositor_init_state(struct vl_compositor_state *s, struct pipe_context *pipe)
1229 {
1230 vl_csc_matrix csc_matrix;
1231
1232 assert(s);
1233
1234 memset(s, 0, sizeof(*s));
1235
1236 s->pipe = pipe;
1237
1238 s->clear_color.f[0] = s->clear_color.f[1] = 0.0f;
1239 s->clear_color.f[2] = s->clear_color.f[3] = 0.0f;
1240
1241 /*
1242 * Create our fragment shader's constant buffer
1243 * Const buffer contains the color conversion matrix and bias vectors
1244 */
1245 /* XXX: Create with IMMUTABLE/STATIC... although it does change every once in a long while... */
1246 s->csc_matrix = pipe_buffer_create
1247 (
1248 pipe->screen,
1249 PIPE_BIND_CONSTANT_BUFFER,
1250 PIPE_USAGE_DEFAULT,
1251 sizeof(csc_matrix) + 2*sizeof(float)
1252 );
1253
1254 if (!s->csc_matrix)
1255 return false;
1256
1257 vl_compositor_clear_layers(s);
1258
1259 vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_IDENTITY, NULL, true, &csc_matrix);
1260 if (!vl_compositor_set_csc_matrix(s, (const vl_csc_matrix *)&csc_matrix, 1.0f, 0.0f))
1261 return false;
1262
1263 return true;
1264 }
1265
1266 void
1267 vl_compositor_cleanup_state(struct vl_compositor_state *s)
1268 {
1269 assert(s);
1270
1271 vl_compositor_clear_layers(s);
1272 pipe_resource_reference(&s->csc_matrix, NULL);
1273 }