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 OR COPYRIGHT HOLDERS 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 #include "postprocess/pp_filters.h"
     30 #include "postprocess/pp_private.h"
     31 
     32 #include "util/u_inlines.h"
     33 #include "util/u_sampler.h"
     34 
     35 #include "tgsi/tgsi_parse.h"
     36 
     37 
     38 void
     39 pp_blit(struct pipe_context *pipe,
     40         struct pipe_resource *src_tex,
     41         int srcX0, int srcY0,
     42         int srcX1, int srcY1,
     43         int srcZ0,
     44         struct pipe_surface *dst,
     45         int dstX0, int dstY0,
     46         int dstX1, int dstY1)
     47 {
     48    struct pipe_blit_info blit;
     49 
     50    memset(&blit, 0, sizeof(blit));
     51 
     52    blit.src.resource = src_tex;
     53    blit.src.level = 0;
     54    blit.src.format = src_tex->format;
     55    blit.src.box.x = srcX0;
     56    blit.src.box.y = srcY0;
     57    blit.src.box.z = srcZ0;
     58    blit.src.box.width = srcX1 - srcX0;
     59    blit.src.box.height = srcY1 - srcY0;
     60    blit.src.box.depth = 1;
     61 
     62    blit.dst.resource = dst->texture;
     63    blit.dst.level = dst->u.tex.level;
     64    blit.dst.format = dst->format;
     65    blit.dst.box.x = dstX0;
     66    blit.dst.box.y = dstY0;
     67    blit.dst.box.z = 0;
     68    blit.dst.box.width = dstX1 - dstX0;
     69    blit.dst.box.height = dstY1 - dstY0;
     70    blit.dst.box.depth = 1;
     71 
     72    blit.mask = PIPE_MASK_RGBA;
     73 
     74    pipe->blit(pipe, &blit);
     75 }
     76 
     77 /**
     78 *	Main run function of the PP queue. Called on swapbuffers/flush.
     79 *
     80 *	Runs all requested filters in order and handles shuffling the temp
     81 *	buffers in between.
     82 */
     83 void
     84 pp_run(struct pp_queue_t *ppq, struct pipe_resource *in,
     85        struct pipe_resource *out, struct pipe_resource *indepth)
     86 {
     87    struct pipe_resource *refin = NULL, *refout = NULL;
     88    unsigned int i;
     89    struct cso_context *cso = ppq->p->cso;
     90 
     91    if (ppq->n_filters == 0)
     92       return;
     93 
     94    assert(ppq->pp_queue);
     95    assert(ppq->tmp[0]);
     96 
     97    if (in->width0 != ppq->p->framebuffer.width ||
     98        in->height0 != ppq->p->framebuffer.height) {
     99       pp_debug("Resizing the temp pp buffers\n");
    100       pp_free_fbos(ppq);
    101       pp_init_fbos(ppq, in->width0, in->height0);
    102    }
    103 
    104    if (in == out && ppq->n_filters == 1) {
    105       /* Make a copy of in to tmp[0] in this case. */
    106       unsigned int w = ppq->p->framebuffer.width;
    107       unsigned int h = ppq->p->framebuffer.height;
    108 
    109 
    110       pp_blit(ppq->p->pipe, in, 0, 0,
    111               w, h, 0, ppq->tmps[0],
    112               0, 0, w, h);
    113 
    114       in = ppq->tmp[0];
    115    }
    116 
    117    /* save state (restored below) */
    118    cso_save_state(cso, (CSO_BIT_BLEND |
    119                         CSO_BIT_DEPTH_STENCIL_ALPHA |
    120                         CSO_BIT_FRAGMENT_SHADER |
    121                         CSO_BIT_FRAMEBUFFER |
    122                         CSO_BIT_TESSCTRL_SHADER |
    123                         CSO_BIT_TESSEVAL_SHADER |
    124                         CSO_BIT_GEOMETRY_SHADER |
    125                         CSO_BIT_RASTERIZER |
    126                         CSO_BIT_SAMPLE_MASK |
    127                         CSO_BIT_MIN_SAMPLES |
    128                         CSO_BIT_FRAGMENT_SAMPLERS |
    129                         CSO_BIT_FRAGMENT_SAMPLER_VIEWS |
    130                         CSO_BIT_STENCIL_REF |
    131                         CSO_BIT_STREAM_OUTPUTS |
    132                         CSO_BIT_VERTEX_ELEMENTS |
    133                         CSO_BIT_VERTEX_SHADER |
    134                         CSO_BIT_VIEWPORT |
    135                         CSO_BIT_AUX_VERTEX_BUFFER_SLOT |
    136                         CSO_BIT_PAUSE_QUERIES |
    137                         CSO_BIT_RENDER_CONDITION));
    138    cso_save_constant_buffer_slot0(cso, PIPE_SHADER_VERTEX);
    139    cso_save_constant_buffer_slot0(cso, PIPE_SHADER_FRAGMENT);
    140 
    141    /* set default state */
    142    cso_set_sample_mask(cso, ~0);
    143    cso_set_min_samples(cso, 1);
    144    cso_set_stream_outputs(cso, 0, NULL, NULL);
    145    cso_set_tessctrl_shader_handle(cso, NULL);
    146    cso_set_tesseval_shader_handle(cso, NULL);
    147    cso_set_geometry_shader_handle(cso, NULL);
    148    cso_set_render_condition(cso, NULL, FALSE, 0);
    149 
    150    // Kept only for this frame.
    151    pipe_resource_reference(&ppq->depth, indepth);
    152    pipe_resource_reference(&refin, in);
    153    pipe_resource_reference(&refout, out);
    154 
    155    switch (ppq->n_filters) {
    156    case 0:
    157       /* Failsafe, but never reached. */
    158       break;
    159    case 1:                     /* No temp buf */
    160       ppq->pp_queue[0] (ppq, in, out, 0);
    161       break;
    162    case 2:                     /* One temp buf */
    163 
    164       ppq->pp_queue[0] (ppq, in, ppq->tmp[0], 0);
    165       ppq->pp_queue[1] (ppq, ppq->tmp[0], out, 1);
    166 
    167       break;
    168    default:                    /* Two temp bufs */
    169       assert(ppq->tmp[1]);
    170       ppq->pp_queue[0] (ppq, in, ppq->tmp[0], 0);
    171 
    172       for (i = 1; i < (ppq->n_filters - 1); i++) {
    173          if (i % 2 == 0)
    174             ppq->pp_queue[i] (ppq, ppq->tmp[1], ppq->tmp[0], i);
    175 
    176          else
    177             ppq->pp_queue[i] (ppq, ppq->tmp[0], ppq->tmp[1], i);
    178       }
    179 
    180       if (i % 2 == 0)
    181          ppq->pp_queue[i] (ppq, ppq->tmp[1], out, i);
    182 
    183       else
    184          ppq->pp_queue[i] (ppq, ppq->tmp[0], out, i);
    185 
    186       break;
    187    }
    188 
    189    /* restore state we changed */
    190    cso_restore_state(cso);
    191    cso_restore_constant_buffer_slot0(cso, PIPE_SHADER_VERTEX);
    192    cso_restore_constant_buffer_slot0(cso, PIPE_SHADER_FRAGMENT);
    193 
    194    pipe_resource_reference(&ppq->depth, NULL);
    195    pipe_resource_reference(&refin, NULL);
    196    pipe_resource_reference(&refout, NULL);
    197 }
    198 
    199 
    200 /* Utility functions for the filters. You're not forced to use these if */
    201 /* your filter is more complicated. */
    202 
    203 /** Setup this resource as the filter input. */
    204 void
    205 pp_filter_setup_in(struct pp_program *p, struct pipe_resource *in)
    206 {
    207    struct pipe_sampler_view v_tmp;
    208    u_sampler_view_default_template(&v_tmp, in, in->format);
    209    p->view = p->pipe->create_sampler_view(p->pipe, in, &v_tmp);
    210 }
    211 
    212 /** Setup this resource as the filter output. */
    213 void
    214 pp_filter_setup_out(struct pp_program *p, struct pipe_resource *out)
    215 {
    216    p->surf.format = out->format;
    217 
    218    p->framebuffer.cbufs[0] = p->pipe->create_surface(p->pipe, out, &p->surf);
    219 }
    220 
    221 /** Clean up the input and output set with the above. */
    222 void
    223 pp_filter_end_pass(struct pp_program *p)
    224 {
    225    pipe_surface_reference(&p->framebuffer.cbufs[0], NULL);
    226    pipe_sampler_view_reference(&p->view, NULL);
    227 }
    228 
    229 /**
    230 *	Convert the TGSI assembly to a runnable shader.
    231 *
    232 * We need not care about geometry shaders. All we have is screen quads.
    233 */
    234 void *
    235 pp_tgsi_to_state(struct pipe_context *pipe, const char *text, bool isvs,
    236                  const char *name)
    237 {
    238    struct pipe_shader_state state;
    239    struct tgsi_token *tokens = NULL;
    240    void *ret_state = NULL;
    241 
    242    /*
    243     * Allocate temporary token storage. State creation will duplicate
    244     * tokens so we must free them on exit.
    245     */
    246    tokens = tgsi_alloc_tokens(PP_MAX_TOKENS);
    247 
    248    if (!tokens) {
    249       pp_debug("Failed to allocate temporary token storage.\n");
    250       return NULL;
    251    }
    252 
    253    if (tgsi_text_translate(text, tokens, PP_MAX_TOKENS) == FALSE) {
    254       _debug_printf("pp: Failed to translate a shader for %s\n", name);
    255       return NULL;
    256    }
    257 
    258    pipe_shader_state_from_tgsi(&state, tokens);
    259 
    260    if (isvs) {
    261       ret_state = pipe->create_vs_state(pipe, &state);
    262       FREE(tokens);
    263    } else {
    264       ret_state = pipe->create_fs_state(pipe, &state);
    265       FREE(tokens);
    266    }
    267 
    268    return ret_state;
    269 }
    270 
    271 /** Setup misc state for the filter. */
    272 void
    273 pp_filter_misc_state(struct pp_program *p)
    274 {
    275    cso_set_blend(p->cso, &p->blend);
    276    cso_set_depth_stencil_alpha(p->cso, &p->depthstencil);
    277    cso_set_rasterizer(p->cso, &p->rasterizer);
    278    cso_set_viewport(p->cso, &p->viewport);
    279 
    280    cso_set_vertex_elements(p->cso, 2, p->velem);
    281 }
    282 
    283 /** Draw with the filter to the set output. */
    284 void
    285 pp_filter_draw(struct pp_program *p)
    286 {
    287    util_draw_vertex_buffer(p->pipe, p->cso, p->vbuf, 0, 0,
    288                            PIPE_PRIM_QUADS, 4, 2);
    289 }
    290 
    291 /** Set the framebuffer as active. */
    292 void
    293 pp_filter_set_fb(struct pp_program *p)
    294 {
    295    cso_set_framebuffer(p->cso, &p->framebuffer);
    296 }
    297 
    298 /** Set the framebuffer as active and clear it. */
    299 void
    300 pp_filter_set_clear_fb(struct pp_program *p)
    301 {
    302    cso_set_framebuffer(p->cso, &p->framebuffer);
    303    p->pipe->clear(p->pipe, PIPE_CLEAR_COLOR0, &p->clear_color, 0, 0);
    304 }
    305