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