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 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.
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(PIPE_SHADER_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
;
85 struct ureg_dst t_sum
;
86 struct ureg_dst o_fragment
;
89 shader
= ureg_create(PIPE_SHADER_FRAGMENT
);
94 i_vtex
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_VTEX
, TGSI_INTERPOLATE_LINEAR
);
95 sampler
= ureg_DECL_sampler(shader
, 0);
96 ureg_DECL_sampler_view(shader
, 0, TGSI_TEXTURE_2D
,
97 TGSI_RETURN_TYPE_FLOAT
,
98 TGSI_RETURN_TYPE_FLOAT
,
99 TGSI_RETURN_TYPE_FLOAT
,
100 TGSI_RETURN_TYPE_FLOAT
);
102 tmp
= ureg_DECL_temporary(shader
);
103 t_sum
= ureg_DECL_temporary(shader
);
104 o_fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
106 ureg_MOV(shader
, t_sum
, ureg_imm1f(shader
, 0.0f
));
107 for (i
= 0; i
< num_offsets
; ++i
) {
108 if (matrix_values
[i
] == 0.0f
)
111 if (!is_vec_zero(offsets
[i
])) {
112 ureg_ADD(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_XY
),
113 i_vtex
, ureg_imm2f(shader
, offsets
[i
].x
, offsets
[i
].y
));
114 ureg_MOV(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_ZW
),
115 ureg_imm1f(shader
, 0.0f
));
116 ureg_TEX(shader
, tmp
, TGSI_TEXTURE_2D
, ureg_src(tmp
), sampler
);
118 ureg_TEX(shader
, tmp
, TGSI_TEXTURE_2D
, i_vtex
, sampler
);
120 ureg_MAD(shader
, t_sum
, ureg_src(tmp
), ureg_imm1f(shader
, matrix_values
[i
]),
124 ureg_MOV(shader
, o_fragment
, ureg_src(t_sum
));
128 return ureg_create_shader_and_destroy(shader
, filter
->pipe
);
132 vl_matrix_filter_init(struct vl_matrix_filter
*filter
, struct pipe_context
*pipe
,
133 unsigned video_width
, unsigned video_height
,
134 unsigned matrix_width
, unsigned matrix_height
,
135 const float *matrix_values
)
137 struct pipe_rasterizer_state rs_state
;
138 struct pipe_blend_state blend
;
139 struct pipe_sampler_state sampler
;
140 struct pipe_vertex_element ve
;
141 struct vertex2f
*offsets
, v
, sizes
;
142 unsigned i
, num_offsets
= matrix_width
* matrix_height
;
144 assert(filter
&& pipe
);
145 assert(video_width
&& video_height
);
146 assert(matrix_width
&& matrix_height
);
148 memset(filter
, 0, sizeof(*filter
));
151 memset(&rs_state
, 0, sizeof(rs_state
));
152 rs_state
.half_pixel_center
= true;
153 rs_state
.bottom_edge_rule
= true;
154 rs_state
.depth_clip
= 1;
155 filter
->rs_state
= pipe
->create_rasterizer_state(pipe
, &rs_state
);
156 if (!filter
->rs_state
)
159 memset(&blend
, 0, sizeof blend
);
160 blend
.rt
[0].rgb_func
= PIPE_BLEND_ADD
;
161 blend
.rt
[0].rgb_src_factor
= PIPE_BLENDFACTOR_ONE
;
162 blend
.rt
[0].rgb_dst_factor
= PIPE_BLENDFACTOR_ONE
;
163 blend
.rt
[0].alpha_func
= PIPE_BLEND_ADD
;
164 blend
.rt
[0].alpha_src_factor
= PIPE_BLENDFACTOR_ONE
;
165 blend
.rt
[0].alpha_dst_factor
= PIPE_BLENDFACTOR_ONE
;
166 blend
.logicop_func
= PIPE_LOGICOP_CLEAR
;
167 blend
.rt
[0].colormask
= PIPE_MASK_RGBA
;
168 filter
->blend
= pipe
->create_blend_state(pipe
, &blend
);
172 memset(&sampler
, 0, sizeof(sampler
));
173 sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
174 sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
175 sampler
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
176 sampler
.min_img_filter
= PIPE_TEX_FILTER_NEAREST
;
177 sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
178 sampler
.mag_img_filter
= PIPE_TEX_FILTER_NEAREST
;
179 sampler
.compare_mode
= PIPE_TEX_COMPARE_NONE
;
180 sampler
.compare_func
= PIPE_FUNC_ALWAYS
;
181 sampler
.normalized_coords
= 1;
182 filter
->sampler
= pipe
->create_sampler_state(pipe
, &sampler
);
183 if (!filter
->sampler
)
186 filter
->quad
= vl_vb_upload_quads(pipe
);
187 if(!filter
->quad
.buffer
)
190 memset(&ve
, 0, sizeof(ve
));
192 ve
.instance_divisor
= 0;
193 ve
.vertex_buffer_index
= 0;
194 ve
.src_format
= PIPE_FORMAT_R32G32_FLOAT
;
195 filter
->ves
= pipe
->create_vertex_elements_state(pipe
, 1, &ve
);
199 offsets
= MALLOC(sizeof(struct vertex2f
) * num_offsets
);
203 sizes
.x
= (float)(matrix_width
- 1) / 2.0f
;
204 sizes
.y
= (float)(matrix_height
- 1) / 2.0f
;
206 for (v
.x
= -sizes
.x
, i
= 0; v
.x
<= sizes
.x
; v
.x
+= 1.0f
)
207 for (v
.y
= -sizes
.y
; v
.y
<= sizes
.y
; v
.y
+= 1.0f
)
210 for (i
= 0; i
< num_offsets
; ++i
) {
211 offsets
[i
].x
/= video_width
;
212 offsets
[i
].y
/= video_height
;
215 filter
->vs
= create_vert_shader(filter
);
219 filter
->fs
= create_frag_shader(filter
, num_offsets
, offsets
, matrix_values
);
227 pipe
->delete_vs_state(pipe
, filter
->vs
);
233 pipe
->delete_vertex_elements_state(pipe
, filter
->ves
);
236 pipe_resource_reference(&filter
->quad
.buffer
, NULL
);
239 pipe
->delete_sampler_state(pipe
, filter
->sampler
);
242 pipe
->delete_blend_state(pipe
, filter
->blend
);
245 pipe
->delete_rasterizer_state(pipe
, filter
->rs_state
);
252 vl_matrix_filter_cleanup(struct vl_matrix_filter
*filter
)
256 filter
->pipe
->delete_sampler_state(filter
->pipe
, filter
->sampler
);
257 filter
->pipe
->delete_blend_state(filter
->pipe
, filter
->blend
);
258 filter
->pipe
->delete_rasterizer_state(filter
->pipe
, filter
->rs_state
);
259 filter
->pipe
->delete_vertex_elements_state(filter
->pipe
, filter
->ves
);
260 pipe_resource_reference(&filter
->quad
.buffer
, NULL
);
262 filter
->pipe
->delete_vs_state(filter
->pipe
, filter
->vs
);
263 filter
->pipe
->delete_fs_state(filter
->pipe
, filter
->fs
);
267 vl_matrix_filter_render(struct vl_matrix_filter
*filter
,
268 struct pipe_sampler_view
*src
,
269 struct pipe_surface
*dst
)
271 struct pipe_viewport_state viewport
;
272 struct pipe_framebuffer_state fb_state
;
274 assert(filter
&& src
&& dst
);
276 memset(&viewport
, 0, sizeof(viewport
));
277 viewport
.scale
[0] = dst
->width
;
278 viewport
.scale
[1] = dst
->height
;
279 viewport
.scale
[2] = 1;
281 memset(&fb_state
, 0, sizeof(fb_state
));
282 fb_state
.width
= dst
->width
;
283 fb_state
.height
= dst
->height
;
284 fb_state
.nr_cbufs
= 1;
285 fb_state
.cbufs
[0] = dst
;
287 filter
->pipe
->bind_rasterizer_state(filter
->pipe
, filter
->rs_state
);
288 filter
->pipe
->bind_blend_state(filter
->pipe
, filter
->blend
);
289 filter
->pipe
->bind_sampler_states(filter
->pipe
, PIPE_SHADER_FRAGMENT
,
290 0, 1, &filter
->sampler
);
291 filter
->pipe
->set_sampler_views(filter
->pipe
, PIPE_SHADER_FRAGMENT
,
293 filter
->pipe
->bind_vs_state(filter
->pipe
, filter
->vs
);
294 filter
->pipe
->bind_fs_state(filter
->pipe
, filter
->fs
);
295 filter
->pipe
->set_framebuffer_state(filter
->pipe
, &fb_state
);
296 filter
->pipe
->set_viewport_states(filter
->pipe
, 0, 1, &viewport
);
297 filter
->pipe
->set_vertex_buffers(filter
->pipe
, 0, 1, &filter
->quad
);
298 filter
->pipe
->bind_vertex_elements_state(filter
->pipe
, filter
->ves
);
300 util_draw_arrays(filter
->pipe
, PIPE_PRIM_QUADS
, 0, 4);