1 #include <wayfire/core.hpp> 2 #include <wayfire/opengl.hpp> 3 #include <wayfire/render-manager.hpp> 4 5 /* The MIT License (MIT) 6 * 7 * Copyright (c) 2018 Ilia Bozhinov 8 * Copyright (c) 2018 Scott Moreau 9 * 10 * The design of blur takes extra consideration due to the fact that 11 * the results of blurred pixels rely on surrounding pixel values. 12 * This means that when damage happens for only part of the scene (1), 13 * blurring this area can result to artifacts because of sampling 14 * beyond the edges of the area. To work around this issue, wayfire 15 * issues two signals - workspace-stream-pre and workspace-stream-post. 16 * workspace-stream-pre gives plugins an opportunity to pad the rects 17 * of the damage region (2) and save a snap-shot of the padded area from 18 * the buffer containing the last frame. This will be used to redraw 19 * the area that will contain artifacts after rendering. This is ok 20 * because this area is outside of the original damage area, so the 21 * pixels wont be changing in this region of the scene. pre_render is 22 * called with the padded damage region as an argument (2). The padded 23 * damage extents (3) are used for blitting from the framebuffer, which 24 * contains the scene rendered up until the view for which pre_render 25 * is called. The padded damage extents rect is blurred with artifacts 26 * in pre_render, after which it is then alpha blended with the window 27 * and rendered to the framebuffer. Finally, workspace-stream-post 28 * allows a chance to redraw the padded area with the saved pixels, 29 * before swapping buffers. As long as the padding is enough to cover 30 * the maximum sample offset that the shader uses, there should be a 31 * seamless experience. 32 * 33 * 1) 34 * ................................................................. 35 * | | 36 * | | 37 * | .................................. | 38 * | | |.. | 39 * | | | | | 40 * | | Damage region | | | 41 * | | | | | 42 * | | | | | 43 * | | | | | 44 * | | | | | 45 * | ```|```````````````````````````````| | 46 * | ````````````````````````````````` | 47 * | | 48 * | | 49 * ````````````````````````````````````````````````````````````````` 50 * 51 * 2) 52 * ................................................................. 53 * | | 54 * | ...................................... | 55 * | | .................................. |..<-- Padding | 56 * | | | |.. | | 57 * | | | | | | | 58 * | | | Padded | | | | 59 * | | | Damage region | | | | 60 * | | | | | | | 61 * | | | | | | | 62 * | | | | | | | 63 * | | | | | | | 64 * | | ```|```````````````````````````````| | | 65 * | ```| ````````````````````````````````` |<-- Padding | 66 * | ````````````````````````````````````` | 67 * ````````````````````````````````````````````````````````````````` 68 * 69 * 3) 70 * ................................................................. 71 * | | 72 * | x1| |x2 | 73 * | y1__ ...................................... . | 74 * | | |.. | 75 * | | | | 76 * | | ^ | | 77 * | | | | 78 * | | <- Padded extents -> | | 79 * | | | | 80 * | | v | | 81 * | | | | 82 * | y2__ ```| | | 83 * | ` ````````````````````````````````````` | 84 * | | 85 * ````````````````````````````````````````````````````````````````` 86 */ 87 88 class wf_blur_base 89 { 90 protected: 91 /* used to store temporary results in blur algorithms, cleaned up in base 92 * destructor */ 93 wf::framebuffer_base_t fb[2]; 94 /* the program created by the given algorithm, cleaned up in base destructor */ 95 OpenGL::program_t program[2]; 96 /* the program used by wf_blur_base to combine the blurred, unblurred and 97 * view texture */ 98 OpenGL::program_t blend_program; 99 100 /* used to get individual algorithm options from config 101 * should be set by the constructor */ 102 std::string algorithm_name; 103 104 wf::option_wrapper_t<double> saturation_opt; 105 wf::option_wrapper_t<double> offset_opt; 106 wf::option_wrapper_t<int> degrade_opt, iterations_opt; 107 wf::config::option_base_t::updated_callback_t options_changed; 108 109 wf::output_t *output; 110 111 /* renders the in texture to the out framebuffer. 112 * assumes a properly bound and initialized GL program */ 113 void render_iteration(wf::region_t blur_region, 114 wf::framebuffer_base_t& in, wf::framebuffer_base_t& out, 115 int width, int height); 116 117 /* copy the source pixels from region, storing into result 118 * returns the result geometry, in framebuffer coords */ 119 wlr_box copy_region(wf::framebuffer_base_t& result, 120 const wf::framebuffer_t& source, const wf::region_t& region); 121 122 /* blur fb[0] 123 * width and height are the scaled dimensions of the buffer 124 * returns the index of the fb where the result is stored (0 or 1) */ 125 virtual int blur_fb0(const wf::region_t& blur_region, int width, int height) = 0; 126 127 public: 128 wf_blur_base(wf::output_t *output, std::string name); 129 virtual ~wf_blur_base(); 130 131 virtual int calculate_blur_radius(); 132 133 virtual void pre_render(wf::texture_t src_tex, wlr_box src_box, 134 const wf::region_t& damage, const wf::framebuffer_t& target_fb); 135 136 virtual void render(wf::texture_t src_tex, wlr_box src_box, 137 wlr_box scissor_box, const wf::framebuffer_t& target_fb); 138 }; 139 140 std::unique_ptr<wf_blur_base> create_box_blur(wf::output_t *output); 141 std::unique_ptr<wf_blur_base> create_bokeh_blur(wf::output_t *output); 142 std::unique_ptr<wf_blur_base> create_kawase_blur(wf::output_t *output); 143 std::unique_ptr<wf_blur_base> create_gaussian_blur(wf::output_t *output); 144 145 std::unique_ptr<wf_blur_base> create_blur_from_name(wf::output_t *output, 146 std::string algorithm_name); 147