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