• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
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)
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions are met:
12  *
13  *    1. Redistributions of source code must retain the above copyright notice,
14  *       this list of conditions and the following disclaimer.
15  *
16  *    2. Redistributions in binary form must reproduce the following statement:
17  *
18  *       "Uses Jimenez's MLAA. Copyright (C) 2010 by Jorge Jimenez, Belen Masia,
19  *        Jose I. Echevarria, Fernando Navarro and Diego Gutierrez."
20  *
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.
23  *
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.
35  *
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.
39  */
40 
41 #include "pipe/p_compiler.h"
42 
43 #include "postprocess/postprocess.h"
44 #include "postprocess/pp_mlaa.h"
45 #include "postprocess/pp_filters.h"
46 #include "postprocess/pp_private.h"
47 
48 #include "util/u_box.h"
49 #include "util/u_sampler.h"
50 #include "util/u_inlines.h"
51 #include "util/u_memory.h"
52 #include "util/u_string.h"
53 #include "pipe/p_screen.h"
54 
55 #define IMM_SPACE 80
56 
57 static float constants[] = { 1, 1, 0, 0 };
58 static unsigned int dimensions[2] = { 0, 0 };
59 
60 /** Upload the constants. */
61 static void
up_consts(struct pp_queue_t * ppq)62 up_consts(struct pp_queue_t *ppq)
63 {
64    struct pipe_context *pipe = ppq->p->pipe;
65 
66    pipe->buffer_subdata(pipe, ppq->constbuf, PIPE_TRANSFER_WRITE,
67                         0, sizeof(constants), constants);
68 }
69 
70 /** Run function of the MLAA filter. */
71 static void
pp_jimenezmlaa_run(struct pp_queue_t * ppq,struct pipe_resource * in,struct pipe_resource * out,unsigned int n,bool iscolor)72 pp_jimenezmlaa_run(struct pp_queue_t *ppq, struct pipe_resource *in,
73                    struct pipe_resource *out, unsigned int n, bool iscolor)
74 {
75 
76    struct pp_program *p = ppq->p;
77 
78    struct pipe_depth_stencil_alpha_state mstencil;
79    struct pipe_sampler_view v_tmp, *arr[3];
80 
81    unsigned int w = 0;
82    unsigned int h = 0;
83 
84    const struct pipe_stencil_ref ref = { {1} };
85 
86    /* Insufficient initialization checks. */
87    assert(p);
88    assert(ppq);
89    assert(ppq->constbuf);
90    assert(ppq->areamaptex);
91    assert(ppq->inner_tmp);
92    assert(ppq->shaders[n]);
93 
94    w = p->framebuffer.width;
95    h = p->framebuffer.height;
96 
97    memset(&mstencil, 0, sizeof(mstencil));
98 
99    cso_set_stencil_ref(p->cso, &ref);
100 
101    /* Init the pixel size constant */
102    if (dimensions[0] != p->framebuffer.width ||
103        dimensions[1] != p->framebuffer.height) {
104       constants[0] = 1.0f / p->framebuffer.width;
105       constants[1] = 1.0f / p->framebuffer.height;
106 
107       up_consts(ppq);
108       dimensions[0] = p->framebuffer.width;
109       dimensions[1] = p->framebuffer.height;
110    }
111 
112    cso_set_constant_buffer_resource(p->cso, PIPE_SHADER_VERTEX,
113                                     0, ppq->constbuf);
114    cso_set_constant_buffer_resource(p->cso, PIPE_SHADER_FRAGMENT,
115                                     0, ppq->constbuf);
116 
117    mstencil.stencil[0].enabled = 1;
118    mstencil.stencil[0].valuemask = mstencil.stencil[0].writemask = ~0;
119    mstencil.stencil[0].func = PIPE_FUNC_ALWAYS;
120    mstencil.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
121    mstencil.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
122    mstencil.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
123 
124    p->framebuffer.zsbuf = ppq->stencils;
125 
126    /* First pass: depth edge detection */
127    if (iscolor)
128       pp_filter_setup_in(p, in);
129    else
130       pp_filter_setup_in(p, ppq->depth);
131 
132    pp_filter_setup_out(p, ppq->inner_tmp[0]);
133 
134    pp_filter_set_fb(p);
135    pp_filter_misc_state(p);
136    cso_set_depth_stencil_alpha(p->cso, &mstencil);
137    p->pipe->clear(p->pipe, PIPE_CLEAR_STENCIL | PIPE_CLEAR_COLOR0,
138                   &p->clear_color, 0, 0);
139 
140    {
141       const struct pipe_sampler_state *samplers[] = {&p->sampler_point};
142       cso_set_samplers(p->cso, PIPE_SHADER_FRAGMENT, 1, samplers);
143    }
144    cso_set_sampler_views(p->cso, PIPE_SHADER_FRAGMENT, 1, &p->view);
145 
146    cso_set_vertex_shader_handle(p->cso, ppq->shaders[n][1]);    /* offsetvs */
147    cso_set_fragment_shader_handle(p->cso, ppq->shaders[n][2]);
148 
149    pp_filter_draw(p);
150    pp_filter_end_pass(p);
151 
152 
153    /* Second pass: blend weights */
154    /* Sampler order: areamap, edgesmap, edgesmapL (reversed, thx compiler) */
155    mstencil.stencil[0].func = PIPE_FUNC_EQUAL;
156    mstencil.stencil[0].zpass_op = PIPE_STENCIL_OP_KEEP;
157    cso_set_depth_stencil_alpha(p->cso, &mstencil);
158 
159    pp_filter_setup_in(p, ppq->areamaptex);
160    pp_filter_setup_out(p, ppq->inner_tmp[1]);
161 
162    u_sampler_view_default_template(&v_tmp, ppq->inner_tmp[0],
163                                    ppq->inner_tmp[0]->format);
164    arr[1] = arr[2] = p->pipe->create_sampler_view(p->pipe,
165                                                   ppq->inner_tmp[0], &v_tmp);
166 
167    pp_filter_set_clear_fb(p);
168 
169    {
170       const struct pipe_sampler_state *samplers[] =
171          {&p->sampler_point, &p->sampler_point, &p->sampler};
172       cso_set_samplers(p->cso, PIPE_SHADER_FRAGMENT, 3, samplers);
173    }
174 
175    arr[0] = p->view;
176    cso_set_sampler_views(p->cso, PIPE_SHADER_FRAGMENT, 3, arr);
177 
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]);
180 
181    pp_filter_draw(p);
182    pp_filter_end_pass(p);
183    pipe_sampler_view_reference(&arr[1], NULL);
184 
185 
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);
190 
191    pp_filter_set_fb(p);
192 
193    /* Blit the input to the output */
194    pp_blit(p->pipe, in, 0, 0,
195            w, h, 0, p->framebuffer.cbufs[0],
196            0, 0, w, h);
197 
198    u_sampler_view_default_template(&v_tmp, in, in->format);
199    arr[0] = p->pipe->create_sampler_view(p->pipe, in, &v_tmp);
200 
201    {
202       const struct pipe_sampler_state *samplers[] =
203          {&p->sampler_point, &p->sampler_point};
204       cso_set_samplers(p->cso, PIPE_SHADER_FRAGMENT, 2, samplers);
205    }
206 
207    arr[1] = p->view;
208    cso_set_sampler_views(p->cso, PIPE_SHADER_FRAGMENT, 2, arr);
209 
210    cso_set_vertex_shader_handle(p->cso, ppq->shaders[n][1]);    /* offsetvs */
211    cso_set_fragment_shader_handle(p->cso, ppq->shaders[n][4]);
212 
213    p->blend.rt[0].blend_enable = 1;
214    cso_set_blend(p->cso, &p->blend);
215 
216    pp_filter_draw(p);
217    pp_filter_end_pass(p);
218    pipe_sampler_view_reference(&arr[0], NULL);
219 
220    p->blend.rt[0].blend_enable = 0;
221    p->framebuffer.zsbuf = NULL;
222 }
223 
224 /** The init function of the MLAA filter. */
225 static bool
pp_jimenezmlaa_init_run(struct pp_queue_t * ppq,unsigned int n,unsigned int val,bool iscolor)226 pp_jimenezmlaa_init_run(struct pp_queue_t *ppq, unsigned int n,
227                         unsigned int val, bool iscolor)
228 {
229 
230    struct pipe_box box;
231    struct pipe_resource res;
232    char *tmp_text = NULL;
233 
234    tmp_text = CALLOC(sizeof(blend2fs_1) + sizeof(blend2fs_2) +
235                      IMM_SPACE, sizeof(char));
236 
237    if (!tmp_text) {
238       pp_debug("Failed to allocate shader space\n");
239       return FALSE;
240    }
241 
242    ppq->constbuf = pipe_buffer_create(ppq->p->screen,
243                                       PIPE_BIND_CONSTANT_BUFFER,
244                                       PIPE_USAGE_DEFAULT,
245                                       sizeof(constants));
246    if (ppq->constbuf == NULL) {
247       pp_debug("Failed to allocate constant buffer\n");
248       goto fail;
249    }
250 
251    pp_debug("mlaa: using %u max search steps\n", val);
252 
253    util_sprintf(tmp_text, "%s"
254                 "IMM FLT32 {    %.8f,     0.0000,     0.0000,     0.0000}\n"
255                 "%s\n", blend2fs_1, (float) val, blend2fs_2);
256 
257    memset(&res, 0, sizeof(res));
258 
259    res.target = PIPE_TEXTURE_2D;
260    res.format = PIPE_FORMAT_R8G8_UNORM;
261    res.width0 = res.height0 = 165;
262    res.bind = PIPE_BIND_SAMPLER_VIEW;
263    res.usage = PIPE_USAGE_DEFAULT;
264    res.depth0 = res.array_size = res.nr_samples = 1;
265 
266    if (!ppq->p->screen->is_format_supported(ppq->p->screen, res.format,
267                                             res.target, 1, res.bind))
268       pp_debug("Areamap format not supported\n");
269 
270    ppq->areamaptex = ppq->p->screen->resource_create(ppq->p->screen, &res);
271 
272    if (ppq->areamaptex == NULL) {
273       pp_debug("Failed to allocate area map texture\n");
274       goto fail;
275    }
276 
277    u_box_2d(0, 0, 165, 165, &box);
278 
279    ppq->p->pipe->texture_subdata(ppq->p->pipe, ppq->areamaptex, 0,
280                                  PIPE_TRANSFER_WRITE, &box,
281                                  areamap, 165 * 2, sizeof(areamap));
282 
283    ppq->shaders[n][1] = pp_tgsi_to_state(ppq->p->pipe, offsetvs, true,
284                                          "offsetvs");
285    if (iscolor)
286       ppq->shaders[n][2] = pp_tgsi_to_state(ppq->p->pipe, color1fs,
287                                             false, "color1fs");
288    else
289       ppq->shaders[n][2] = pp_tgsi_to_state(ppq->p->pipe, depth1fs,
290                                             false, "depth1fs");
291    ppq->shaders[n][3] = pp_tgsi_to_state(ppq->p->pipe, tmp_text, false,
292                                          "blend2fs");
293    ppq->shaders[n][4] = pp_tgsi_to_state(ppq->p->pipe, neigh3fs, false,
294                                          "neigh3fs");
295 
296    FREE(tmp_text);
297 
298    return TRUE;
299 
300  fail:
301 
302    FREE(tmp_text);
303 
304    /*
305     * Call the common free function for destruction of partially initialized
306     * resources.
307     */
308    pp_jimenezmlaa_free(ppq, n);
309 
310    return FALSE;
311 }
312 
313 /** Short wrapper to init the depth version. */
314 bool
pp_jimenezmlaa_init(struct pp_queue_t * ppq,unsigned int n,unsigned int val)315 pp_jimenezmlaa_init(struct pp_queue_t *ppq, unsigned int n, unsigned int val)
316 {
317    return pp_jimenezmlaa_init_run(ppq, n, val, false);
318 }
319 
320 /** Short wrapper to init the color version. */
321 bool
pp_jimenezmlaa_init_color(struct pp_queue_t * ppq,unsigned int n,unsigned int val)322 pp_jimenezmlaa_init_color(struct pp_queue_t *ppq, unsigned int n,
323                           unsigned int val)
324 {
325    return pp_jimenezmlaa_init_run(ppq, n, val, true);
326 }
327 
328 /** Short wrapper to run the depth version. */
329 void
pp_jimenezmlaa(struct pp_queue_t * ppq,struct pipe_resource * in,struct pipe_resource * out,unsigned int n)330 pp_jimenezmlaa(struct pp_queue_t *ppq, struct pipe_resource *in,
331                struct pipe_resource *out, unsigned int n)
332 {
333    if (!ppq->depth) {
334       return;
335    }
336    pp_jimenezmlaa_run(ppq, in, out, n, false);
337 }
338 
339 /** Short wrapper to run the color version. */
340 void
pp_jimenezmlaa_color(struct pp_queue_t * ppq,struct pipe_resource * in,struct pipe_resource * out,unsigned int n)341 pp_jimenezmlaa_color(struct pp_queue_t *ppq, struct pipe_resource *in,
342                      struct pipe_resource *out, unsigned int n)
343 {
344    pp_jimenezmlaa_run(ppq, in, out, n, true);
345 }
346 
347 
348 /**
349  * Short wrapper to free the mlaa filter resources. Shaders are freed in
350  * the common code in pp_free.
351  */
352 void
pp_jimenezmlaa_free(struct pp_queue_t * ppq,unsigned int n)353 pp_jimenezmlaa_free(struct pp_queue_t *ppq, unsigned int n)
354 {
355    if (ppq->areamaptex) {
356       pipe_resource_reference(&ppq->areamaptex, NULL);
357    }
358 
359    if (ppq->constbuf) {
360       pipe_resource_reference(&ppq->constbuf, NULL);
361    }
362 }
363 
364