1 /**************************************************************************
3 * Copyright 2009 Younes Manton.
4 * Copyright 2011 Maarten Lankhorst
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sub license, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
15 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial portions
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
23 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 **************************************************************************/
31 #include "pipe/p_compiler.h"
32 #include "pipe/p_context.h"
34 #include "util/u_memory.h"
35 #include "util/u_draw.h"
36 #include "util/u_surface.h"
37 #include "util/u_sampler.h"
39 #include "tgsi/tgsi_ureg.h"
43 #include "vl_compositor.h"
45 typedef float csc_matrix
[16];
47 /* Set to 1 to run a contour shader for interpolation */
48 #define DEBUG_CONTOUR 1
50 /* Set to 1 to make all non-interpolated data in the contour shader black */
51 #define DEBUG_CONTOUR_CHROMA 0
53 static const float vl_contour_luma_threshold
= .1f
;
55 /* Set to non-zero half-pixel units for finding what would be affected by bicubic resizing */
56 #define DEBUG_BICUBIC 0
58 /* There's no point in using bicubic, it's not a good interpolation method for video when downscaling
59 * and for upscaling it's completely pointless until you get to a magnification of 4x or so
64 create_vert_shader(struct vl_compositor
*c
)
66 struct ureg_program
*shader
;
67 struct ureg_src vpos
, vtex
;
68 struct ureg_dst o_vpos
, o_vtex
;
70 shader
= ureg_create(TGSI_PROCESSOR_VERTEX
);
74 vpos
= ureg_DECL_vs_input(shader
, 0);
75 vtex
= ureg_DECL_vs_input(shader
, 1);
76 o_vpos
= ureg_DECL_output(shader
, TGSI_SEMANTIC_POSITION
, 0);
77 o_vtex
= ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, 1);
83 ureg_MOV(shader
, o_vpos
, vpos
);
84 ureg_MOV(shader
, o_vtex
, vtex
);
88 return ureg_create_shader_and_destroy(shader
, c
->pipe
);
91 static struct ureg_dst
92 calc_line(struct ureg_program
*shader
, struct ureg_src pos
, unsigned nearest
)
96 tmp
= ureg_DECL_temporary(shader
);
99 * tmp.y = fraction(pos.y * .5) >= 0.5 ? 1 : 0
100 * however, for linear interpolation (chroma deinterlace) 2 pixels are required..
103 ureg_MUL(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_Y
), pos
, ureg_imm1f(shader
, 0.5f
));
105 ureg_MUL(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_Y
), pos
, ureg_imm1f(shader
, 0.25f
));
106 ureg_FRC(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_Y
), ureg_src(tmp
));
107 ureg_SGE(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_Y
), ureg_src(tmp
), ureg_imm1f(shader
, 0.5f
));
113 create_frag_shader_video_buffer(struct vl_compositor
*c
)
115 struct ureg_program
*shader
;
117 struct ureg_src csc
[3];
118 struct ureg_src sampler
[3];
119 struct ureg_dst texel
;
120 struct ureg_dst fragment
;
123 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
127 tc
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, 1, TGSI_INTERPOLATE_LINEAR
);
128 for (i
= 0; i
< 3; ++i
) {
129 csc
[i
] = ureg_DECL_constant(shader
, i
);
130 sampler
[i
] = ureg_DECL_sampler(shader
, i
);
132 texel
= ureg_DECL_temporary(shader
);
133 fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
136 * texel.xyz = tex(tc, sampler[i])
137 * fragment = csc * texel
139 for (i
= 0; i
< 3; ++i
)
140 ureg_TEX(shader
, ureg_writemask(texel
, TGSI_WRITEMASK_X
<< i
), TGSI_TEXTURE_2D
, tc
, sampler
[i
]);
141 ureg_MOV(shader
, ureg_writemask(texel
, TGSI_WRITEMASK_W
), ureg_imm1f(shader
, 1.0f
));
143 for (i
= 0; i
< 3; ++i
)
144 ureg_DP4(shader
, ureg_writemask(fragment
, TGSI_WRITEMASK_X
<< i
), csc
[i
], ureg_src(texel
));
146 ureg_MOV(shader
, ureg_writemask(fragment
, TGSI_WRITEMASK_W
), ureg_imm1f(shader
, 1.0f
));
148 ureg_release_temporary(shader
, texel
);
151 return ureg_create_shader_and_destroy(shader
, c
->pipe
);
155 create_frag_shader_sobel_video(struct vl_compositor
*c
)
157 struct ureg_program
*shader
;
159 struct ureg_src csc
[3];
160 struct ureg_src sampler
[5], invsize
, size
;
161 struct ureg_dst texel
, tmp
, fragment
;
164 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
168 tc
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, 1, TGSI_INTERPOLATE_LINEAR
);
169 for (i
= 0; i
< 3; ++i
) {
170 csc
[i
] = ureg_DECL_constant(shader
, i
);
171 sampler
[i
] = ureg_DECL_sampler(shader
, i
);
174 sampler
[i
] = ureg_DECL_sampler(shader
, i
);
175 size
= ureg_DECL_constant(shader
, 4);
176 invsize
= ureg_DECL_constant(shader
, 5);
178 texel
= ureg_DECL_temporary(shader
);
179 tmp
= ureg_DECL_temporary(shader
);
180 fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
182 ureg_TEX(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_X
), TGSI_TEXTURE_2D
, tc
, sampler
[3]);
183 ureg_SLE(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_Y
), ureg_scalar(ureg_src(tmp
), TGSI_SWIZZLE_X
), ureg_imm1f(shader
, 1.f
));
184 ureg_SGE(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_X
), ureg_src(tmp
), ureg_imm1f(shader
, vl_contour_luma_threshold
));
185 ureg_IF(shader
, ureg_swizzle(ureg_src(tmp
), TGSI_SWIZZLE_X
, TGSI_SWIZZLE_Y
, TGSI_SWIZZLE_Y
, TGSI_SWIZZLE_Y
), &label
);
187 ureg_MUL(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_XY
), tc
,
188 ureg_swizzle(size
, TGSI_SWIZZLE_Z
, TGSI_SWIZZLE_W
, TGSI_SWIZZLE_W
, TGSI_SWIZZLE_W
));
189 ureg_MUL(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_XY
), ureg_src(tmp
), ureg_imm2f(shader
, .5f
, .5f
));
190 ureg_FRC(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_XY
), ureg_src(tmp
));
191 ureg_SGE(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_XY
), ureg_src(tmp
), ureg_imm2f(shader
, .5f
, .5f
));
192 ureg_SUB(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_XY
), ureg_src(tmp
), ureg_imm2f(shader
, .5f
, .5f
));
193 // tmp.xy = -.5 for even x / y, .5 for odd x / y, this is then multiplied
194 // by absolute gradient previously calculated in the second sobel shader
195 // for the chroma offset
197 ureg_TEX(shader
, texel
, TGSI_TEXTURE_2D
, tc
, sampler
[4]);
198 ureg_MUL(shader
, tmp
, ureg_src(texel
),
199 ureg_swizzle(ureg_src(tmp
), TGSI_SWIZZLE_X
, TGSI_SWIZZLE_Y
, TGSI_SWIZZLE_X
, TGSI_SWIZZLE_Y
));
201 ureg_MAD(shader
, tmp
, ureg_src(tmp
),
202 ureg_swizzle(invsize
, TGSI_SWIZZLE_Z
, TGSI_SWIZZLE_W
, TGSI_SWIZZLE_Z
, TGSI_SWIZZLE_W
),
203 ureg_swizzle(tc
, TGSI_SWIZZLE_X
, TGSI_SWIZZLE_Y
, TGSI_SWIZZLE_X
, TGSI_SWIZZLE_Y
));
205 ureg_TEX(shader
, ureg_writemask(texel
, TGSI_WRITEMASK_X
), TGSI_TEXTURE_2D
, tc
, sampler
[0]);
206 ureg_TEX(shader
, ureg_writemask(texel
, TGSI_WRITEMASK_Y
), TGSI_TEXTURE_2D
, ureg_src(tmp
), sampler
[1]);
207 ureg_TEX(shader
, ureg_writemask(texel
, TGSI_WRITEMASK_Z
), TGSI_TEXTURE_2D
,
208 ureg_swizzle(ureg_src(tmp
), TGSI_SWIZZLE_Z
, TGSI_SWIZZLE_W
, TGSI_SWIZZLE_W
, TGSI_SWIZZLE_W
), sampler
[2]);
210 // ureg_MOV(shader, ureg_writemask(texel, TGSI_WRITEMASK_X), ureg_imm3f(shader, 0.f, .5f, .5f));
211 ureg_fixup_label(shader
, label
, ureg_get_instruction_number(shader
));
213 ureg_ELSE(shader
, &label
);
215 ureg_TEX(shader
, ureg_writemask(texel
, TGSI_WRITEMASK_X
), TGSI_TEXTURE_2D
, tc
, sampler
[0]);
216 ureg_TEX(shader
, ureg_writemask(texel
, TGSI_WRITEMASK_Y
), TGSI_TEXTURE_2D
, tc
, sampler
[1]);
217 ureg_TEX(shader
, ureg_writemask(texel
, TGSI_WRITEMASK_Z
), TGSI_TEXTURE_2D
, tc
, sampler
[2]);
218 if (DEBUG_CONTOUR_CHROMA
)
219 ureg_MOV(shader
, ureg_writemask(texel
, TGSI_WRITEMASK_XYZ
), ureg_imm3f(shader
, 0.f
, .5f
, .5f
));
220 ureg_fixup_label(shader
, label
, ureg_get_instruction_number(shader
));
223 ureg_release_temporary(shader
, tmp
);
225 ureg_MOV(shader
, ureg_writemask(texel
, TGSI_WRITEMASK_W
), ureg_imm1f(shader
, 1.0f
));
227 for (i
= 0; i
< 3; ++i
)
228 ureg_DP4(shader
, ureg_writemask(fragment
, TGSI_WRITEMASK_X
<< i
), csc
[i
], ureg_src(texel
));
230 ureg_MOV(shader
, ureg_writemask(fragment
, TGSI_WRITEMASK_W
), ureg_imm1f(shader
, 1.0f
));
232 ureg_release_temporary(shader
, texel
);
235 return ureg_create_shader_and_destroy(shader
, c
->pipe
);
239 /* Deinterlace or weave NV12 or YV12 to a temporary video buffer
243 create_frag_shader_weave(struct vl_compositor
*c
, unsigned luma
, unsigned interlaced
)
245 struct ureg_program
*shader
;
246 struct ureg_src pos
, tc
, sampler
[4];
247 struct ureg_dst field
, fragment
, swizcolor
;
248 unsigned label
, writemask
, nearest
;
251 writemask
= TGSI_WRITEMASK_X
;
253 writemask
= TGSI_WRITEMASK_Y
;
255 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
259 pos
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_POSITION
, 0, TGSI_INTERPOLATE_LINEAR
);
260 tc
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, 1, TGSI_INTERPOLATE_LINEAR
);
261 fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
262 sampler
[0] = ureg_DECL_sampler(shader
, 0);
263 sampler
[1] = ureg_DECL_sampler(shader
, 1);
265 sampler
[2] = ureg_DECL_sampler(shader
, 2);
266 sampler
[3] = ureg_DECL_sampler(shader
, 3);
269 nearest
= luma
|| c
->chroma
!= PIPE_VIDEO_CHROMA_FORMAT_420
|| !interlaced
;
270 field
= calc_line(shader
, pos
, nearest
);
271 swizcolor
= ureg_DECL_temporary(shader
);
273 /* field.y = fraction(coord/2) < . 5
276 * swiz = sampler[top];
278 * swiz = sampler[bottom];
283 * color.xy = swiz.yz;
286 ureg_IF(shader
, ureg_scalar(ureg_src(field
), TGSI_SWIZZLE_Y
), &label
);
288 struct ureg_dst adjtc
= ureg_DECL_temporary(shader
);
290 /* -2.0 / c->video_h (1 pixel up, chroma = half height, full height wouldn't need this)
291 * + .5 / c->video_h (.25 pixel down, since interlaced first pixel = .75 first
293 ureg_MOV(shader
, ureg_writemask(adjtc
, TGSI_WRITEMASK_X
), tc
);
294 ureg_SUB(shader
, ureg_writemask(adjtc
, TGSI_WRITEMASK_Y
), ureg_scalar(tc
, TGSI_SWIZZLE_Y
),
295 ureg_imm1f(shader
, 1.5f
/ c
->video_h
));
297 ureg_MOV(shader
, ureg_writemask(adjtc
, TGSI_WRITEMASK_XY
), tc
);
298 ureg_TEX(shader
, ureg_writemask(swizcolor
, writemask
), TGSI_TEXTURE_2D
, ureg_src(adjtc
), sampler
[1]);
300 ureg_TEX(shader
, ureg_writemask(swizcolor
, TGSI_WRITEMASK_Z
), TGSI_TEXTURE_2D
, ureg_src(adjtc
), sampler
[3]);
301 ureg_release_temporary(shader
, adjtc
);
302 ureg_fixup_label(shader
, label
, ureg_get_instruction_number(shader
));
304 ureg_ELSE(shader
, &label
);
306 struct ureg_dst adjtc
= ureg_DECL_temporary(shader
);
308 ureg_MOV(shader
, ureg_writemask(adjtc
, TGSI_WRITEMASK_X
), tc
);
309 ureg_ADD(shader
, ureg_writemask(adjtc
, TGSI_WRITEMASK_Y
), ureg_scalar(tc
, TGSI_SWIZZLE_Y
),
310 ureg_imm1f(shader
, .5f
/ c
->video_h
));
312 ureg_MOV(shader
, ureg_writemask(adjtc
, TGSI_WRITEMASK_XY
), tc
);
313 ureg_TEX(shader
, ureg_writemask(swizcolor
, writemask
), TGSI_TEXTURE_2D
, ureg_src(adjtc
), sampler
[0]);
315 ureg_TEX(shader
, ureg_writemask(swizcolor
, TGSI_WRITEMASK_Z
), TGSI_TEXTURE_2D
, ureg_src(adjtc
), sampler
[2]);
316 ureg_release_temporary(shader
, adjtc
);
317 ureg_fixup_label(shader
, label
, ureg_get_instruction_number(shader
));
322 ureg_MOV(shader
, ureg_writemask(fragment
, writemask
), ureg_src(swizcolor
));
324 ureg_MOV(shader
, ureg_writemask(fragment
, TGSI_WRITEMASK_XY
),
325 ureg_swizzle(ureg_src(swizcolor
), TGSI_SWIZZLE_Y
, TGSI_SWIZZLE_Z
, TGSI_SWIZZLE_Z
, TGSI_SWIZZLE_Z
));
327 ureg_release_temporary(shader
, swizcolor
);
328 ureg_release_temporary(shader
, field
);
330 return ureg_create_shader_and_destroy(shader
, c
->pipe
);
334 create_frag_shader_bicubic(struct vl_compositor
*c
) {
335 struct ureg_src sampler
[3], lookup
, cst
, size
, tc
, csc
[4];
336 struct ureg_dst fragment
, tmp
, hg_x
, hg_y
, color
, coord
[2][2], tex
[2][2];
339 struct ureg_program
*shader
;
340 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
344 ureg_property_fs_coord_pixel_center(shader
, TGSI_FS_COORD_PIXEL_CENTER_INTEGER
);
345 tc
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, 1, TGSI_INTERPOLATE_LINEAR
);
346 for (i
= 0; i
< 3; ++i
)
347 csc
[i
] = ureg_DECL_constant(shader
, i
);
348 size
= ureg_DECL_constant(shader
, 4);
349 cst
= ureg_DECL_constant(shader
, 5);
351 fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
352 for (i
= 0; i
< 3; ++i
)
353 sampler
[i
] = ureg_DECL_sampler(shader
, i
);
354 lookup
= ureg_DECL_sampler(shader
, 3);
356 tmp
= ureg_DECL_temporary(shader
);
357 hg_x
= ureg_DECL_temporary(shader
);
358 hg_y
= ureg_DECL_temporary(shader
);
359 color
= ureg_DECL_temporary(shader
);
361 for (i
= 0; i
< 4; ++i
) {
362 coord
[i
/2][i
%2] = ureg_DECL_temporary(shader
);
363 tex
[i
/2][i
%2] = ureg_DECL_temporary(shader
);
366 for (j
= 0; j
< 3; ++j
) {
367 unsigned writemask
, p
= j
>= 1;
368 writemask
= TGSI_WRITEMASK_X
<< j
;
370 if (j
== 0 || (j
== 1 && c
->chroma
!= PIPE_VIDEO_CHROMA_FORMAT_444
)) {
371 /* tmp.xy = tc * size[p].xy
372 * hg_x.xyz = tex1D(lookup, tmp.x);
373 * hg_y.xyz = tex1D(lookup, tmp.y);
375 ureg_MUL(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_XY
),
376 tc
, ureg_swizzle(size
, 2 * p
, 2 * p
+ 1, 2 * p
+ 1, 2 * p
+ 1));
377 ureg_FRC(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_XY
), ureg_src(tmp
));
378 ureg_TEX(shader
, ureg_writemask(hg_x
, TGSI_WRITEMASK_XYZ
),
379 TGSI_TEXTURE_1D
, ureg_scalar(ureg_src(tmp
), TGSI_SWIZZLE_X
), lookup
);
380 ureg_TEX(shader
, ureg_writemask(hg_y
, TGSI_WRITEMASK_XYZ
),
381 TGSI_TEXTURE_1D
, ureg_scalar(ureg_src(tmp
), TGSI_SWIZZLE_Y
), lookup
);
383 #define e_x(x, p) ureg_scalar(x, 2 * p)
384 #define e_y(x, p) ureg_scalar(x, 2 * p + 1)
386 /* coord1X.x += hg_x.x * cst[p].x;
387 * coord0X.x -= hg_x.y * cst[p].x;
389 * coord11.y += hg_y.x * cst[p].w
390 * coord01.y += hg_y.x * cst[p].w
392 * coord10.y -= hg_y.y * cst[p].w
393 * coord00.y -= hg_y.y * cst[p].w
396 ureg_MAD(shader
, ureg_writemask(coord
[1][0], TGSI_WRITEMASK_X
),
397 ureg_scalar(ureg_src(hg_x
), TGSI_SWIZZLE_X
),
399 ureg_MAD(shader
, ureg_writemask(coord
[0][0], TGSI_WRITEMASK_X
),
400 ureg_negate(ureg_scalar(ureg_src(hg_x
), TGSI_SWIZZLE_Y
)),
403 for (i
= 0; i
< 2; ++i
)
404 ureg_MOV(shader
, ureg_writemask(coord
[i
][1], TGSI_WRITEMASK_X
), ureg_src(coord
[i
][0]));
405 ureg_MAD(shader
, ureg_writemask(coord
[1][1], TGSI_WRITEMASK_Y
),
406 ureg_scalar(ureg_src(hg_y
), TGSI_SWIZZLE_X
),
408 ureg_MAD(shader
, ureg_writemask(coord
[0][1], TGSI_WRITEMASK_Y
),
409 ureg_scalar(ureg_src(hg_y
), TGSI_SWIZZLE_X
),
412 ureg_MAD(shader
, ureg_writemask(coord
[1][0], TGSI_WRITEMASK_Y
),
413 ureg_negate(ureg_scalar(ureg_src(hg_y
), TGSI_SWIZZLE_Y
)),
415 ureg_MAD(shader
, ureg_writemask(coord
[0][0], TGSI_WRITEMASK_Y
),
416 ureg_negate(ureg_scalar(ureg_src(hg_y
), TGSI_SWIZZLE_Y
)),
423 for (i
= 0; i
< 4; ++i
) {
424 ureg_TEX(shader
, ureg_writemask(tex
[i
/2][i
%2], writemask
),
425 TGSI_TEXTURE_2D
, ureg_src(coord
[i
/2][i
%2]), sampler
[j
]);
428 for (i
= 0; i
< 2; ++i
)
429 ureg_LRP(shader
, ureg_writemask(tex
[i
][0], writemask
),
430 ureg_scalar(ureg_src(hg_y
), TGSI_SWIZZLE_Z
),
431 ureg_src(tex
[i
][0]), ureg_src(tex
[i
][1]));
433 ureg_LRP(shader
, ureg_writemask(color
, writemask
),
434 ureg_scalar(ureg_src(hg_x
), TGSI_SWIZZLE_Z
),
435 ureg_src(tex
[0][0]), ureg_src(tex
[1][0]));
438 for (i
= 3; i
>= 0; --i
) {
439 ureg_release_temporary(shader
, tex
[i
/2][i
%2]);
440 ureg_release_temporary(shader
, coord
[i
/2][i
%2]);
442 ureg_release_temporary(shader
, hg_y
);
443 ureg_release_temporary(shader
, hg_x
);
444 ureg_release_temporary(shader
, tmp
);
446 ureg_MOV(shader
, ureg_writemask(color
, TGSI_WRITEMASK_W
), ureg_imm1f(shader
, 1.0f
));
449 struct ureg_dst lincolor
= ureg_DECL_temporary(shader
);
451 float val
= ((float)DEBUG_BICUBIC
) / 512.f
;
452 ureg_TEX(shader
, ureg_writemask(lincolor
, TGSI_WRITEMASK_X
), TGSI_TEXTURE_2D
, tc
, sampler
[0]);
453 ureg_TEX(shader
, ureg_writemask(lincolor
, TGSI_WRITEMASK_Y
),
454 TGSI_TEXTURE_2D
, tc
, sampler
[1]);
455 ureg_TEX(shader
, ureg_writemask(lincolor
, TGSI_WRITEMASK_Z
),
456 TGSI_TEXTURE_2D
, tc
, sampler
[2]);
457 /* lincolor.xyz = tex2D(...);
458 * lincolor.xyz = |color - lincolor|
459 * lincolor.xyz = lincolor >= DEBUG_BICUBIC / 512.f
461 * color.xyz = { 1.f, .5f, .5f }
464 ureg_SUB(shader
, ureg_writemask(lincolor
, TGSI_WRITEMASK_XYZ
), ureg_src(color
), ureg_src(lincolor
));
465 ureg_ABS(shader
, ureg_writemask(lincolor
, TGSI_WRITEMASK_XYZ
), ureg_src(lincolor
));
466 ureg_SGE(shader
, ureg_writemask(lincolor
, TGSI_WRITEMASK_XYZ
), ureg_src(lincolor
), ureg_imm3f(shader
, val
, val
, val
));
467 ureg_IF(shader
, ureg_swizzle(ureg_src(lincolor
), TGSI_SWIZZLE_X
, TGSI_SWIZZLE_Y
, TGSI_SWIZZLE_W
, TGSI_SWIZZLE_Z
), &label
);
468 ureg_MOV(shader
, ureg_writemask(color
, TGSI_WRITEMASK_XYZ
), ureg_imm3f(shader
, 1.f
, .5f
, .5f
));
469 ureg_fixup_label(shader
, label
, ureg_get_instruction_number(shader
));
471 ureg_release_temporary(shader
, lincolor
);
474 for (i
= 0; i
< 3; ++i
)
475 ureg_DP4(shader
, ureg_writemask(fragment
, TGSI_WRITEMASK_X
<< i
), csc
[i
], ureg_src(color
));
476 ureg_MOV(shader
, ureg_writemask(fragment
, TGSI_WRITEMASK_W
), ureg_imm1f(shader
, 1.0f
));
478 ureg_release_temporary(shader
, color
);
481 return ureg_create_shader_and_destroy(shader
, c
->pipe
);
485 create_frag_shader_sobel(struct vl_compositor
*c
, unsigned planes
)
487 struct ureg_program
*shader
;
488 struct ureg_src tc
, sampler
[3];
489 struct ureg_dst fragment
, color
[4], tctmp
, ly
, lx
;
490 float v
[2] = { -.5f
, .5f
}, wmul
= 1.f
, hmul
= 1.f
;
492 unsigned label
, writemask
= TGSI_WRITEMASK_X
;
494 if (c
->chroma
!= PIPE_VIDEO_CHROMA_FORMAT_444
)
496 if (c
->chroma
== PIPE_VIDEO_CHROMA_FORMAT_420
)
498 writemask
= TGSI_WRITEMASK_YZ
;
501 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
505 tc
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, 1, TGSI_INTERPOLATE_LINEAR
);
506 fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
507 tctmp
= ureg_DECL_temporary(shader
);
509 sampler
[0] = ureg_DECL_sampler(shader
, 0);
511 for (i
= 1; i
< planes
; ++i
)
512 sampler
[i
] = ureg_DECL_sampler(shader
, i
);
514 ureg_TEX(shader
, ureg_writemask(tctmp
, TGSI_WRITEMASK_X
), TGSI_TEXTURE_2D
, tc
, sampler
[0]);
515 ureg_SGE(shader
, ureg_writemask(tctmp
, TGSI_WRITEMASK_X
), ureg_src(tctmp
), ureg_imm1f(shader
, vl_contour_luma_threshold
));
516 ureg_IF(shader
, ureg_scalar(ureg_src(tctmp
), TGSI_SWIZZLE_X
), &label
);
519 lx
= ureg_DECL_temporary(shader
);
520 ly
= ureg_DECL_temporary(shader
);
521 for (i
= 0; i
< Elements(color
); ++i
)
522 color
[i
] = ureg_DECL_temporary(shader
);
524 /* Sobel, calculate textures for Ly, each point is sampling 4 others */
525 /* Weighting matrix in y direction (roughly):
529 * 4 divided by 2 weightings => multiply by 2
531 for (i
= 0; i
< 4; ++i
) {
532 ureg_ADD(shader
, ureg_writemask(tctmp
, TGSI_WRITEMASK_XY
), tc
, ureg_imm2f(shader
, .5 * wmul
* v
[i
%2]/(float)c
->video_w
, hmul
* 2.25f
* v
[i
/2]/(float)c
->video_h
));
534 ureg_TEX(shader
, ureg_writemask(color
[i
], writemask
), TGSI_TEXTURE_2D
, ureg_src(tctmp
), sampler
[!!planes
]);
536 ureg_TEX(shader
, ureg_writemask(color
[i
], TGSI_WRITEMASK_Y
), TGSI_TEXTURE_2D
, ureg_src(tctmp
), sampler
[1]);
537 ureg_TEX(shader
, ureg_writemask(color
[i
], TGSI_WRITEMASK_Z
), TGSI_TEXTURE_2D
, ureg_src(tctmp
), sampler
[2]);
541 /* Ly.xyz = wtop - wbottom */
542 ureg_ADD(shader
, ureg_writemask(color
[0], writemask
), ureg_src(color
[0]), ureg_src(color
[1]));
543 ureg_ADD(shader
, ureg_writemask(color
[1], writemask
), ureg_src(color
[2]), ureg_src(color
[3]));
544 ureg_SUB(shader
, ureg_writemask(ly
, writemask
), ureg_src(color
[0]), ureg_src(color
[1]));
546 for (i
= 0; i
< 4; ++i
) {
547 ureg_ADD(shader
, ureg_writemask(tctmp
, TGSI_WRITEMASK_XY
), tc
, ureg_imm2f(shader
, wmul
* 2.25f
* v
[i
/2]/(float)c
->video_w
, .5 * hmul
* v
[i
%2]/(float)c
->video_h
));
549 ureg_TEX(shader
, ureg_writemask(color
[i
], writemask
), TGSI_TEXTURE_2D
, ureg_src(tctmp
), sampler
[!!planes
]);
551 ureg_TEX(shader
, ureg_writemask(color
[i
], TGSI_WRITEMASK_Y
), TGSI_TEXTURE_2D
, ureg_src(tctmp
), sampler
[1]);
552 ureg_TEX(shader
, ureg_writemask(color
[i
], TGSI_WRITEMASK_Z
), TGSI_TEXTURE_2D
, ureg_src(tctmp
), sampler
[2]);
556 ureg_ADD(shader
, ureg_writemask(color
[0], writemask
), ureg_src(color
[0]), ureg_src(color
[1]));
557 ureg_ADD(shader
, ureg_writemask(color
[1], writemask
), ureg_src(color
[2]), ureg_src(color
[3]));
558 ureg_SUB(shader
, ureg_writemask(lx
, writemask
), ureg_src(color
[0]), ureg_src(color
[1]));
559 /* Lx.xyz = wleft - wright */
562 /* tmp.xyz = |Lx|**2 + |Ly|**2 */
563 ureg_MUL(shader
, ureg_writemask(tctmp
, writemask
), ureg_src(lx
), ureg_src(lx
));
564 ureg_MAD(shader
, ureg_writemask(tctmp
, writemask
), ureg_src(ly
), ureg_src(ly
), ureg_src(tctmp
));
565 ureg_MUL(shader
, ureg_writemask(fragment
, writemask
), ureg_src(tctmp
), ureg_imm1f(shader
, 2.f
));
567 static const float s
= 2.f
;
568 ureg_ABS(shader
, ureg_writemask(lx
, writemask
), ureg_src(lx
));
569 ureg_ABS(shader
, ureg_writemask(ly
, writemask
), ureg_src(ly
));
570 ureg_MUL(shader
, ureg_writemask(fragment
, TGSI_WRITEMASK_XZ
),
571 ureg_swizzle(ureg_src(lx
), TGSI_SWIZZLE_Y
, TGSI_SWIZZLE_Y
, TGSI_SWIZZLE_Z
, TGSI_SWIZZLE_Z
),
572 ureg_imm4f(shader
, s
, s
, s
, s
));
573 ureg_MUL(shader
, ureg_writemask(fragment
, TGSI_WRITEMASK_YW
),
574 ureg_swizzle(ureg_src(ly
), TGSI_SWIZZLE_Y
, TGSI_SWIZZLE_Y
, TGSI_SWIZZLE_Z
, TGSI_SWIZZLE_Z
),
575 ureg_imm4f(shader
, s
, s
, s
, s
));
578 for (i
= 0; i
< Elements(color
); ++i
)
579 ureg_release_temporary(shader
, color
[i
]);
580 ureg_release_temporary(shader
, ly
);
581 ureg_release_temporary(shader
, lx
);
584 ureg_fixup_label(shader
, label
, ureg_get_instruction_number(shader
));
585 ureg_ELSE(shader
, &label
);
586 ureg_MOV(shader
, fragment
, ureg_imm4f(shader
, 0.f
, 0.f
, 0.f
, 0.f
));
587 ureg_fixup_label(shader
, label
, ureg_get_instruction_number(shader
));
590 ureg_release_temporary(shader
, tctmp
);
592 return ureg_create_shader_and_destroy(shader
, c
->pipe
);
596 create_frag_shader_palette(struct vl_compositor
*c
, bool include_cc
)
598 struct ureg_program
*shader
;
599 struct ureg_src csc
[3];
601 struct ureg_src sampler
;
602 struct ureg_src palette
;
603 struct ureg_dst texel
;
604 struct ureg_dst fragment
;
607 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
611 for (i
= 0; include_cc
&& i
< 3; ++i
)
612 csc
[i
] = ureg_DECL_constant(shader
, i
);
614 tc
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, 1, TGSI_INTERPOLATE_LINEAR
);
615 sampler
= ureg_DECL_sampler(shader
, 0);
616 palette
= ureg_DECL_sampler(shader
, 1);
618 texel
= ureg_DECL_temporary(shader
);
619 fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
622 * texel = tex(tc, sampler)
623 * fragment.xyz = tex(texel, palette) * csc
624 * fragment.a = texel.a
626 ureg_TEX(shader
, texel
, TGSI_TEXTURE_2D
, tc
, sampler
);
627 ureg_MOV(shader
, ureg_writemask(fragment
, TGSI_WRITEMASK_W
), ureg_src(texel
));
630 ureg_TEX(shader
, texel
, TGSI_TEXTURE_1D
, ureg_src(texel
), palette
);
631 for (i
= 0; i
< 3; ++i
)
632 ureg_DP4(shader
, ureg_writemask(fragment
, TGSI_WRITEMASK_X
<< i
), csc
[i
], ureg_src(texel
));
634 ureg_TEX(shader
, ureg_writemask(fragment
, TGSI_WRITEMASK_XYZ
),
635 TGSI_TEXTURE_1D
, ureg_src(texel
), palette
);
638 ureg_release_temporary(shader
, texel
);
641 return ureg_create_shader_and_destroy(shader
, c
->pipe
);
645 create_frag_shader_rgba(struct vl_compositor
*c
)
647 struct ureg_program
*shader
;
649 struct ureg_src sampler
;
650 struct ureg_dst fragment
;
652 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
656 tc
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, 1, TGSI_INTERPOLATE_LINEAR
);
657 sampler
= ureg_DECL_sampler(shader
, 0);
658 fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
661 * fragment = tex(tc, sampler)
663 ureg_TEX(shader
, fragment
, TGSI_TEXTURE_2D
, tc
, sampler
);
666 return ureg_create_shader_and_destroy(shader
, c
->pipe
);
670 init_shaders(struct vl_compositor
*c
)
674 c
->vs
= create_vert_shader(c
);
676 debug_printf("Unable to create vertex shader.\n");
680 c
->fs_palette
.yuv
= create_frag_shader_palette(c
, true);
681 if (!c
->fs_palette
.yuv
) {
682 debug_printf("Unable to create YUV-Palette-to-RGB fragment shader.\n");
686 c
->fs_palette
.rgb
= create_frag_shader_palette(c
, false);
687 if (!c
->fs_palette
.rgb
) {
688 debug_printf("Unable to create RGB-Palette-to-RGB fragment shader.\n");
692 c
->fs_rgba
= create_frag_shader_rgba(c
);
694 debug_printf("Unable to create RGB-to-RGB fragment shader.\n");
701 static void cleanup_shaders(struct vl_compositor
*c
)
705 c
->pipe
->delete_vs_state(c
->pipe
, c
->vs
);
706 c
->pipe
->delete_fs_state(c
->pipe
, c
->fs_palette
.yuv
);
707 c
->pipe
->delete_fs_state(c
->pipe
, c
->fs_palette
.rgb
);
708 c
->pipe
->delete_fs_state(c
->pipe
, c
->fs_rgba
);
712 init_pipe_state(struct vl_compositor
*c
)
714 struct pipe_rasterizer_state rast
;
715 struct pipe_sampler_state sampler
;
716 struct pipe_blend_state blend
;
717 struct pipe_depth_stencil_alpha_state dsa
;
722 c
->fb_state
.nr_cbufs
= 1;
723 c
->fb_state
.zsbuf
= NULL
;
725 c
->viewport
.scale
[2] = 1;
726 c
->viewport
.scale
[3] = 1;
727 c
->viewport
.translate
[2] = 0;
728 c
->viewport
.translate
[3] = 0;
730 memset(&sampler
, 0, sizeof(sampler
));
731 sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
732 sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
733 sampler
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
734 sampler
.min_img_filter
= PIPE_TEX_FILTER_LINEAR
;
735 sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
736 sampler
.mag_img_filter
= PIPE_TEX_FILTER_LINEAR
;
737 sampler
.compare_mode
= PIPE_TEX_COMPARE_NONE
;
738 sampler
.compare_func
= PIPE_FUNC_ALWAYS
;
739 sampler
.normalized_coords
= 1;
741 c
->sampler_linear
= c
->pipe
->create_sampler_state(c
->pipe
, &sampler
);
743 sampler
.min_img_filter
= PIPE_TEX_FILTER_NEAREST
;
744 sampler
.mag_img_filter
= PIPE_TEX_FILTER_NEAREST
;
745 c
->sampler_nearest
= c
->pipe
->create_sampler_state(c
->pipe
, &sampler
);
747 sampler
.wrap_s
= sampler
.wrap_t
= sampler
.wrap_r
= PIPE_TEX_WRAP_REPEAT
;
748 sampler
.min_img_filter
= PIPE_TEX_FILTER_LINEAR
;
749 sampler
.mag_img_filter
= PIPE_TEX_FILTER_LINEAR
;
750 c
->sampler_repeat
= c
->pipe
->create_sampler_state(c
->pipe
, &sampler
);
752 memset(&blend
, 0, sizeof blend
);
753 blend
.independent_blend_enable
= 0;
754 blend
.rt
[0].blend_enable
= 0;
755 blend
.logicop_enable
= 0;
756 blend
.logicop_func
= PIPE_LOGICOP_CLEAR
;
757 blend
.rt
[0].colormask
= PIPE_MASK_RGBA
;
759 c
->blend_clear
= c
->pipe
->create_blend_state(c
->pipe
, &blend
);
761 blend
.rt
[0].blend_enable
= 1;
762 blend
.rt
[0].rgb_func
= PIPE_BLEND_ADD
;
763 blend
.rt
[0].rgb_src_factor
= PIPE_BLENDFACTOR_SRC_ALPHA
;
764 blend
.rt
[0].rgb_dst_factor
= PIPE_BLENDFACTOR_INV_SRC_ALPHA
;
765 blend
.rt
[0].alpha_func
= PIPE_BLEND_ADD
;
766 blend
.rt
[0].alpha_src_factor
= PIPE_BLENDFACTOR_ONE
;
767 blend
.rt
[0].alpha_dst_factor
= PIPE_BLENDFACTOR_ONE
;
768 c
->blend_add
= c
->pipe
->create_blend_state(c
->pipe
, &blend
);
770 memset(&rast
, 0, sizeof rast
);
773 rast
.cull_face
= PIPE_FACE_NONE
;
774 rast
.fill_back
= PIPE_POLYGON_MODE_FILL
;
775 rast
.fill_front
= PIPE_POLYGON_MODE_FILL
;
778 rast
.point_size_per_vertex
= 1;
779 rast
.offset_units
= 1;
780 rast
.offset_scale
= 1;
781 rast
.gl_rasterization_rules
= 1;
783 c
->rast
= c
->pipe
->create_rasterizer_state(c
->pipe
, &rast
);
785 memset(&dsa
, 0, sizeof dsa
);
786 dsa
.depth
.enabled
= 0;
787 dsa
.depth
.writemask
= 0;
788 dsa
.depth
.func
= PIPE_FUNC_ALWAYS
;
789 for (i
= 0; i
< 2; ++i
) {
790 dsa
.stencil
[i
].enabled
= 0;
791 dsa
.stencil
[i
].func
= PIPE_FUNC_ALWAYS
;
792 dsa
.stencil
[i
].fail_op
= PIPE_STENCIL_OP_KEEP
;
793 dsa
.stencil
[i
].zpass_op
= PIPE_STENCIL_OP_KEEP
;
794 dsa
.stencil
[i
].zfail_op
= PIPE_STENCIL_OP_KEEP
;
795 dsa
.stencil
[i
].valuemask
= 0;
796 dsa
.stencil
[i
].writemask
= 0;
798 dsa
.alpha
.enabled
= 0;
799 dsa
.alpha
.func
= PIPE_FUNC_ALWAYS
;
800 dsa
.alpha
.ref_value
= 0;
801 c
->dsa
= c
->pipe
->create_depth_stencil_alpha_state(c
->pipe
, &dsa
);
802 c
->pipe
->bind_depth_stencil_alpha_state(c
->pipe
, c
->dsa
);
807 static void cleanup_pipe_state(struct vl_compositor
*c
)
811 /* Asserted in softpipe_delete_fs_state() for some reason */
812 c
->pipe
->bind_vs_state(c
->pipe
, NULL
);
813 c
->pipe
->bind_fs_state(c
->pipe
, NULL
);
815 c
->pipe
->delete_depth_stencil_alpha_state(c
->pipe
, c
->dsa
);
816 c
->pipe
->delete_sampler_state(c
->pipe
, c
->sampler_linear
);
817 c
->pipe
->delete_sampler_state(c
->pipe
, c
->sampler_nearest
);
818 c
->pipe
->delete_sampler_state(c
->pipe
, c
->sampler_repeat
);
819 c
->pipe
->delete_blend_state(c
->pipe
, c
->blend_clear
);
820 c
->pipe
->delete_blend_state(c
->pipe
, c
->blend_add
);
821 c
->pipe
->delete_rasterizer_state(c
->pipe
, c
->rast
);
825 create_vertex_buffer(struct vl_compositor
*c
)
829 pipe_resource_reference(&c
->vertex_buf
.buffer
, NULL
);
830 c
->vertex_buf
.buffer
= pipe_buffer_create
833 PIPE_BIND_VERTEX_BUFFER
,
835 sizeof(struct vertex4f
) * VL_COMPOSITOR_MAX_LAYERS
* 4
838 return c
->vertex_buf
.buffer
!= NULL
;
842 init_buffers(struct vl_compositor
*c
)
844 struct pipe_vertex_element vertex_elems
[2];
849 * Create our vertex buffer and vertex buffer elements
851 c
->vertex_buf
.stride
= sizeof(struct vertex4f
);
852 c
->vertex_buf
.buffer_offset
= 0;
853 create_vertex_buffer(c
);
855 vertex_elems
[0].src_offset
= 0;
856 vertex_elems
[0].instance_divisor
= 0;
857 vertex_elems
[0].vertex_buffer_index
= 0;
858 vertex_elems
[0].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
859 vertex_elems
[1].src_offset
= sizeof(struct vertex2f
);
860 vertex_elems
[1].instance_divisor
= 0;
861 vertex_elems
[1].vertex_buffer_index
= 0;
862 vertex_elems
[1].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
863 c
->vertex_elems_state
= c
->pipe
->create_vertex_elements_state(c
->pipe
, 2, vertex_elems
);
866 * Create our fragment shader's constant buffer
867 * Const buffer contains the color conversion matrix and bias vectors
869 /* XXX: Create with IMMUTABLE/STATIC... although it does change every once in a long while... */
870 c
->csc_matrix
= pipe_buffer_create
873 PIPE_BIND_CONSTANT_BUFFER
,
875 sizeof(csc_matrix
) + sizeof(c
->original_sizes
)
877 assert((Elements(c
->csc
) + Elements(c
->original_sizes
))/4 == 7); // amount of constants
883 cleanup_buffers(struct vl_compositor
*c
)
887 c
->pipe
->delete_vertex_elements_state(c
->pipe
, c
->vertex_elems_state
);
888 pipe_resource_reference(&c
->vertex_buf
.buffer
, NULL
);
889 pipe_resource_reference(&c
->csc_matrix
, NULL
);
892 static INLINE
struct pipe_video_rect
893 default_rect(struct vl_compositor_layer
*layer
)
895 struct pipe_resource
*res
= layer
->sampler_views
[0]->texture
;
896 struct pipe_video_rect rect
= { 0, 0, res
->width0
, res
->height0
};
900 static INLINE
struct vertex2f
901 calc_topleft(struct vertex2f size
, struct pipe_video_rect rect
)
903 struct vertex2f res
= { rect
.x
/ size
.x
, rect
.y
/ size
.y
};
907 static INLINE
struct vertex2f
908 calc_bottomright(struct vertex2f size
, struct pipe_video_rect rect
)
910 struct vertex2f res
= { (rect
.x
+ rect
.w
) / size
.x
, (rect
.y
+ rect
.h
) / size
.y
};
915 calc_src_and_dst(struct vl_compositor_layer
*layer
, unsigned width
, unsigned height
,
916 struct pipe_video_rect src
, struct pipe_video_rect
*dst
)
918 struct vertex2f size_in
= { width
, height
};
919 struct vertex2f size_out
= { 1.f
, 1.f
};
921 layer
->src
.tl
= calc_topleft(size_in
, src
);
922 layer
->src
.br
= calc_bottomright(size_in
, src
);
924 layer
->dst
.tl
= calc_topleft(size_out
, *dst
);
925 layer
->dst
.br
= calc_bottomright(size_out
, *dst
);
926 layer
->custom_dest_rect
= 1;
928 layer
->dst
.tl
.x
= layer
->dst
.tl
.y
= 0.f
;
929 layer
->dst
.br
.x
= layer
->dst
.br
.y
= 1.f
;
930 layer
->custom_dest_rect
= 0;
935 gen_rect_verts(struct vertex4f
*vb
, struct vl_compositor_layer
*layer
, float w
, float h
)
939 vb
[0].x
= layer
->dst
.tl
.x
/ w
;
940 vb
[0].y
= layer
->dst
.tl
.y
/ h
;
941 vb
[0].z
= layer
->src
.tl
.x
;
942 vb
[0].w
= layer
->src
.tl
.y
;
944 vb
[1].x
= layer
->dst
.br
.x
/ w
;
945 vb
[1].y
= layer
->dst
.tl
.y
/ h
;
946 vb
[1].z
= layer
->src
.br
.x
;
947 vb
[1].w
= layer
->src
.tl
.y
;
949 vb
[2].x
= layer
->dst
.br
.x
/ w
;
950 vb
[2].y
= layer
->dst
.br
.y
/ h
;
951 vb
[2].z
= layer
->src
.br
.x
;
952 vb
[2].w
= layer
->src
.br
.y
;
954 vb
[3].x
= layer
->dst
.tl
.x
/ w
;
955 vb
[3].y
= layer
->dst
.br
.y
/ h
;
956 vb
[3].z
= layer
->src
.tl
.x
;
957 vb
[3].w
= layer
->src
.br
.y
;
961 gen_vertex_data(struct vl_compositor
*c
, float w
, float h
)
964 struct pipe_transfer
*buf_transfer
;
969 vb
= pipe_buffer_map(c
->pipe
, c
->vertex_buf
.buffer
,
970 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD
| PIPE_TRANSFER_DONTBLOCK
,
974 // If buffer is still locked from last draw create a new one
975 create_vertex_buffer(c
);
976 vb
= pipe_buffer_map(c
->pipe
, c
->vertex_buf
.buffer
,
977 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD
,
981 for (i
= 0; i
< VL_COMPOSITOR_MAX_LAYERS
; i
++) {
982 if (c
->used_layers
& (1 << i
)) {
983 struct vl_compositor_layer
*layer
= &c
->layers
[i
];
984 if (layer
->custom_dest_rect
)
985 gen_rect_verts(vb
, layer
, w
, h
);
987 gen_rect_verts(vb
, layer
, 1.f
, 1.f
);
990 if (layer
->clearing
&&
991 (!layer
->custom_dest_rect
||
992 (c
->dirty_tl
.x
>= layer
->dst
.tl
.x
/w
&&
993 c
->dirty_tl
.y
>= layer
->dst
.tl
.y
/h
&&
994 c
->dirty_br
.x
<= layer
->dst
.br
.x
/w
&&
995 c
->dirty_br
.y
<= layer
->dst
.br
.y
/h
))) {
996 // We clear the dirty area anyway, no need for clear_render_target
997 c
->dirty_tl
.x
= c
->dirty_tl
.y
= 1.0f
;
998 c
->dirty_br
.x
= c
->dirty_br
.y
= 0.0f
;
1003 pipe_buffer_unmap(c
->pipe
, buf_transfer
);
1007 draw_layers(struct vl_compositor
*c
, float w
, float h
)
1009 unsigned vb_index
, i
;
1013 for (i
= 0, vb_index
= 0; i
< VL_COMPOSITOR_MAX_LAYERS
; ++i
) {
1014 if (c
->used_layers
& (1 << i
)) {
1015 struct vl_compositor_layer
*layer
= &c
->layers
[i
];
1016 struct pipe_sampler_view
**samplers
= &layer
->sampler_views
[0];
1017 unsigned num_sampler_views
= !samplers
[1] ? 1 : !samplers
[2] ? 2 : !samplers
[3] ? 3 : !samplers
[4] ? 4 : 5;
1019 c
->pipe
->bind_blend_state(c
->pipe
, layer
->blend
);
1020 c
->pipe
->bind_fs_state(c
->pipe
, layer
->fs
);
1021 c
->pipe
->bind_fragment_sampler_states(c
->pipe
, num_sampler_views
, layer
->samplers
);
1022 c
->pipe
->set_fragment_sampler_views(c
->pipe
, num_sampler_views
, samplers
);
1023 util_draw_arrays(c
->pipe
, PIPE_PRIM_QUADS
, vb_index
* 4, 4);
1026 // Remember the currently drawn area as dirty for the next draw command
1027 if (layer
->custom_dest_rect
) {
1028 c
->dirty_tl
.x
= MIN2(layer
->dst
.tl
.x
/w
, c
->dirty_tl
.x
);
1029 c
->dirty_tl
.y
= MIN2(layer
->dst
.tl
.y
/h
, c
->dirty_tl
.y
);
1030 c
->dirty_br
.x
= MAX2(layer
->dst
.br
.x
/w
, c
->dirty_br
.x
);
1031 c
->dirty_br
.y
= MAX2(layer
->dst
.br
.y
/h
, c
->dirty_br
.y
);
1033 c
->dirty_tl
.x
= 0.f
;
1034 c
->dirty_tl
.y
= 0.f
;
1035 c
->dirty_br
.x
= 1.f
;
1036 c
->dirty_br
.y
= 1.f
;
1043 vl_compositor_reset_dirty_area(struct vl_compositor
*c
)
1047 c
->dirty_tl
.x
= c
->dirty_tl
.y
= 0.0f
;
1048 c
->dirty_br
.x
= c
->dirty_br
.y
= 1.0f
;
1052 vl_compositor_set_clear_color(struct vl_compositor
*c
, union pipe_color_union
*color
)
1056 c
->clear_color
= *color
;
1060 vl_compositor_get_clear_color(struct vl_compositor
*c
, union pipe_color_union
*color
)
1065 *color
= c
->clear_color
;
1069 vl_compositor_clear_layers(struct vl_compositor
*c
)
1076 for ( i
= 0; i
< VL_COMPOSITOR_MAX_LAYERS
; ++i
) {
1077 c
->layers
[i
].clearing
= i
? false : true;
1078 c
->layers
[i
].blend
= i
? c
->blend_add
: c
->blend_clear
;
1079 c
->layers
[i
].fs
= NULL
;
1080 for ( j
= 0; j
< 3; j
++)
1081 pipe_sampler_view_reference(&c
->layers
[i
].sampler_views
[j
], NULL
);
1086 cleanup_video(struct vl_compositor
*c
)
1089 for (i
= 0; i
< Elements(c
->video_res
); ++i
) {
1090 pipe_sampler_view_reference(&c
->video_sv
[i
], NULL
);
1091 pipe_surface_reference(&c
->video_surf
[i
], NULL
);
1092 pipe_resource_reference(&c
->video_res
[i
], NULL
);
1094 for (i
= 0; i
< Elements(c
->fs_weave
); ++i
) {
1095 if (!c
->fs_weave
[i
])
1097 c
->pipe
->delete_fs_state(c
->pipe
, c
->fs_weave
[i
]);
1098 c
->fs_weave
[i
] = NULL
;
1101 for (i
= 0; i
< Elements(c
->fs_video_buffer
); ++i
) {
1102 if (c
->fs_video_buffer
[i
])
1103 c
->pipe
->delete_fs_state(c
->pipe
, c
->fs_video_buffer
[i
]);
1104 c
->fs_video_buffer
[i
] = NULL
;
1109 vl_compositor_cleanup(struct vl_compositor
*c
)
1113 vl_compositor_clear_layers(c
);
1116 cleanup_pipe_state(c
);
1121 vl_compositor_set_csc_matrix(struct vl_compositor
*c
, const float matrix
[16])
1123 struct pipe_transfer
*buf_transfer
;
1128 map
= pipe_buffer_map(c
->pipe
, c
->csc_matrix
,
1129 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD
,
1131 memcpy(map
, matrix
, sizeof(csc_matrix
));
1132 memcpy(map
+ Elements(c
->csc
), c
->original_sizes
, sizeof(c
->original_sizes
));
1133 memcpy(c
->csc
, matrix
, sizeof(csc_matrix
));
1134 pipe_buffer_unmap(c
->pipe
, buf_transfer
);
1138 vl_compositor_set_layer_blend(struct vl_compositor
*c
,
1139 unsigned layer
, void *blend
,
1144 assert(layer
< VL_COMPOSITOR_MAX_LAYERS
);
1146 c
->layers
[layer
].clearing
= is_clearing
;
1147 c
->layers
[layer
].blend
= blend
;
1151 static void gen_vertex_data_video(struct vl_compositor
*c
) {
1152 struct vertex4f
*vb
;
1153 struct pipe_transfer
*buf_transfer
;
1154 vb
= pipe_buffer_map(c
->pipe
, c
->vertex_buf
.buffer
,
1155 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD
| PIPE_TRANSFER_DONTBLOCK
,
1159 // If buffer is still locked from last draw create a new one
1160 create_vertex_buffer(c
);
1161 vb
= pipe_buffer_map(c
->pipe
, c
->vertex_buf
.buffer
,
1162 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD
,
1179 pipe_buffer_unmap(c
->pipe
, buf_transfer
);
1183 vl_compositor_render_sobel(struct vl_compositor
*c
, struct pipe_sampler_view
**sv
)
1185 struct pipe_scissor_state scissor
;
1186 struct pipe_surface
*dst_surface
;
1188 struct pipe_sampler_view
*sv_render
[3];
1190 for (i
= 0; i
< 3; ++i
) {
1191 sv_render
[i
] = sv
[i
];
1192 samplers
[i
] = c
->sampler_linear
;
1197 gen_vertex_data_video(c
);
1199 c
->pipe
->bind_vs_state(c
->pipe
, c
->vs
);
1200 c
->pipe
->set_vertex_buffers(c
->pipe
, 1, &c
->vertex_buf
);
1201 c
->pipe
->bind_vertex_elements_state(c
->pipe
, c
->vertex_elems_state
);
1202 c
->pipe
->bind_rasterizer_state(c
->pipe
, c
->rast
);
1203 c
->pipe
->bind_blend_state(c
->pipe
, c
->blend_clear
);
1204 c
->pipe
->bind_fragment_sampler_states(c
->pipe
, 3, samplers
);
1206 for (i
= 0; i
< 2; ++i
) {
1208 sv_render
[0] = c
->video_sv
[3];
1209 c
->pipe
->set_fragment_sampler_views(c
->pipe
, 3, sv_render
);
1211 c
->viewport
.scale
[0] = sv
[i
]->texture
->width0
;
1212 c
->viewport
.scale
[1] = sv
[i
]->texture
->height0
;
1213 c
->viewport
.translate
[0] = 0;
1214 c
->viewport
.translate
[1] = 0;
1215 c
->pipe
->set_viewport_state(c
->pipe
, &c
->viewport
);
1217 c
->pipe
->bind_fs_state(c
->pipe
, c
->fs_weave
[3+i
]);
1218 dst_surface
= c
->video_surf
[3 + i
];
1220 c
->fb_state
.width
= dst_surface
->width
;
1221 c
->fb_state
.height
= dst_surface
->height
;
1222 c
->fb_state
.cbufs
[0] = dst_surface
;
1226 scissor
.maxx
= dst_surface
->width
;
1227 scissor
.maxy
= dst_surface
->height
;
1229 c
->pipe
->set_scissor_state(c
->pipe
, &scissor
);
1230 c
->pipe
->set_framebuffer_state(c
->pipe
, &c
->fb_state
);
1231 util_draw_arrays(c
->pipe
, PIPE_PRIM_TRIANGLES
, 0, 3);
1236 vl_compositor_render_video(struct vl_compositor
*c
,
1237 struct pipe_sampler_view
**sv
,
1238 unsigned interlaced
)
1240 struct pipe_scissor_state scissor
;
1243 for (i
= 0; i
< 4; ++i
) {
1244 if (!interlaced
|| i
< 2 || c
->chroma
!= PIPE_VIDEO_CHROMA_FORMAT_420
)
1245 samplers
[i
] = c
->sampler_nearest
;
1247 samplers
[i
] = c
->sampler_linear
;
1250 gen_vertex_data_video(c
);
1251 for (i
= 0; i
< 2; ++i
) {
1252 struct pipe_surface
*dst_surface
;
1253 unsigned num_sampler_views
;
1256 num_sampler_views
= 2;
1257 dst_surface
= c
->video_surf
[0];
1258 fs
= c
->fs_weave
[0];
1260 num_sampler_views
= 4;
1262 dst_surface
= c
->video_surf
[1];
1263 fs
= c
->fs_weave
[1];
1265 dst_surface
= c
->video_surf
[2];
1266 fs
= c
->fs_weave
[2];
1270 assert(dst_surface
);
1271 c
->fb_state
.width
= dst_surface
->width
;
1272 c
->fb_state
.height
= dst_surface
->height
;
1273 c
->fb_state
.cbufs
[0] = dst_surface
;
1275 c
->viewport
.scale
[0] = sv
[0]->texture
->width0
;
1276 c
->viewport
.scale
[1] = sv
[0]->texture
->height0
* 2;
1277 if (i
&& c
->chroma
== PIPE_VIDEO_CHROMA_FORMAT_420
&& interlaced
)
1278 c
->viewport
.scale
[1] *= 2;
1279 c
->viewport
.translate
[0] = 0;
1280 c
->viewport
.translate
[1] = 0;
1284 scissor
.maxx
= dst_surface
->width
;
1285 scissor
.maxy
= dst_surface
->height
;
1287 c
->pipe
->set_scissor_state(c
->pipe
, &scissor
);
1288 c
->pipe
->set_framebuffer_state(c
->pipe
, &c
->fb_state
);
1289 c
->pipe
->set_viewport_state(c
->pipe
, &c
->viewport
);
1290 c
->pipe
->bind_vs_state(c
->pipe
, c
->vs
);
1291 c
->pipe
->set_vertex_buffers(c
->pipe
, 1, &c
->vertex_buf
);
1292 c
->pipe
->bind_vertex_elements_state(c
->pipe
, c
->vertex_elems_state
);
1293 c
->pipe
->bind_rasterizer_state(c
->pipe
, c
->rast
);
1295 c
->pipe
->bind_blend_state(c
->pipe
, c
->blend_clear
);
1296 c
->pipe
->bind_fs_state(c
->pipe
, fs
);
1297 c
->pipe
->bind_fragment_sampler_states(c
->pipe
, num_sampler_views
, samplers
);
1298 c
->pipe
->set_fragment_sampler_views(c
->pipe
, num_sampler_views
, sv
);
1299 sv
+= num_sampler_views
;
1300 util_draw_arrays(c
->pipe
, PIPE_PRIM_TRIANGLES
, 0, 3);
1305 vl_compositor_set_buffer_layer(struct vl_compositor
*c
, unsigned layer
,
1306 enum pipe_video_picture_structure field
,
1307 struct pipe_video_buffer
*buffer
,
1308 struct pipe_video_rect
*src_rect
,
1309 struct pipe_video_rect
*dst_rect
,
1310 unsigned past_count
,
1311 struct pipe_video_buffer
**past
,
1312 unsigned future_count
,
1313 struct pipe_video_buffer
**future
)
1315 struct pipe_sampler_view
**sampler_views
, *sv_weave
[6], *sv
[VL_COMPOSITOR_SAMPLERS
] = {};
1316 struct pipe_video_rect rect
;
1317 unsigned i
, half_h
= 0;
1319 assert(c
&& buffer
);
1320 assert(c
->video_w
<= buffer
->width
&& c
->video_h
<= buffer
->height
);
1321 assert(layer
< VL_COMPOSITOR_MAX_LAYERS
);
1323 if (field
== PIPE_VIDEO_PICTURE_STRUCTURE_FRAME
) {
1324 sampler_views
= buffer
->get_sampler_view_planes(buffer
, 0);
1325 if (!sampler_views
) {
1326 sampler_views
= buffer
->get_sampler_view_planes(buffer
, 1);
1327 for (i
= 0; i
< 6; ++i
)
1328 sv_weave
[i
] = sampler_views
[i
];
1330 sv_weave
[4] = sv_weave
[2];
1332 sv_weave
[5] = sv_weave
[3];
1333 vl_compositor_render_video(c
, sv_weave
, 0);
1334 sv
[0] = c
->video_sv
[0];
1335 sv
[2] = sv
[1] = c
->video_sv
[2];
1337 for (i
= 0; i
< 3; ++i
)
1338 sv
[i
] = sampler_views
[i
];
1343 struct pipe_sampler_view
**sv_cur
, **sv_prev
= NULL
;
1344 int top
= field
== PIPE_VIDEO_PICTURE_STRUCTURE_FIELD_TOP
;
1345 sv_cur
= buffer
->get_sampler_view_planes(buffer
, 1);
1346 if (past_count
&& past
[0])
1347 sv_prev
= buffer
->get_sampler_view_planes(past
[0], 1);
1349 for (i
= 0; i
< 6; i
+= 2) {
1351 sv_weave
[i
] = sv_cur
[i
];
1352 sv_weave
[i
+1] = sv_prev
[i
+1];
1354 sv_weave
[i
] = sv_prev
[i
];
1355 sv_weave
[i
+1] = sv_cur
[i
+1];
1359 sv_weave
[4] = sv_weave
[2];
1361 sv_weave
[5] = sv_weave
[3];
1362 vl_compositor_render_video(c
, sv_weave
, 1);
1363 sv
[0] = c
->video_sv
[0];
1364 sv
[2] = sv
[1] = c
->video_sv
[1];
1366 for (i
= 0; i
< 3; ++i
)
1367 sv
[i
] = sv_cur
[2*i
+!top
];
1373 assert(sv
[2] && sv
[1] && sv
[0]);
1375 if (DEBUG_CONTOUR
&& !half_h
)
1376 vl_compositor_render_sobel(c
, sv
);
1378 c
->used_layers
|= 1 << layer
;
1381 rect
.x
= rect
.y
= 0;
1382 rect
.w
= c
->video_w
;
1383 rect
.h
= c
->video_h
;
1385 if (DEBUG_CONTOUR
&& !half_h
) {
1386 c
->layers
[layer
].fs
= c
->fs_video_buffer
[1];
1387 sv
[3] = c
->video_sv
[3];
1388 sv
[4] = c
->video_sv
[4];
1390 c
->layers
[layer
].fs
= c
->fs_video_buffer
[0];
1392 for (i
= 0; i
< VL_COMPOSITOR_SAMPLERS
; ++i
) {
1393 c
->layers
[layer
].samplers
[i
] = c
->sampler_linear
;
1394 pipe_sampler_view_reference(&c
->layers
[layer
].sampler_views
[i
], sv
[i
]);
1397 pipe_sampler_view_reference(&c
->layers
[layer
].sampler_views
[3], c
->video_sv
[4]);
1398 c
->layers
[layer
].samplers
[3] = c
->sampler_repeat
;
1401 if (c
->original_sizes
[0] != (float)sv
[0]->texture
->width0
||
1402 c
->original_sizes
[1] != (float)sv
[0]->texture
->height0
||
1403 c
->original_sizes
[2] != (float)sv
[1]->texture
->width0
||
1404 c
->original_sizes
[3] != (float)sv
[1]->texture
->height0
) {
1405 struct pipe_transfer
*buf_transfer
;
1406 float *map
= pipe_buffer_map(c
->pipe
, c
->csc_matrix
,
1407 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD
,
1409 c
->original_sizes
[0] = (float)sv
[0]->texture
->width0
;
1410 c
->original_sizes
[1] = (float)sv
[0]->texture
->height0
;
1411 c
->original_sizes
[2] = (float)sv
[1]->texture
->width0
;
1412 c
->original_sizes
[3] = (float)sv
[1]->texture
->height0
;
1413 c
->original_sizes
[4] = 1.f
/(float)sv
[0]->texture
->width0
;
1414 c
->original_sizes
[5] = 1.f
/(float)sv
[0]->texture
->height0
;
1415 c
->original_sizes
[6] = 1.f
/(float)sv
[1]->texture
->width0
;
1416 c
->original_sizes
[7] = 1.f
/(float)sv
[1]->texture
->height0
;
1417 c
->original_sizes
[8] = .5f
/(float)sv
[0]->texture
->width0
;
1418 c
->original_sizes
[9] = .5f
/(float)sv
[0]->texture
->height0
;
1419 c
->original_sizes
[10] = .5f
/(float)sv
[1]->texture
->width0
;
1420 c
->original_sizes
[11] = .5f
/(float)sv
[1]->texture
->height0
;
1421 memcpy(map
, c
->csc
, sizeof(c
->csc
));
1422 memcpy(map
+ Elements(c
->csc
), c
->original_sizes
, sizeof(c
->original_sizes
));
1423 pipe_buffer_unmap(c
->pipe
, buf_transfer
);
1426 calc_src_and_dst(&c
->layers
[layer
],
1427 sv
[0]->texture
->width0
,
1428 sv
[0]->texture
->height0
<< half_h
,
1429 *src_rect
, dst_rect
);
1433 vl_compositor_set_palette_layer(struct vl_compositor
*c
,
1435 struct pipe_sampler_view
*indexes
,
1436 struct pipe_sampler_view
*palette
,
1437 struct pipe_video_rect
*src_rect
,
1438 struct pipe_video_rect
*dst_rect
,
1439 bool include_color_conversion
)
1441 assert(c
&& indexes
&& palette
);
1444 assert(layer
< VL_COMPOSITOR_MAX_LAYERS
);
1446 c
->used_layers
|= 1 << layer
;
1448 c
->layers
[layer
].fs
= include_color_conversion
?
1449 c
->fs_palette
.yuv
: c
->fs_palette
.rgb
;
1451 c
->layers
[layer
].samplers
[0] = c
->sampler_linear
;
1452 c
->layers
[layer
].samplers
[1] = c
->sampler_nearest
;
1453 pipe_sampler_view_reference(&c
->layers
[layer
].sampler_views
[0], indexes
);
1454 pipe_sampler_view_reference(&c
->layers
[layer
].sampler_views
[1], palette
);
1455 for (i
= 2; i
< VL_COMPOSITOR_SAMPLERS
; ++i
) {
1456 pipe_sampler_view_reference(&c
->layers
[layer
].sampler_views
[i
], NULL
);
1457 c
->layers
[layer
].samplers
[i
] = NULL
;
1459 calc_src_and_dst(&c
->layers
[layer
], indexes
->texture
->width0
, indexes
->texture
->height0
,
1460 src_rect
? *src_rect
: default_rect(&c
->layers
[layer
]),
1465 vl_compositor_set_rgba_layer(struct vl_compositor
*c
,
1467 struct pipe_sampler_view
*rgba
,
1468 struct pipe_video_rect
*src_rect
,
1469 struct pipe_video_rect
*dst_rect
)
1474 assert(layer
< VL_COMPOSITOR_MAX_LAYERS
);
1476 c
->used_layers
|= 1 << layer
;
1477 c
->layers
[layer
].fs
= c
->fs_rgba
;
1478 c
->layers
[layer
].samplers
[0] = c
->sampler_linear
;
1479 pipe_sampler_view_reference(&c
->layers
[layer
].sampler_views
[0], rgba
);
1480 for (i
= 1; i
< VL_COMPOSITOR_SAMPLERS
; ++i
) {
1481 pipe_sampler_view_reference(&c
->layers
[layer
].sampler_views
[i
], NULL
);
1482 c
->layers
[layer
].samplers
[i
] = NULL
;
1484 calc_src_and_dst(&c
->layers
[layer
], rgba
->texture
->width0
, rgba
->texture
->height0
,
1485 src_rect
? *src_rect
: default_rect(&c
->layers
[layer
]),
1490 vl_compositor_render(struct vl_compositor
*c
,
1491 struct pipe_surface
*dst_surface
,
1492 struct pipe_video_rect
*dst_area
,
1493 struct pipe_video_rect
*dst_clip
,
1494 bool clear_dirty_area
)
1496 struct pipe_scissor_state scissor
;
1499 assert(dst_surface
);
1501 c
->fb_state
.width
= dst_surface
->width
;
1502 c
->fb_state
.height
= dst_surface
->height
;
1503 c
->fb_state
.cbufs
[0] = dst_surface
;
1506 c
->viewport
.scale
[0] = dst_area
->w
;
1507 c
->viewport
.scale
[1] = dst_area
->h
;
1508 c
->viewport
.translate
[0] = dst_area
->x
;
1509 c
->viewport
.translate
[1] = dst_area
->y
;
1511 c
->viewport
.scale
[0] = dst_surface
->width
;
1512 c
->viewport
.scale
[1] = dst_surface
->height
;
1513 c
->viewport
.translate
[0] = 0;
1514 c
->viewport
.translate
[1] = 0;
1518 scissor
.minx
= dst_clip
->x
;
1519 scissor
.miny
= dst_clip
->y
;
1520 scissor
.maxx
= dst_clip
->x
+ dst_clip
->w
;
1521 scissor
.maxy
= dst_clip
->y
+ dst_clip
->h
;
1525 scissor
.maxx
= dst_surface
->width
;
1526 scissor
.maxy
= dst_surface
->height
;
1529 gen_vertex_data(c
, dst_surface
->width
, dst_surface
->height
);
1531 if (clear_dirty_area
&& (c
->dirty_tl
.x
< c
->dirty_br
.x
||
1532 c
->dirty_tl
.y
< c
->dirty_br
.y
)) {
1533 util_clear_render_target(c
->pipe
, dst_surface
, &c
->clear_color
,
1534 0, 0, dst_surface
->width
, dst_surface
->height
);
1535 c
->dirty_tl
.x
= c
->dirty_tl
.y
= 1.0f
;
1536 c
->dirty_br
.x
= c
->dirty_br
.y
= 0.0f
;
1539 c
->pipe
->set_scissor_state(c
->pipe
, &scissor
);
1540 c
->pipe
->set_framebuffer_state(c
->pipe
, &c
->fb_state
);
1541 c
->pipe
->set_viewport_state(c
->pipe
, &c
->viewport
);
1542 c
->pipe
->bind_vs_state(c
->pipe
, c
->vs
);
1543 c
->pipe
->set_vertex_buffers(c
->pipe
, 1, &c
->vertex_buf
);
1544 c
->pipe
->bind_vertex_elements_state(c
->pipe
, c
->vertex_elems_state
);
1545 c
->pipe
->set_constant_buffer(c
->pipe
, PIPE_SHADER_FRAGMENT
, 0, c
->csc_matrix
);
1546 c
->pipe
->bind_rasterizer_state(c
->pipe
, c
->rast
);
1548 draw_layers(c
, dst_surface
->width
, dst_surface
->height
);
1552 vl_compositor_init(struct vl_compositor
*c
, struct pipe_context
*pipe
)
1554 csc_matrix csc_matrix
;
1558 if (!init_pipe_state(c
))
1561 if (!init_shaders(c
)) {
1562 cleanup_pipe_state(c
);
1566 if (!init_buffers(c
)) {
1568 cleanup_pipe_state(c
);
1572 vl_compositor_clear_layers(c
);
1574 vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_IDENTITY
, NULL
, true, csc_matrix
);
1575 vl_compositor_set_csc_matrix(c
, c
->csc
);
1577 c
->clear_color
.f
[0] = c
->clear_color
.f
[1] = 0.0f
;
1578 c
->clear_color
.f
[2] = c
->clear_color
.f
[3] = 0.0f
;
1579 vl_compositor_reset_dirty_area(c
);
1585 vl_compositor_init_video(struct vl_compositor
*c
, struct pipe_context
*pipe
,
1586 enum pipe_video_chroma_format chroma
, unsigned w
, unsigned h
)
1588 struct pipe_resource templ
;
1590 if (!vl_compositor_init(c
, pipe
))
1596 c
->fs_video_buffer
[0] = create_frag_shader_bicubic(c
);
1598 c
->fs_video_buffer
[0] = create_frag_shader_video_buffer(c
);
1600 c
->fs_video_buffer
[1] = create_frag_shader_sobel_video(c
);
1602 for (i
= 0; i
< Elements(c
->fs_video_buffer
); ++i
) {
1603 if (i
== 1 && !DEBUG_CONTOUR
) continue;
1604 if (!c
->fs_video_buffer
[i
]) {
1605 debug_printf("Unable to create YCbCr-to-RGB fragment shader %i.\n", i
);
1609 c
->fs_weave
[0] = create_frag_shader_weave(c
, 1, 0);
1610 c
->fs_weave
[1] = create_frag_shader_weave(c
, 0, 1); // interlaced
1611 c
->fs_weave
[2] = create_frag_shader_weave(c
, 0, 0); // progressive
1612 if (DEBUG_CONTOUR
) {
1613 c
->fs_weave
[3] = create_frag_shader_sobel(c
, 0);
1614 c
->fs_weave
[4] = create_frag_shader_sobel(c
, 3);
1616 for (i
= 0; i
< Elements(c
->fs_weave
); ++i
) {
1617 if (!DEBUG_CONTOUR
&& (i
>= 3 && i
<= 4)) continue;
1618 if (!c
->fs_weave
[i
]) {
1619 debug_printf("Unable to create weave fragment shaders [%i].\n", i
);
1623 memset(&templ
, 0, sizeof(templ
));
1624 templ
.target
= PIPE_TEXTURE_2D
;
1625 templ
.format
= PIPE_FORMAT_R8_UNORM
;
1629 templ
.array_size
= 1;
1630 templ
.bind
= PIPE_BIND_SAMPLER_VIEW
| PIPE_BIND_RENDER_TARGET
;
1631 templ
.usage
= PIPE_USAGE_STATIC
;
1632 c
->video_res
[0] = pipe
->screen
->resource_create(pipe
->screen
, &templ
);
1633 if (!c
->video_res
[0]) {
1634 debug_printf("Could not create weave temp frame for luma\n");
1638 if (chroma
!= PIPE_VIDEO_CHROMA_FORMAT_444
)
1640 templ
.format
= PIPE_FORMAT_R8G8_UNORM
;
1641 c
->video_res
[1] = pipe
->screen
->resource_create(pipe
->screen
, &templ
);
1642 if (!c
->video_res
[1]) {
1643 debug_printf("Could not create interlaced temp frame for chroma\n");
1647 if (chroma
== PIPE_VIDEO_CHROMA_FORMAT_420
)
1648 templ
.height0
= h
/ 2;
1649 c
->video_res
[2] = pipe
->screen
->resource_create(pipe
->screen
, &templ
);
1650 if (!c
->video_res
[2]) {
1651 debug_printf("Could not create deinterlaced temp frame for chroma\n");
1655 if (DEBUG_CONTOUR
) {
1656 c
->video_res
[3] = pipe
->screen
->resource_create(pipe
->screen
, c
->video_res
[0]);
1657 if (!c
->video_res
[3]) {
1658 debug_printf("Could not create sobel temp frame for luma\n");
1661 templ
.format
= PIPE_FORMAT_R8G8B8A8_UNORM
;
1662 c
->video_res
[4] = pipe
->screen
->resource_create(pipe
->screen
, &templ
);
1663 if (!c
->video_res
[4]) {
1664 debug_printf("Could not create sobel temp frame for chroma\n");
1670 memset(&templ
, 0, sizeof(templ
));
1671 templ
.target
= PIPE_TEXTURE_1D
;
1672 templ
.format
= PIPE_FORMAT_R16G16B16A16_UNORM
;
1676 templ
.array_size
= 1;
1677 templ
.bind
= PIPE_BIND_SAMPLER_VIEW
;
1678 templ
.usage
= PIPE_USAGE_STATIC
;
1679 c
->video_res
[5] = pipe
->screen
->resource_create(pipe
->screen
, &templ
);
1680 if (!c
->video_res
[5]) {
1681 debug_printf("Could not generate lookup texture\n");
1685 if (c
->video_res
[5]) {
1686 struct pipe_transfer
*buf_transfer
;
1687 unsigned short *map
= pipe_buffer_map(c
->pipe
, c
->video_res
[4],
1688 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD
,
1691 for (i
= 0; i
< templ
.width0
; ++i
, map
+= 4) {
1692 float weight
[4], h0
, h1
, g0
;
1693 float alpha
= (float)i
/ (float)templ
.width0
;
1694 float alpha2
= alpha
* alpha
;
1695 float alpha3
= alpha2
* alpha
;
1696 float mul
= (float)((sizeof(*map
)<<8)-1);
1698 weight
[0] = (-alpha3
+ 3.f
* alpha2
- 3.f
* alpha
+ 1.f
) / 6.f
;
1699 weight
[1] = (3.f
* alpha3
- 6.f
* alpha2
+ 4.f
) / 6.f
;
1700 weight
[2] = (-3.f
* alpha3
+ 3.f
* alpha2
+ 3.f
* alpha
+ 1.f
) / 6.f
;
1701 weight
[3] = alpha3
/ 6.f
;
1702 h0
= 1.f
+ alpha
- weight
[1] / (weight
[0] + weight
[1]);
1703 h1
= 1.f
- alpha
+ weight
[3] / (weight
[2] + weight
[3]);
1704 g0
= weight
[0] + weight
[1];
1710 pipe_buffer_unmap(c
->pipe
, buf_transfer
);
1713 for (i
= 0; i
< Elements(c
->video_res
); ++i
) {
1714 struct pipe_sampler_view sv_templ
;
1715 struct pipe_surface surf_templ
;
1716 if (!c
->video_res
[i
]) continue;
1718 memset(&sv_templ
, 0, sizeof(sv_templ
));
1719 u_sampler_view_default_template(&sv_templ
, c
->video_res
[i
], c
->video_res
[i
]->format
);
1720 if (c
->video_res
[i
]->format
== PIPE_FORMAT_R8_UNORM
)
1721 sv_templ
.swizzle_a
= sv_templ
.swizzle_b
= sv_templ
.swizzle_g
= sv_templ
.swizzle_r
;
1722 else if (c
->video_res
[i
]->format
== PIPE_FORMAT_R8G8_UNORM
) {
1723 sv_templ
.swizzle_b
= PIPE_SWIZZLE_GREEN
;
1724 sv_templ
.swizzle_g
= PIPE_SWIZZLE_RED
;
1726 c
->video_sv
[i
] = pipe
->create_sampler_view(pipe
, c
->video_res
[i
], &sv_templ
);
1728 if (!c
->video_sv
[i
]) {
1729 debug_printf("Could not create temp video sampler views\n");
1733 memset(&surf_templ
, 0, sizeof(surf_templ
));
1734 surf_templ
.usage
= PIPE_BIND_SAMPLER_VIEW
| PIPE_BIND_RENDER_TARGET
;
1735 surf_templ
.format
= c
->video_res
[i
]->format
;
1736 c
->video_surf
[i
] = pipe
->create_surface(pipe
, c
->video_res
[i
], &surf_templ
);
1737 if (!c
->video_surf
[i
]) {
1738 debug_printf("Could not create temp video surface\n");
1746 vl_compositor_cleanup(c
);