1848b8605Smrg/************************************************************************** 2848b8605Smrg * 3848b8605Smrg * Copyright 2011 Lauri Kasanen 4848b8605Smrg * All Rights Reserved. 5848b8605Smrg * 6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7848b8605Smrg * copy of this software and associated documentation files (the 8848b8605Smrg * "Software"), to deal in the Software without restriction, including 9848b8605Smrg * without limitation the rights to use, copy, modify, merge, publish, 10848b8605Smrg * distribute, sub license, and/or sell copies of the Software, and to 11848b8605Smrg * permit persons to whom the Software is furnished to do so, subject to 12848b8605Smrg * the following conditions: 13848b8605Smrg * 14848b8605Smrg * The above copyright notice and this permission notice (including the 15848b8605Smrg * next paragraph) shall be included in all copies or substantial portions 16848b8605Smrg * of the Software. 17848b8605Smrg * 18848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20848b8605Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21848b8605Smrg * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR 22848b8605Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23848b8605Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24848b8605Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25848b8605Smrg * 26848b8605Smrg **************************************************************************/ 27848b8605Smrg 28848b8605Smrg#include "postprocess.h" 29848b8605Smrg#include "postprocess/pp_filters.h" 30848b8605Smrg#include "postprocess/pp_private.h" 31848b8605Smrg 32848b8605Smrg#include "util/u_inlines.h" 33848b8605Smrg#include "util/u_sampler.h" 34848b8605Smrg 35848b8605Smrg#include "tgsi/tgsi_parse.h" 36848b8605Smrg 37848b8605Smrg 38848b8605Smrgvoid 39848b8605Smrgpp_blit(struct pipe_context *pipe, 40848b8605Smrg struct pipe_resource *src_tex, 41848b8605Smrg int srcX0, int srcY0, 42848b8605Smrg int srcX1, int srcY1, 43848b8605Smrg int srcZ0, 44848b8605Smrg struct pipe_surface *dst, 45848b8605Smrg int dstX0, int dstY0, 46848b8605Smrg int dstX1, int dstY1) 47848b8605Smrg{ 48848b8605Smrg struct pipe_blit_info blit; 49848b8605Smrg 50848b8605Smrg memset(&blit, 0, sizeof(blit)); 51848b8605Smrg 52848b8605Smrg blit.src.resource = src_tex; 53848b8605Smrg blit.src.level = 0; 54848b8605Smrg blit.src.format = src_tex->format; 55848b8605Smrg blit.src.box.x = srcX0; 56848b8605Smrg blit.src.box.y = srcY0; 57848b8605Smrg blit.src.box.z = srcZ0; 58848b8605Smrg blit.src.box.width = srcX1 - srcX0; 59848b8605Smrg blit.src.box.height = srcY1 - srcY0; 60848b8605Smrg blit.src.box.depth = 1; 61848b8605Smrg 62848b8605Smrg blit.dst.resource = dst->texture; 63848b8605Smrg blit.dst.level = dst->u.tex.level; 64848b8605Smrg blit.dst.format = dst->format; 65848b8605Smrg blit.dst.box.x = dstX0; 66848b8605Smrg blit.dst.box.y = dstY0; 67848b8605Smrg blit.dst.box.z = 0; 68848b8605Smrg blit.dst.box.width = dstX1 - dstX0; 69848b8605Smrg blit.dst.box.height = dstY1 - dstY0; 70848b8605Smrg blit.dst.box.depth = 1; 71848b8605Smrg 72848b8605Smrg blit.mask = PIPE_MASK_RGBA; 73848b8605Smrg 74848b8605Smrg pipe->blit(pipe, &blit); 75848b8605Smrg} 76848b8605Smrg 77848b8605Smrg/** 78848b8605Smrg* Main run function of the PP queue. Called on swapbuffers/flush. 79848b8605Smrg* 80848b8605Smrg* Runs all requested filters in order and handles shuffling the temp 81848b8605Smrg* buffers in between. 82848b8605Smrg*/ 83848b8605Smrgvoid 84848b8605Smrgpp_run(struct pp_queue_t *ppq, struct pipe_resource *in, 85848b8605Smrg struct pipe_resource *out, struct pipe_resource *indepth) 86848b8605Smrg{ 87848b8605Smrg struct pipe_resource *refin = NULL, *refout = NULL; 88848b8605Smrg unsigned int i; 89848b8605Smrg struct cso_context *cso = ppq->p->cso; 90848b8605Smrg 91848b8605Smrg if (ppq->n_filters == 0) 92848b8605Smrg return; 93848b8605Smrg 94848b8605Smrg assert(ppq->pp_queue); 95848b8605Smrg assert(ppq->tmp[0]); 96848b8605Smrg 97848b8605Smrg if (in->width0 != ppq->p->framebuffer.width || 98848b8605Smrg in->height0 != ppq->p->framebuffer.height) { 99848b8605Smrg pp_debug("Resizing the temp pp buffers\n"); 100848b8605Smrg pp_free_fbos(ppq); 101848b8605Smrg pp_init_fbos(ppq, in->width0, in->height0); 102848b8605Smrg } 103848b8605Smrg 104848b8605Smrg if (in == out && ppq->n_filters == 1) { 105848b8605Smrg /* Make a copy of in to tmp[0] in this case. */ 106848b8605Smrg unsigned int w = ppq->p->framebuffer.width; 107848b8605Smrg unsigned int h = ppq->p->framebuffer.height; 108848b8605Smrg 109848b8605Smrg 110848b8605Smrg pp_blit(ppq->p->pipe, in, 0, 0, 111848b8605Smrg w, h, 0, ppq->tmps[0], 112848b8605Smrg 0, 0, w, h); 113848b8605Smrg 114848b8605Smrg in = ppq->tmp[0]; 115848b8605Smrg } 116848b8605Smrg 117848b8605Smrg /* save state (restored below) */ 118b8e80941Smrg cso_save_state(cso, (CSO_BIT_BLEND | 119b8e80941Smrg CSO_BIT_DEPTH_STENCIL_ALPHA | 120b8e80941Smrg CSO_BIT_FRAGMENT_SHADER | 121b8e80941Smrg CSO_BIT_FRAMEBUFFER | 122b8e80941Smrg CSO_BIT_TESSCTRL_SHADER | 123b8e80941Smrg CSO_BIT_TESSEVAL_SHADER | 124b8e80941Smrg CSO_BIT_GEOMETRY_SHADER | 125b8e80941Smrg CSO_BIT_RASTERIZER | 126b8e80941Smrg CSO_BIT_SAMPLE_MASK | 127b8e80941Smrg CSO_BIT_MIN_SAMPLES | 128b8e80941Smrg CSO_BIT_FRAGMENT_SAMPLERS | 129b8e80941Smrg CSO_BIT_FRAGMENT_SAMPLER_VIEWS | 130b8e80941Smrg CSO_BIT_STENCIL_REF | 131b8e80941Smrg CSO_BIT_STREAM_OUTPUTS | 132b8e80941Smrg CSO_BIT_VERTEX_ELEMENTS | 133b8e80941Smrg CSO_BIT_VERTEX_SHADER | 134b8e80941Smrg CSO_BIT_VIEWPORT | 135b8e80941Smrg CSO_BIT_AUX_VERTEX_BUFFER_SLOT | 136b8e80941Smrg CSO_BIT_PAUSE_QUERIES | 137b8e80941Smrg CSO_BIT_RENDER_CONDITION)); 138848b8605Smrg cso_save_constant_buffer_slot0(cso, PIPE_SHADER_VERTEX); 139848b8605Smrg cso_save_constant_buffer_slot0(cso, PIPE_SHADER_FRAGMENT); 140848b8605Smrg 141848b8605Smrg /* set default state */ 142848b8605Smrg cso_set_sample_mask(cso, ~0); 143848b8605Smrg cso_set_min_samples(cso, 1); 144848b8605Smrg cso_set_stream_outputs(cso, 0, NULL, NULL); 145b8e80941Smrg cso_set_tessctrl_shader_handle(cso, NULL); 146b8e80941Smrg cso_set_tesseval_shader_handle(cso, NULL); 147848b8605Smrg cso_set_geometry_shader_handle(cso, NULL); 148848b8605Smrg cso_set_render_condition(cso, NULL, FALSE, 0); 149848b8605Smrg 150848b8605Smrg // Kept only for this frame. 151848b8605Smrg pipe_resource_reference(&ppq->depth, indepth); 152848b8605Smrg pipe_resource_reference(&refin, in); 153848b8605Smrg pipe_resource_reference(&refout, out); 154848b8605Smrg 155848b8605Smrg switch (ppq->n_filters) { 156848b8605Smrg case 0: 157848b8605Smrg /* Failsafe, but never reached. */ 158848b8605Smrg break; 159848b8605Smrg case 1: /* No temp buf */ 160848b8605Smrg ppq->pp_queue[0] (ppq, in, out, 0); 161848b8605Smrg break; 162848b8605Smrg case 2: /* One temp buf */ 163848b8605Smrg 164848b8605Smrg ppq->pp_queue[0] (ppq, in, ppq->tmp[0], 0); 165848b8605Smrg ppq->pp_queue[1] (ppq, ppq->tmp[0], out, 1); 166848b8605Smrg 167848b8605Smrg break; 168848b8605Smrg default: /* Two temp bufs */ 169848b8605Smrg assert(ppq->tmp[1]); 170848b8605Smrg ppq->pp_queue[0] (ppq, in, ppq->tmp[0], 0); 171848b8605Smrg 172848b8605Smrg for (i = 1; i < (ppq->n_filters - 1); i++) { 173848b8605Smrg if (i % 2 == 0) 174848b8605Smrg ppq->pp_queue[i] (ppq, ppq->tmp[1], ppq->tmp[0], i); 175848b8605Smrg 176848b8605Smrg else 177848b8605Smrg ppq->pp_queue[i] (ppq, ppq->tmp[0], ppq->tmp[1], i); 178848b8605Smrg } 179848b8605Smrg 180848b8605Smrg if (i % 2 == 0) 181848b8605Smrg ppq->pp_queue[i] (ppq, ppq->tmp[1], out, i); 182848b8605Smrg 183848b8605Smrg else 184848b8605Smrg ppq->pp_queue[i] (ppq, ppq->tmp[0], out, i); 185848b8605Smrg 186848b8605Smrg break; 187848b8605Smrg } 188848b8605Smrg 189848b8605Smrg /* restore state we changed */ 190b8e80941Smrg cso_restore_state(cso); 191848b8605Smrg cso_restore_constant_buffer_slot0(cso, PIPE_SHADER_VERTEX); 192848b8605Smrg cso_restore_constant_buffer_slot0(cso, PIPE_SHADER_FRAGMENT); 193848b8605Smrg 194848b8605Smrg pipe_resource_reference(&ppq->depth, NULL); 195848b8605Smrg pipe_resource_reference(&refin, NULL); 196848b8605Smrg pipe_resource_reference(&refout, NULL); 197848b8605Smrg} 198848b8605Smrg 199848b8605Smrg 200848b8605Smrg/* Utility functions for the filters. You're not forced to use these if */ 201848b8605Smrg/* your filter is more complicated. */ 202848b8605Smrg 203848b8605Smrg/** Setup this resource as the filter input. */ 204848b8605Smrgvoid 205848b8605Smrgpp_filter_setup_in(struct pp_program *p, struct pipe_resource *in) 206848b8605Smrg{ 207848b8605Smrg struct pipe_sampler_view v_tmp; 208848b8605Smrg u_sampler_view_default_template(&v_tmp, in, in->format); 209848b8605Smrg p->view = p->pipe->create_sampler_view(p->pipe, in, &v_tmp); 210848b8605Smrg} 211848b8605Smrg 212848b8605Smrg/** Setup this resource as the filter output. */ 213848b8605Smrgvoid 214848b8605Smrgpp_filter_setup_out(struct pp_program *p, struct pipe_resource *out) 215848b8605Smrg{ 216848b8605Smrg p->surf.format = out->format; 217848b8605Smrg 218848b8605Smrg p->framebuffer.cbufs[0] = p->pipe->create_surface(p->pipe, out, &p->surf); 219848b8605Smrg} 220848b8605Smrg 221848b8605Smrg/** Clean up the input and output set with the above. */ 222848b8605Smrgvoid 223848b8605Smrgpp_filter_end_pass(struct pp_program *p) 224848b8605Smrg{ 225848b8605Smrg pipe_surface_reference(&p->framebuffer.cbufs[0], NULL); 226848b8605Smrg pipe_sampler_view_reference(&p->view, NULL); 227848b8605Smrg} 228848b8605Smrg 229848b8605Smrg/** 230848b8605Smrg* Convert the TGSI assembly to a runnable shader. 231848b8605Smrg* 232848b8605Smrg* We need not care about geometry shaders. All we have is screen quads. 233848b8605Smrg*/ 234848b8605Smrgvoid * 235848b8605Smrgpp_tgsi_to_state(struct pipe_context *pipe, const char *text, bool isvs, 236848b8605Smrg const char *name) 237848b8605Smrg{ 238848b8605Smrg struct pipe_shader_state state; 239848b8605Smrg struct tgsi_token *tokens = NULL; 240848b8605Smrg void *ret_state = NULL; 241848b8605Smrg 242848b8605Smrg /* 243848b8605Smrg * Allocate temporary token storage. State creation will duplicate 244848b8605Smrg * tokens so we must free them on exit. 245848b8605Smrg */ 246848b8605Smrg tokens = tgsi_alloc_tokens(PP_MAX_TOKENS); 247848b8605Smrg 248b8e80941Smrg if (!tokens) { 249848b8605Smrg pp_debug("Failed to allocate temporary token storage.\n"); 250848b8605Smrg return NULL; 251848b8605Smrg } 252848b8605Smrg 253848b8605Smrg if (tgsi_text_translate(text, tokens, PP_MAX_TOKENS) == FALSE) { 254848b8605Smrg _debug_printf("pp: Failed to translate a shader for %s\n", name); 255848b8605Smrg return NULL; 256848b8605Smrg } 257848b8605Smrg 258b8e80941Smrg pipe_shader_state_from_tgsi(&state, tokens); 259848b8605Smrg 260848b8605Smrg if (isvs) { 261848b8605Smrg ret_state = pipe->create_vs_state(pipe, &state); 262848b8605Smrg FREE(tokens); 263848b8605Smrg } else { 264848b8605Smrg ret_state = pipe->create_fs_state(pipe, &state); 265848b8605Smrg FREE(tokens); 266848b8605Smrg } 267848b8605Smrg 268848b8605Smrg return ret_state; 269848b8605Smrg} 270848b8605Smrg 271848b8605Smrg/** Setup misc state for the filter. */ 272848b8605Smrgvoid 273848b8605Smrgpp_filter_misc_state(struct pp_program *p) 274848b8605Smrg{ 275848b8605Smrg cso_set_blend(p->cso, &p->blend); 276848b8605Smrg cso_set_depth_stencil_alpha(p->cso, &p->depthstencil); 277848b8605Smrg cso_set_rasterizer(p->cso, &p->rasterizer); 278848b8605Smrg cso_set_viewport(p->cso, &p->viewport); 279848b8605Smrg 280848b8605Smrg cso_set_vertex_elements(p->cso, 2, p->velem); 281848b8605Smrg} 282848b8605Smrg 283848b8605Smrg/** Draw with the filter to the set output. */ 284848b8605Smrgvoid 285848b8605Smrgpp_filter_draw(struct pp_program *p) 286848b8605Smrg{ 287848b8605Smrg util_draw_vertex_buffer(p->pipe, p->cso, p->vbuf, 0, 0, 288848b8605Smrg PIPE_PRIM_QUADS, 4, 2); 289848b8605Smrg} 290848b8605Smrg 291848b8605Smrg/** Set the framebuffer as active. */ 292848b8605Smrgvoid 293848b8605Smrgpp_filter_set_fb(struct pp_program *p) 294848b8605Smrg{ 295848b8605Smrg cso_set_framebuffer(p->cso, &p->framebuffer); 296848b8605Smrg} 297848b8605Smrg 298848b8605Smrg/** Set the framebuffer as active and clear it. */ 299848b8605Smrgvoid 300848b8605Smrgpp_filter_set_clear_fb(struct pp_program *p) 301848b8605Smrg{ 302848b8605Smrg cso_set_framebuffer(p->cso, &p->framebuffer); 303848b8605Smrg p->pipe->clear(p->pipe, PIPE_CLEAR_COLOR0, &p->clear_color, 0, 0); 304848b8605Smrg} 305