1 /**************************************************************************
3 * Copyright 2012 Christian König.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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 TUNGSTEN GRAPHICS 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.
26 **************************************************************************/
30 #include "pipe/p_context.h"
32 #include "tgsi/tgsi_ureg.h"
34 #include "util/u_draw.h"
35 #include "util/u_memory.h"
36 #include "util/u_math.h"
39 #include "vl_vertex_buffers.h"
40 #include "vl_matrix_filter.h"
49 create_vert_shader(struct vl_matrix_filter
*filter
)
51 struct ureg_program
*shader
;
52 struct ureg_src i_vpos
;
53 struct ureg_dst o_vpos
, o_vtex
;
55 shader
= ureg_create(TGSI_PROCESSOR_VERTEX
);
59 i_vpos
= ureg_DECL_vs_input(shader
, 0);
60 o_vpos
= ureg_DECL_output(shader
, TGSI_SEMANTIC_POSITION
, VS_O_VPOS
);
61 o_vtex
= ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_VTEX
);
63 ureg_MOV(shader
, o_vpos
, i_vpos
);
64 ureg_MOV(shader
, o_vtex
, i_vpos
);
68 return ureg_create_shader_and_destroy(shader
, filter
->pipe
);
72 is_vec_zero(struct vertex2f v
)
74 return v
.x
== 0.0f
&& v
.y
== 0.0f
;
78 create_frag_shader(struct vl_matrix_filter
*filter
, unsigned num_offsets
,
79 struct vertex2f
*offsets
, const float *matrix_values
)
81 struct ureg_program
*shader
;
82 struct ureg_src i_vtex
;
83 struct ureg_src sampler
;
84 struct ureg_dst
*t_array
= MALLOC(sizeof(struct ureg_dst
) * num_offsets
);
85 struct ureg_dst t_sum
;
86 struct ureg_dst o_fragment
;
90 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
96 i_vtex
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_VTEX
, TGSI_INTERPOLATE_LINEAR
);
97 sampler
= ureg_DECL_sampler(shader
, 0);
99 for (i
= 0; i
< num_offsets
; ++i
)
100 if (matrix_values
[i
] != 0.0f
)
101 t_array
[i
] = ureg_DECL_temporary(shader
);
103 o_fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
106 * t_array[0..*] = vtex + offset[0..*]
107 * t_array[0..*] = tex(t_array[0..*], sampler)
108 * o_fragment = sum(t_array[0..*] * matrix_values[0..*])
111 for (i
= 0; i
< num_offsets
; ++i
) {
112 if (matrix_values
[i
] != 0.0f
&& !is_vec_zero(offsets
[i
])) {
113 ureg_ADD(shader
, ureg_writemask(t_array
[i
], TGSI_WRITEMASK_XY
),
114 i_vtex
, ureg_imm2f(shader
, offsets
[i
].x
, offsets
[i
].y
));
115 ureg_MOV(shader
, ureg_writemask(t_array
[i
], TGSI_WRITEMASK_ZW
),
116 ureg_imm1f(shader
, 0.0f
));
120 for (i
= 0; i
< num_offsets
; ++i
) {
121 if (matrix_values
[i
] != 0.0f
) {
122 struct ureg_src src
= is_vec_zero(offsets
[i
]) ? i_vtex
: ureg_src(t_array
[i
]);
123 ureg_TEX(shader
, t_array
[i
], TGSI_TEXTURE_2D
, src
, sampler
);
127 for (i
= 0, first
= true; i
< num_offsets
; ++i
) {
128 if (matrix_values
[i
] != 0.0f
) {
131 ureg_MUL(shader
, t_sum
, ureg_src(t_array
[i
]),
132 ureg_imm1f(shader
, matrix_values
[i
]));
135 ureg_MAD(shader
, t_sum
, ureg_src(t_array
[i
]),
136 ureg_imm1f(shader
, matrix_values
[i
]), ureg_src(t_sum
));
140 ureg_MOV(shader
, o_fragment
, ureg_imm1f(shader
, 0.0f
));
142 ureg_MOV(shader
, o_fragment
, ureg_src(t_sum
));
147 return ureg_create_shader_and_destroy(shader
, filter
->pipe
);
151 vl_matrix_filter_init(struct vl_matrix_filter
*filter
, struct pipe_context
*pipe
,
152 unsigned video_width
, unsigned video_height
,
153 unsigned matrix_width
, unsigned matrix_height
,
154 const float *matrix_values
)
156 struct pipe_rasterizer_state rs_state
;
157 struct pipe_blend_state blend
;
158 struct pipe_sampler_state sampler
;
159 struct pipe_vertex_element ve
;
160 struct vertex2f
*offsets
, v
, sizes
;
161 unsigned i
, num_offsets
= matrix_width
* matrix_height
;
163 assert(filter
&& pipe
);
164 assert(video_width
&& video_height
);
165 assert(matrix_width
&& matrix_height
);
167 memset(filter
, 0, sizeof(*filter
));
170 memset(&rs_state
, 0, sizeof(rs_state
));
171 rs_state
.half_pixel_center
= true;
172 rs_state
.bottom_edge_rule
= true;
173 rs_state
.depth_clip
= 1;
174 filter
->rs_state
= pipe
->create_rasterizer_state(pipe
, &rs_state
);
175 if (!filter
->rs_state
)
178 memset(&blend
, 0, sizeof blend
);
179 blend
.rt
[0].rgb_func
= PIPE_BLEND_ADD
;
180 blend
.rt
[0].rgb_src_factor
= PIPE_BLENDFACTOR_ONE
;
181 blend
.rt
[0].rgb_dst_factor
= PIPE_BLENDFACTOR_ONE
;
182 blend
.rt
[0].alpha_func
= PIPE_BLEND_ADD
;
183 blend
.rt
[0].alpha_src_factor
= PIPE_BLENDFACTOR_ONE
;
184 blend
.rt
[0].alpha_dst_factor
= PIPE_BLENDFACTOR_ONE
;
185 blend
.logicop_func
= PIPE_LOGICOP_CLEAR
;
186 blend
.rt
[0].colormask
= PIPE_MASK_RGBA
;
187 filter
->blend
= pipe
->create_blend_state(pipe
, &blend
);
191 memset(&sampler
, 0, sizeof(sampler
));
192 sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
193 sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
194 sampler
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
195 sampler
.min_img_filter
= PIPE_TEX_FILTER_NEAREST
;
196 sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
197 sampler
.mag_img_filter
= PIPE_TEX_FILTER_NEAREST
;
198 sampler
.compare_mode
= PIPE_TEX_COMPARE_NONE
;
199 sampler
.compare_func
= PIPE_FUNC_ALWAYS
;
200 sampler
.normalized_coords
= 1;
201 filter
->sampler
= pipe
->create_sampler_state(pipe
, &sampler
);
202 if (!filter
->sampler
)
205 filter
->quad
= vl_vb_upload_quads(pipe
);
206 if(!filter
->quad
.buffer
)
209 memset(&ve
, 0, sizeof(ve
));
211 ve
.instance_divisor
= 0;
212 ve
.vertex_buffer_index
= 0;
213 ve
.src_format
= PIPE_FORMAT_R32G32_FLOAT
;
214 filter
->ves
= pipe
->create_vertex_elements_state(pipe
, 1, &ve
);
218 offsets
= MALLOC(sizeof(struct vertex2f
) * num_offsets
);
222 sizes
.x
= (float)(matrix_width
- 1) / 2.0f
;
223 sizes
.y
= (float)(matrix_height
- 1) / 2.0f
;
225 for (v
.x
= -sizes
.x
, i
= 0; v
.x
<= sizes
.x
; v
.x
+= 1.0f
)
226 for (v
.y
= -sizes
.y
; v
.y
<= sizes
.y
; v
.y
+= 1.0f
)
229 for (i
= 0; i
< num_offsets
; ++i
) {
230 offsets
[i
].x
/= video_width
;
231 offsets
[i
].y
/= video_height
;
234 filter
->vs
= create_vert_shader(filter
);
238 filter
->fs
= create_frag_shader(filter
, num_offsets
, offsets
, matrix_values
);
246 pipe
->delete_vs_state(pipe
, filter
->vs
);
252 pipe
->delete_vertex_elements_state(pipe
, filter
->ves
);
255 pipe_resource_reference(&filter
->quad
.buffer
, NULL
);
258 pipe
->delete_sampler_state(pipe
, filter
->sampler
);
261 pipe
->delete_blend_state(pipe
, filter
->blend
);
264 pipe
->delete_rasterizer_state(pipe
, filter
->rs_state
);
271 vl_matrix_filter_cleanup(struct vl_matrix_filter
*filter
)
275 filter
->pipe
->delete_sampler_state(filter
->pipe
, filter
->sampler
);
276 filter
->pipe
->delete_blend_state(filter
->pipe
, filter
->blend
);
277 filter
->pipe
->delete_rasterizer_state(filter
->pipe
, filter
->rs_state
);
278 filter
->pipe
->delete_vertex_elements_state(filter
->pipe
, filter
->ves
);
279 pipe_resource_reference(&filter
->quad
.buffer
, NULL
);
281 filter
->pipe
->delete_vs_state(filter
->pipe
, filter
->vs
);
282 filter
->pipe
->delete_fs_state(filter
->pipe
, filter
->fs
);
286 vl_matrix_filter_render(struct vl_matrix_filter
*filter
,
287 struct pipe_sampler_view
*src
,
288 struct pipe_surface
*dst
)
290 struct pipe_viewport_state viewport
;
291 struct pipe_framebuffer_state fb_state
;
293 assert(filter
&& src
&& dst
);
295 memset(&viewport
, 0, sizeof(viewport
));
296 viewport
.scale
[0] = dst
->width
;
297 viewport
.scale
[1] = dst
->height
;
298 viewport
.scale
[2] = 1;
299 viewport
.scale
[3] = 1;
301 memset(&fb_state
, 0, sizeof(fb_state
));
302 fb_state
.width
= dst
->width
;
303 fb_state
.height
= dst
->height
;
304 fb_state
.nr_cbufs
= 1;
305 fb_state
.cbufs
[0] = dst
;
307 filter
->pipe
->bind_rasterizer_state(filter
->pipe
, filter
->rs_state
);
308 filter
->pipe
->bind_blend_state(filter
->pipe
, filter
->blend
);
309 filter
->pipe
->bind_sampler_states(filter
->pipe
, PIPE_SHADER_FRAGMENT
,
310 0, 1, &filter
->sampler
);
311 filter
->pipe
->set_fragment_sampler_views(filter
->pipe
, 1, &src
);
312 filter
->pipe
->bind_vs_state(filter
->pipe
, filter
->vs
);
313 filter
->pipe
->bind_fs_state(filter
->pipe
, filter
->fs
);
314 filter
->pipe
->set_framebuffer_state(filter
->pipe
, &fb_state
);
315 filter
->pipe
->set_viewport_states(filter
->pipe
, 0, 1, &viewport
);
316 filter
->pipe
->set_vertex_buffers(filter
->pipe
, 0, 1, &filter
->quad
);
317 filter
->pipe
->bind_vertex_elements_state(filter
->pipe
, filter
->ves
);
319 util_draw_arrays(filter
->pipe
, PIPE_PRIM_QUADS
, 0, 4);