2 * Copyright (C) 2010 Jorge Jimenez (jorge@iryoku.com)
3 * Copyright (C) 2010 Belen Masia (bmasia@unizar.es)
4 * Copyright (C) 2010 Jose I. Echevarria (joseignacioechevarria@gmail.com)
5 * Copyright (C) 2010 Fernando Navarro (fernandn@microsoft.com)
6 * Copyright (C) 2010 Diego Gutierrez (diegog@unizar.es)
7 * Copyright (C) 2011 Lauri Kasanen (cand@gmx.com)
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are met:
13 * 1. Redistributions of source code must retain the above copyright notice,
14 * this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the following statement:
18 * "Uses Jimenez's MLAA. Copyright (C) 2010 by Jorge Jimenez, Belen Masia,
19 * Jose I. Echevarria, Fernando Navarro and Diego Gutierrez."
21 * Only for use in the Mesa project, this point 2 is filled by naming the
22 * technique Jimenez's MLAA in the Mesa config options.
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
25 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
26 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
27 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS OR CONTRIBUTORS
28 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
36 * The views and conclusions contained in the software and documentation are
37 * those of the authors and should not be interpreted as representing official
38 * policies, either expressed or implied, of the copyright holders.
41 #include "pipe/p_compiler.h"
43 #include "postprocess/postprocess.h"
44 #include "postprocess/pp_mlaa.h"
45 #include "postprocess/pp_filters.h"
46 #include "util/u_blit.h"
47 #include "util/u_box.h"
48 #include "util/u_sampler.h"
49 #include "util/u_inlines.h"
50 #include "util/u_memory.h"
51 #include "util/u_string.h"
52 #include "pipe/p_screen.h"
56 static float constants
[] = { 1, 1, 0, 0 };
57 static unsigned int dimensions
[2] = { 0, 0 };
59 /** Upload the constants. */
61 up_consts(struct pp_queue_t
*ppq
)
63 struct pipe_context
*pipe
= ppq
->p
->pipe
;
66 u_box_2d(0, 0, sizeof(constants
), 1, &box
);
68 pipe
->transfer_inline_write(pipe
, ppq
->constbuf
, 0, PIPE_TRANSFER_WRITE
,
69 &box
, constants
, sizeof(constants
),
73 /** Run function of the MLAA filter. */
75 pp_jimenezmlaa_run(struct pp_queue_t
*ppq
, struct pipe_resource
*in
,
76 struct pipe_resource
*out
, unsigned int n
, bool iscolor
)
79 struct program
*p
= ppq
->p
;
81 struct pipe_depth_stencil_alpha_state mstencil
;
82 struct pipe_sampler_view v_tmp
, *arr
[3];
87 const struct pipe_stencil_ref ref
= { {1} };
89 /* Insufficient initialization checks. */
92 assert(ppq
->constbuf
);
93 assert(ppq
->areamaptex
);
94 assert(ppq
->inner_tmp
);
95 assert(ppq
->shaders
[n
]);
97 w
= p
->framebuffer
.width
;
98 h
= p
->framebuffer
.height
;
100 memset(&mstencil
, 0, sizeof(mstencil
));
102 cso_set_stencil_ref(p
->cso
, &ref
);
104 /* Init the pixel size constant */
105 if (dimensions
[0] != p
->framebuffer
.width
||
106 dimensions
[1] != p
->framebuffer
.height
) {
107 constants
[0] = 1.0f
/ p
->framebuffer
.width
;
108 constants
[1] = 1.0f
/ p
->framebuffer
.height
;
111 dimensions
[0] = p
->framebuffer
.width
;
112 dimensions
[1] = p
->framebuffer
.height
;
115 cso_set_constant_buffer_resource(p
->cso
, PIPE_SHADER_VERTEX
,
117 cso_set_constant_buffer_resource(p
->cso
, PIPE_SHADER_FRAGMENT
,
120 mstencil
.stencil
[0].enabled
= 1;
121 mstencil
.stencil
[0].valuemask
= mstencil
.stencil
[0].writemask
= ~0;
122 mstencil
.stencil
[0].func
= PIPE_FUNC_ALWAYS
;
123 mstencil
.stencil
[0].fail_op
= PIPE_STENCIL_OP_KEEP
;
124 mstencil
.stencil
[0].zfail_op
= PIPE_STENCIL_OP_KEEP
;
125 mstencil
.stencil
[0].zpass_op
= PIPE_STENCIL_OP_REPLACE
;
127 p
->framebuffer
.zsbuf
= ppq
->stencils
;
129 /* First pass: depth edge detection */
131 pp_filter_setup_in(p
, in
);
133 pp_filter_setup_in(p
, ppq
->depth
);
135 pp_filter_setup_out(p
, ppq
->inner_tmp
[0]);
138 pp_filter_misc_state(p
);
139 cso_set_depth_stencil_alpha(p
->cso
, &mstencil
);
140 p
->pipe
->clear(p
->pipe
, PIPE_CLEAR_STENCIL
| PIPE_CLEAR_COLOR
,
141 &p
->clear_color
, 0, 0);
143 cso_single_sampler(p
->cso
, PIPE_SHADER_FRAGMENT
, 0, &p
->sampler_point
);
144 cso_single_sampler_done(p
->cso
, PIPE_SHADER_FRAGMENT
);
145 cso_set_sampler_views(p
->cso
, PIPE_SHADER_FRAGMENT
, 1, &p
->view
);
147 cso_set_vertex_shader_handle(p
->cso
, ppq
->shaders
[n
][1]); /* offsetvs */
148 cso_set_fragment_shader_handle(p
->cso
, ppq
->shaders
[n
][2]);
151 pp_filter_end_pass(p
);
154 /* Second pass: blend weights */
155 /* Sampler order: areamap, edgesmap, edgesmapL (reversed, thx compiler) */
156 mstencil
.stencil
[0].func
= PIPE_FUNC_EQUAL
;
157 mstencil
.stencil
[0].zpass_op
= PIPE_STENCIL_OP_KEEP
;
158 cso_set_depth_stencil_alpha(p
->cso
, &mstencil
);
160 pp_filter_setup_in(p
, ppq
->areamaptex
);
161 pp_filter_setup_out(p
, ppq
->inner_tmp
[1]);
163 u_sampler_view_default_template(&v_tmp
, ppq
->inner_tmp
[0],
164 ppq
->inner_tmp
[0]->format
);
165 arr
[1] = arr
[2] = p
->pipe
->create_sampler_view(p
->pipe
,
166 ppq
->inner_tmp
[0], &v_tmp
);
168 pp_filter_set_clear_fb(p
);
170 cso_single_sampler(p
->cso
, PIPE_SHADER_FRAGMENT
, 0, &p
->sampler_point
);
171 cso_single_sampler(p
->cso
, PIPE_SHADER_FRAGMENT
, 1, &p
->sampler_point
);
172 cso_single_sampler(p
->cso
, PIPE_SHADER_FRAGMENT
, 2, &p
->sampler
);
173 cso_single_sampler_done(p
->cso
, PIPE_SHADER_FRAGMENT
);
176 cso_set_sampler_views(p
->cso
, PIPE_SHADER_FRAGMENT
, 3, arr
);
178 cso_set_vertex_shader_handle(p
->cso
, ppq
->shaders
[n
][0]); /* passvs */
179 cso_set_fragment_shader_handle(p
->cso
, ppq
->shaders
[n
][3]);
182 pp_filter_end_pass(p
);
183 pipe_sampler_view_reference(&arr
[1], NULL
);
186 /* Third pass: smoothed edges */
187 /* Sampler order: colormap, blendmap (wtf compiler) */
188 pp_filter_setup_in(p
, ppq
->inner_tmp
[1]);
189 pp_filter_setup_out(p
, out
);
193 /* Blit the input to the output */
194 util_blit_pixels(p
->blitctx
, in
, 0, 0, 0,
195 w
, h
, 0, p
->framebuffer
.cbufs
[0],
196 0, 0, w
, h
, 0, PIPE_TEX_MIPFILTER_NEAREST
,
197 TGSI_WRITEMASK_XYZW
, 0);
199 u_sampler_view_default_template(&v_tmp
, in
, in
->format
);
200 arr
[0] = p
->pipe
->create_sampler_view(p
->pipe
, in
, &v_tmp
);
202 cso_single_sampler(p
->cso
, PIPE_SHADER_FRAGMENT
, 0, &p
->sampler_point
);
203 cso_single_sampler(p
->cso
, PIPE_SHADER_FRAGMENT
, 1, &p
->sampler_point
);
204 cso_single_sampler_done(p
->cso
, PIPE_SHADER_FRAGMENT
);
207 cso_set_sampler_views(p
->cso
, PIPE_SHADER_FRAGMENT
, 2, arr
);
209 cso_set_vertex_shader_handle(p
->cso
, ppq
->shaders
[n
][1]); /* offsetvs */
210 cso_set_fragment_shader_handle(p
->cso
, ppq
->shaders
[n
][4]);
212 p
->blend
.rt
[0].blend_enable
= 1;
213 cso_set_blend(p
->cso
, &p
->blend
);
216 pp_filter_end_pass(p
);
217 pipe_sampler_view_reference(&arr
[0], NULL
);
219 p
->blend
.rt
[0].blend_enable
= 0;
220 p
->framebuffer
.zsbuf
= NULL
;
223 /** The init function of the MLAA filter. */
225 pp_jimenezmlaa_init_run(struct pp_queue_t
*ppq
, unsigned int n
,
226 unsigned int val
, bool iscolor
)
230 struct pipe_resource res
;
231 char *tmp_text
= NULL
;
233 tmp_text
= CALLOC(sizeof(blend2fs_1
) + sizeof(blend2fs_2
) +
234 IMM_SPACE
, sizeof(char));
236 if (tmp_text
== NULL
) {
237 pp_debug("Failed to allocate shader space\n");
241 ppq
->constbuf
= pipe_buffer_create(ppq
->p
->screen
,
242 PIPE_BIND_CONSTANT_BUFFER
,
245 if (ppq
->constbuf
== NULL
) {
246 pp_debug("Failed to allocate constant buffer\n");
250 pp_debug("mlaa: using %u max search steps\n", val
);
252 util_sprintf(tmp_text
, "%s"
253 "IMM FLT32 { %.8f, 0.0000, 0.0000, 0.0000}\n"
254 "%s\n", blend2fs_1
, (float) val
, blend2fs_2
);
256 memset(&res
, 0, sizeof(res
));
258 res
.target
= PIPE_TEXTURE_2D
;
259 res
.format
= PIPE_FORMAT_R8G8_UNORM
;
260 res
.width0
= res
.height0
= 165;
261 res
.bind
= PIPE_BIND_SAMPLER_VIEW
;
262 res
.usage
= PIPE_USAGE_STATIC
;
263 res
.depth0
= res
.array_size
= res
.nr_samples
= 1;
265 if (!ppq
->p
->screen
->is_format_supported(ppq
->p
->screen
, res
.format
,
266 res
.target
, 1, res
.bind
))
267 pp_debug("Areamap format not supported\n");
269 ppq
->areamaptex
= ppq
->p
->screen
->resource_create(ppq
->p
->screen
, &res
);
271 if (ppq
->areamaptex
== NULL
) {
272 pp_debug("Failed to allocate area map texture\n");
276 u_box_2d(0, 0, 165, 165, &box
);
278 ppq
->p
->pipe
->transfer_inline_write(ppq
->p
->pipe
, ppq
->areamaptex
, 0,
279 PIPE_TRANSFER_WRITE
, &box
,
280 areamap
, 165 * 2, sizeof(areamap
));
282 ppq
->shaders
[n
][1] = pp_tgsi_to_state(ppq
->p
->pipe
, offsetvs
, true,
285 ppq
->shaders
[n
][2] = pp_tgsi_to_state(ppq
->p
->pipe
, color1fs
,
288 ppq
->shaders
[n
][2] = pp_tgsi_to_state(ppq
->p
->pipe
, depth1fs
,
290 ppq
->shaders
[n
][3] = pp_tgsi_to_state(ppq
->p
->pipe
, tmp_text
, false,
292 ppq
->shaders
[n
][4] = pp_tgsi_to_state(ppq
->p
->pipe
, neigh3fs
, false,
304 * Call the common free function for destruction of partially initialized
307 pp_jimenezmlaa_free(ppq
, n
);
312 /** Short wrapper to init the depth version. */
314 pp_jimenezmlaa_init(struct pp_queue_t
*ppq
, unsigned int n
, unsigned int val
)
316 return pp_jimenezmlaa_init_run(ppq
, n
, val
, false);
319 /** Short wrapper to init the color version. */
321 pp_jimenezmlaa_init_color(struct pp_queue_t
*ppq
, unsigned int n
,
324 return pp_jimenezmlaa_init_run(ppq
, n
, val
, true);
327 /** Short wrapper to run the depth version. */
329 pp_jimenezmlaa(struct pp_queue_t
*ppq
, struct pipe_resource
*in
,
330 struct pipe_resource
*out
, unsigned int n
)
332 pp_jimenezmlaa_run(ppq
, in
, out
, n
, false);
335 /** Short wrapper to run the color version. */
337 pp_jimenezmlaa_color(struct pp_queue_t
*ppq
, struct pipe_resource
*in
,
338 struct pipe_resource
*out
, unsigned int n
)
340 pp_jimenezmlaa_run(ppq
, in
, out
, n
, true);
345 * Short wrapper to free the mlaa filter resources. Shaders are freed in
346 * the common code in pp_free.
349 pp_jimenezmlaa_free(struct pp_queue_t
*ppq
, unsigned int n
)
351 if (ppq
->areamaptex
) {
352 ppq
->p
->screen
->resource_destroy(ppq
->p
->screen
, ppq
->areamaptex
);
353 ppq
->areamaptex
= NULL
;
357 ppq
->p
->screen
->resource_destroy(ppq
->p
->screen
, ppq
->constbuf
);
358 ppq
->constbuf
= NULL
;