Home | History | Annotate | Download | only in postprocess
      1 /**************************************************************************
      2  *
      3  * Copyright 2011 Lauri Kasanen
      4  * All Rights Reserved.
      5  *
      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:
     13  *
     14  * The above copyright notice and this permission notice (including the
     15  * next paragraph) shall be included in all copies or substantial portions
     16  * of the Software.
     17  *
     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 THE AUTHORS 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.
     25  *
     26  **************************************************************************/
     27 
     28 #include "postprocess.h"
     29 
     30 #include "postprocess/pp_filters.h"
     31 #include "util/u_blit.h"
     32 #include "util/u_inlines.h"
     33 #include "util/u_sampler.h"
     34 
     35 /**
     36 *	Main run function of the PP queue. Called on swapbuffers/flush.
     37 *
     38 *	Runs all requested filters in order and handles shuffling the temp
     39 *	buffers in between.
     40 */
     41 void
     42 pp_run(struct pp_queue_t *ppq, struct pipe_resource *in,
     43        struct pipe_resource *out, struct pipe_resource *indepth)
     44 {
     45    struct pipe_resource *refin = NULL, *refout = NULL;
     46    unsigned int i;
     47 
     48    if (in->width0 != ppq->p->framebuffer.width ||
     49        in->height0 != ppq->p->framebuffer.height) {
     50       pp_debug("Resizing the temp pp buffers\n");
     51       pp_free_fbos(ppq);
     52       pp_init_fbos(ppq, in->width0, in->height0);
     53    }
     54 
     55    if (in == out && ppq->n_filters == 1) {
     56       /* Make a copy of in to tmp[0] in this case. */
     57       unsigned int w = ppq->p->framebuffer.width;
     58       unsigned int h = ppq->p->framebuffer.height;
     59 
     60       util_blit_pixels(ppq->p->blitctx, in, 0, 0, 0,
     61                        w, h, 0, ppq->tmps[0],
     62                        0, 0, w, h, 0, PIPE_TEX_MIPFILTER_NEAREST,
     63                        TGSI_WRITEMASK_XYZW, 0);
     64 
     65       in = ppq->tmp[0];
     66    }
     67 
     68    // Kept only for this frame.
     69    pipe_resource_reference(&ppq->depth, indepth);
     70    pipe_resource_reference(&refin, in);
     71    pipe_resource_reference(&refout, out);
     72 
     73    switch (ppq->n_filters) {
     74    case 1:                     /* No temp buf */
     75       ppq->pp_queue[0] (ppq, in, out, 0);
     76       break;
     77    case 2:                     /* One temp buf */
     78 
     79       ppq->pp_queue[0] (ppq, in, ppq->tmp[0], 0);
     80       ppq->pp_queue[1] (ppq, ppq->tmp[0], out, 1);
     81 
     82       break;
     83    default:                    /* Two temp bufs */
     84       ppq->pp_queue[0] (ppq, in, ppq->tmp[0], 0);
     85 
     86       for (i = 1; i < (ppq->n_filters - 1); i++) {
     87          if (i % 2 == 0)
     88             ppq->pp_queue[i] (ppq, ppq->tmp[1], ppq->tmp[0], i);
     89 
     90          else
     91             ppq->pp_queue[i] (ppq, ppq->tmp[0], ppq->tmp[1], i);
     92       }
     93 
     94       if (i % 2 == 0)
     95          ppq->pp_queue[i] (ppq, ppq->tmp[1], out, i);
     96 
     97       else
     98          ppq->pp_queue[i] (ppq, ppq->tmp[0], out, i);
     99 
    100       break;
    101    }
    102 
    103    pipe_resource_reference(&ppq->depth, NULL);
    104    pipe_resource_reference(&refin, NULL);
    105    pipe_resource_reference(&refout, NULL);
    106 }
    107 
    108 
    109 /* Utility functions for the filters. You're not forced to use these if */
    110 /* your filter is more complicated. */
    111 
    112 /** Setup this resource as the filter input. */
    113 void
    114 pp_filter_setup_in(struct program *p, struct pipe_resource *in)
    115 {
    116    struct pipe_sampler_view v_tmp;
    117    u_sampler_view_default_template(&v_tmp, in, in->format);
    118    p->view = p->pipe->create_sampler_view(p->pipe, in, &v_tmp);
    119 }
    120 
    121 /** Setup this resource as the filter output. */
    122 void
    123 pp_filter_setup_out(struct program *p, struct pipe_resource *out)
    124 {
    125    p->surf.format = out->format;
    126    p->surf.usage = PIPE_BIND_RENDER_TARGET;
    127 
    128    p->framebuffer.cbufs[0] = p->pipe->create_surface(p->pipe, out, &p->surf);
    129 }
    130 
    131 /** Clean up the input and output set with the above. */
    132 void
    133 pp_filter_end_pass(struct program *p)
    134 {
    135    pipe_surface_reference(&p->framebuffer.cbufs[0], NULL);
    136    pipe_sampler_view_reference(&p->view, NULL);
    137 }
    138 
    139 /**
    140 *	Convert the TGSI assembly to a runnable shader.
    141 *
    142 * We need not care about geometry shaders. All we have is screen quads.
    143 */
    144 void *
    145 pp_tgsi_to_state(struct pipe_context *pipe, const char *text, bool isvs,
    146                  const char *name)
    147 {
    148    struct pipe_shader_state state;
    149    struct tgsi_token tokens[PP_MAX_TOKENS];
    150 
    151    if (tgsi_text_translate(text, tokens, Elements(tokens)) == FALSE) {
    152       pp_debug("Failed to translate %s\n", name);
    153       return NULL;
    154    }
    155 
    156    state.tokens = tokens;
    157    memset(&state.stream_output, 0, sizeof(state.stream_output));
    158 
    159    if (isvs)
    160       return pipe->create_vs_state(pipe, &state);
    161    else
    162       return pipe->create_fs_state(pipe, &state);
    163 }
    164 
    165 /** Setup misc state for the filter. */
    166 void
    167 pp_filter_misc_state(struct program *p)
    168 {
    169    cso_set_blend(p->cso, &p->blend);
    170    cso_set_depth_stencil_alpha(p->cso, &p->depthstencil);
    171    cso_set_rasterizer(p->cso, &p->rasterizer);
    172    cso_set_viewport(p->cso, &p->viewport);
    173 
    174    cso_set_vertex_elements(p->cso, 2, p->velem);
    175 }
    176 
    177 /** Draw with the filter to the set output. */
    178 void
    179 pp_filter_draw(struct program *p)
    180 {
    181    util_draw_vertex_buffer(p->pipe, p->cso, p->vbuf, 0,
    182                            PIPE_PRIM_QUADS, 4, 2);
    183    p->pipe->flush(p->pipe, NULL);
    184 }
    185 
    186 /** Set the framebuffer as active. */
    187 void
    188 pp_filter_set_fb(struct program *p)
    189 {
    190    cso_set_framebuffer(p->cso, &p->framebuffer);
    191 }
    192 
    193 /** Set the framebuffer as active and clear it. */
    194 void
    195 pp_filter_set_clear_fb(struct program *p)
    196 {
    197    cso_set_framebuffer(p->cso, &p->framebuffer);
    198    p->pipe->clear(p->pipe, PIPE_CLEAR_COLOR, &p->clear_color, 0, 0);
    199 }
    200