Cleanup: style
[blender.git] / source / blender / draw / intern / draw_builtin_shader.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16
17 /** \file draw_builtin_shader.c
18  *  \ingroup draw
19  * Draw manager versions of #eGPUBuiltinShader, see #GPU_shader_get_builtin_shader.
20  *
21  * Allows for modifications to shaders (currently only clipping support).
22  * Follow GPU_shader.h conventions to avoid annoyance.
23  */
24
25 #include "BLI_utildefines.h"
26
27 #include "GPU_shader.h"
28
29 #include "DRW_render.h"
30
31 #include "draw_builtin_shader.h"  /* own include */
32
33
34 extern char datatoc_common_world_clip_lib_glsl[];
35
36 /* Add shaders to this list when support is added. */
37 #define GPU_SHADER_IS_SUPPORTED(shader_id) \
38         ELEM(shader_id, \
39              GPU_SHADER_3D_UNIFORM_COLOR, \
40              GPU_SHADER_3D_SMOOTH_COLOR, \
41              GPU_SHADER_3D_DEPTH_ONLY, \
42              GPU_SHADER_CAMERA, \
43              GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE, \
44              GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SCALE, \
45              GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA, \
46              GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA, \
47              GPU_SHADER_3D_SCREENSPACE_VARIYING_COLOR, \
48              GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED, \
49              GPU_SHADER_3D_GROUNDLINE, \
50              GPU_SHADER_3D_GROUNDPOINT, \
51              GPU_SHADER_DISTANCE_LINES, \
52              GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR)
53
54 /* cache of built-in shaders (each is created on first use) */
55 static struct {
56         GPUShader *builtin_shaders[GPU_NUM_BUILTIN_SHADERS];
57 } g_sh_data[DRW_SHADER_SLOT_LEN - 1] = {{{NULL}}};
58
59 static GPUShader *drw_shader_get_builtin_shader_clipped(eGPUBuiltinShader shader_id)
60 {
61         const char *world_clip_lib = datatoc_common_world_clip_lib_glsl;
62         const char *world_clip_def = "#define USE_WORLD_CLIP_PLANES\n";
63
64         struct  { const char *vert, *frag, *geom, *defs; } shader_code;
65         GPU_shader_get_builtin_shader_code(
66                 shader_id,
67                 &shader_code.vert,
68                 &shader_code.frag,
69                 &shader_code.geom,
70                 &shader_code.defs);
71
72         /* In rare cases geometry shaders calculate clipping themselves. */
73         return DRW_shader_create_from_arrays({
74                 .vert = (const char *[]){world_clip_lib, shader_code.vert, NULL},
75                 .geom = (const char *[]){shader_code.geom ? world_clip_lib : NULL, shader_code.geom, NULL},
76                 .frag = (const char *[]){shader_code.frag, NULL},
77                 .defs = (const char *[]){world_clip_def, shader_code.defs, NULL},
78         });
79 }
80
81 GPUShader *DRW_shader_get_builtin_shader(eGPUBuiltinShader shader_id, eDRW_ShaderSlot slot)
82 {
83         BLI_assert(GPU_SHADER_IS_SUPPORTED(shader_id));
84
85         if (slot == DRW_SHADER_SLOT_DEFAULT) {
86                 return GPU_shader_get_builtin_shader(shader_id);
87         }
88
89         GPUShader **builtin_shaders = g_sh_data[slot - 1].builtin_shaders;
90
91         if (builtin_shaders[shader_id] != NULL) {
92                 return builtin_shaders[shader_id];
93         }
94
95         if (slot == DRW_SHADER_SLOT_CLIPPED) {
96                 builtin_shaders[shader_id] = drw_shader_get_builtin_shader_clipped(shader_id);
97                 return builtin_shaders[shader_id];
98         }
99         else {
100                 BLI_assert(0);
101                 return NULL;
102         }
103 }
104
105 void DRW_shader_free_builtin_shaders(void)
106 {
107         for (int j = 0; j < (DRW_SHADER_SLOT_LEN - 1); j++) {
108                 GPUShader **builtin_shaders = g_sh_data[j].builtin_shaders;
109                 for (int i = 0; i < GPU_NUM_BUILTIN_SHADERS; i++) {
110                         if (builtin_shaders[i]) {
111                                 GPU_shader_free(builtin_shaders[i]);
112                                 builtin_shaders[i] = NULL;
113                         }
114                 }
115         }
116 }