Cleanup: use lowercase gpu prefix for static funcs
[blender.git] / source / blender / gpu / intern / gpu_basic_shader.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2013 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Brecht Van Lommel.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/gpu/intern/gpu_basic_shader.c
29  *  \ingroup gpu
30  *
31  * GLSL shaders to replace fixed function OpenGL materials and lighting. These
32  * are deprecated in newer OpenGL versions and missing in OpenGL ES 2.0. Also,
33  * two sided lighting is no longer natively supported on NVidia cards which
34  * results in slow software fallback.
35  *
36  * Todo:
37  * - Replace glLight and glMaterial functions entirely with GLSL uniforms, to
38  *   make OpenGL ES 2.0 work.
39  * - Replace glTexCoord and glColor with generic attributes.
40  * - Optimize for case where fewer than 3 or 8 lights are used.
41  * - Optimize for case where specular is not used.
42  * - Optimize for case where no texture matrix is used.
43  */
44
45 #include "BLI_math.h"
46 #include "BLI_utildefines.h"
47
48 #include "GPU_basic_shader.h"
49 #include "GPU_glew.h"
50 #include "GPU_shader.h"
51
52 /* State */
53
54 static struct {
55         GPUShader *cached_shaders[GPU_SHADER_OPTION_COMBINATIONS];
56         bool failed_shaders[GPU_SHADER_OPTION_COMBINATIONS];
57
58         int bound_options;
59
60         int lights_enabled;
61         int lights_directional;
62         float line_width;
63         GLint viewport[4];
64 } GPU_MATERIAL_STATE;
65
66
67 /* Stipple patterns */
68 /* ******************************************** */
69 const GLubyte stipple_halftone[128] = {
70         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
71         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
72         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
73         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
74         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
75         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
76         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
77         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
78         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
79         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
80         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
81         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
82         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
83         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
84         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
85         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55};
86
87 const GLubyte stipple_quarttone[128] = {
88         136, 136, 136, 136, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0,
89         136, 136, 136, 136, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0,
90         136, 136, 136, 136, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0,
91         136, 136, 136, 136, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0,
92         136, 136, 136, 136, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0,
93         136, 136, 136, 136, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0,
94         136, 136, 136, 136, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0,
95         136, 136, 136, 136, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0};
96
97 const GLubyte stipple_diag_stripes_pos[128] = {
98         0x00, 0xff, 0x00, 0xff, 0x01, 0xfe, 0x01, 0xfe,
99         0x03, 0xfc, 0x03, 0xfc, 0x07, 0xf8, 0x07, 0xf8,
100         0x0f, 0xf0, 0x0f, 0xf0, 0x1f, 0xe0, 0x1f, 0xe0,
101         0x3f, 0xc0, 0x3f, 0xc0, 0x7f, 0x80, 0x7f, 0x80,
102         0xff, 0x00, 0xff, 0x00, 0xfe, 0x01, 0xfe, 0x01,
103         0xfc, 0x03, 0xfc, 0x03, 0xf8, 0x07, 0xf8, 0x07,
104         0xf0, 0x0f, 0xf0, 0x0f, 0xe0, 0x1f, 0xe0, 0x1f,
105         0xc0, 0x3f, 0xc0, 0x3f, 0x80, 0x7f, 0x80, 0x7f,
106         0x00, 0xff, 0x00, 0xff, 0x01, 0xfe, 0x01, 0xfe,
107         0x03, 0xfc, 0x03, 0xfc, 0x07, 0xf8, 0x07, 0xf8,
108         0x0f, 0xf0, 0x0f, 0xf0, 0x1f, 0xe0, 0x1f, 0xe0,
109         0x3f, 0xc0, 0x3f, 0xc0, 0x7f, 0x80, 0x7f, 0x80,
110         0xff, 0x00, 0xff, 0x00, 0xfe, 0x01, 0xfe, 0x01,
111         0xfc, 0x03, 0xfc, 0x03, 0xf8, 0x07, 0xf8, 0x07,
112         0xf0, 0x0f, 0xf0, 0x0f, 0xe0, 0x1f, 0xe0, 0x1f,
113         0xc0, 0x3f, 0xc0, 0x3f, 0x80, 0x7f, 0x80, 0x7f};
114
115 const GLubyte stipple_diag_stripes_neg[128] = {
116         0xff, 0x00, 0xff, 0x00, 0xfe, 0x01, 0xfe, 0x01,
117         0xfc, 0x03, 0xfc, 0x03, 0xf8, 0x07, 0xf8, 0x07,
118         0xf0, 0x0f, 0xf0, 0x0f, 0xe0, 0x1f, 0xe0, 0x1f,
119         0xc0, 0x3f, 0xc0, 0x3f, 0x80, 0x7f, 0x80, 0x7f,
120         0x00, 0xff, 0x00, 0xff, 0x01, 0xfe, 0x01, 0xfe,
121         0x03, 0xfc, 0x03, 0xfc, 0x07, 0xf8, 0x07, 0xf8,
122         0x0f, 0xf0, 0x0f, 0xf0, 0x1f, 0xe0, 0x1f, 0xe0,
123         0x3f, 0xc0, 0x3f, 0xc0, 0x7f, 0x80, 0x7f, 0x80,
124         0xff, 0x00, 0xff, 0x00, 0xfe, 0x01, 0xfe, 0x01,
125         0xfc, 0x03, 0xfc, 0x03, 0xf8, 0x07, 0xf8, 0x07,
126         0xf0, 0x0f, 0xf0, 0x0f, 0xe0, 0x1f, 0xe0, 0x1f,
127         0xc0, 0x3f, 0xc0, 0x3f, 0x80, 0x7f, 0x80, 0x7f,
128         0x00, 0xff, 0x00, 0xff, 0x01, 0xfe, 0x01, 0xfe,
129         0x03, 0xfc, 0x03, 0xfc, 0x07, 0xf8, 0x07, 0xf8,
130         0x0f, 0xf0, 0x0f, 0xf0, 0x1f, 0xe0, 0x1f, 0xe0,
131         0x3f, 0xc0, 0x3f, 0xc0, 0x7f, 0x80, 0x7f, 0x80};
132
133 const GLubyte stipple_checker_8px[128] = {
134         255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0,
135         255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0,
136         0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
137         0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
138         255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0,
139         255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0,
140         0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
141         0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255};
142
143 const GLubyte stipple_interlace_row[128] = {
144         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
145         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
146         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
147         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
148         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
149         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
150         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
151         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
152         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
153         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
154         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
155         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
156         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
157         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
158         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
159         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00};
160
161 const GLubyte stipple_interlace_row_swap[128] = {
162         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
163         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
164         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
165         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
166         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
167         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
168         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
169         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
170         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
171         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
172         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
173         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
174         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
175         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
176         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
177         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff};
178
179 const GLubyte stipple_interlace_column[128] = {
180         0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
181         0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
182         0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
183         0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
184         0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
185         0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
186         0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
187         0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
188         0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
189         0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
190         0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
191         0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
192         0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
193         0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
194         0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
195         0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
196
197 const GLubyte stipple_interlace_column_swap[128] = {
198         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
199         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
200         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
201         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
202         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
203         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
204         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
205         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
206         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
207         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
208         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
209         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
210         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
211         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
212         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
213         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa};
214
215 const GLubyte stipple_interlace_checker[128] = {
216         0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
217         0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
218         0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
219         0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
220         0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
221         0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
222         0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
223         0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
224         0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
225         0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
226         0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
227         0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
228         0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
229         0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
230         0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
231         0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa};
232
233 const GLubyte stipple_interlace_checker_swap[128] = {
234         0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
235         0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
236         0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
237         0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
238         0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
239         0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
240         0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
241         0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
242         0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
243         0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
244         0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
245         0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
246         0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
247         0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
248         0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
249         0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55};
250
251 const GLubyte stipple_hexagon[128] = {
252         0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
253         0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
254         0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
255         0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
256         0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
257         0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
258         0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
259         0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
260         0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
261         0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
262         0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
263         0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
264         0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
265         0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
266         0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
267         0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22};
268 /* ********************************************* */
269
270 /* GLSL State */
271
272 static bool USE_GLSL = false;
273
274 /**
275  * \note this isn't part of the basic shader API,
276  * only set from the command line once on startup.
277  */
278 void GPU_basic_shader_use_glsl_set(bool enabled)
279 {
280         USE_GLSL = enabled;
281 }
282
283 bool GPU_basic_shader_use_glsl_get(void)
284 {
285         return USE_GLSL;
286 }
287
288 /* Init / exit */
289
290 void GPU_basic_shaders_init(void)
291 {
292         memset(&GPU_MATERIAL_STATE, 0, sizeof(GPU_MATERIAL_STATE));
293 }
294
295 void GPU_basic_shaders_exit(void)
296 {
297         int i;
298         
299         for (i = 0; i < GPU_SHADER_OPTION_COMBINATIONS; i++)
300                 if (GPU_MATERIAL_STATE.cached_shaders[i])
301                         GPU_shader_free(GPU_MATERIAL_STATE.cached_shaders[i]);
302 }
303
304 /* Shader lookup / create */
305
306 static bool solid_compatible_lighting(void)
307 {
308         int enabled = GPU_MATERIAL_STATE.lights_enabled;
309         int directional = GPU_MATERIAL_STATE.lights_directional;
310
311         /* more than 3 lights? */
312         if (enabled >= (1 << 3))
313                 return false;
314
315         /* all directional? */
316         return ((directional & enabled) == enabled);
317 }
318
319 #if 0
320 static int detect_options()
321 {
322         GLint two_sided;
323         int options = 0;
324
325         if (glIsEnabled(GL_TEXTURE_2D))
326                 options |= GPU_SHADER_TEXTURE_2D;
327         if (glIsEnabled(GL_TEXTURE_RECTANGLE))
328                 options |= GPU_SHADER_TEXTURE_RECT;
329         GPU_SHADER_TEXTURE_RECT
330         if (glIsEnabled(GL_COLOR_MATERIAL))
331                 options |= GPU_SHADER_USE_COLOR;
332
333         if (glIsEnabled(GL_LIGHTING))
334                 options |= GPU_SHADER_LIGHTING;
335
336         glGetIntegerv(GL_LIGHT_MODEL_TWO_SIDE, &two_sided);
337         if (two_sided == GL_TRUE)
338                 options |= GPU_SHADER_TWO_SIDED;
339         
340         return options;
341 }
342 #endif
343
344 static GPUShader *gpu_basic_shader(int options)
345 {
346         /* glsl code */
347         extern char datatoc_gpu_shader_basic_vert_glsl[];
348         extern char datatoc_gpu_shader_basic_frag_glsl[];
349         extern char datatoc_gpu_shader_basic_geom_glsl[];
350         char *geom_glsl = NULL;
351         GPUShader *shader;
352
353         /* detect if we can do faster lighting for solid draw mode */
354         if (options & GPU_SHADER_LIGHTING)
355                 if (solid_compatible_lighting())
356                         options |= GPU_SHADER_SOLID_LIGHTING;
357
358         /* cached shaders */
359         shader = GPU_MATERIAL_STATE.cached_shaders[options];
360
361         if (!shader && !GPU_MATERIAL_STATE.failed_shaders[options]) {
362                 /* create shader if it doesn't exist yet */
363                 char defines[64 * GPU_SHADER_OPTIONS_NUM] = "";
364
365                 if (options & GPU_SHADER_USE_COLOR)
366                         strcat(defines, "#define USE_COLOR\n");
367                 if (options & GPU_SHADER_TWO_SIDED)
368                         strcat(defines, "#define USE_TWO_SIDED\n");
369                 if (options & (GPU_SHADER_TEXTURE_2D | GPU_SHADER_TEXTURE_RECT))
370                         strcat(defines, "#define USE_TEXTURE\n");
371                 if (options & GPU_SHADER_TEXTURE_RECT)
372                         strcat(defines, "#define USE_TEXTURE_RECTANGLE\n");
373                 if (options & GPU_SHADER_STIPPLE)
374                         strcat(defines, "#define USE_STIPPLE\n");
375                 if (options & GPU_SHADER_LINE) {
376                         strcat(defines, "#define DRAW_LINE\n");
377                         geom_glsl = datatoc_gpu_shader_basic_geom_glsl;
378                 }
379                 if (options & GPU_SHADER_FLAT_NORMAL)
380                         strcat(defines, "#define USE_FLAT_NORMAL\n");
381                 if (options & GPU_SHADER_SOLID_LIGHTING)
382                         strcat(defines, "#define USE_SOLID_LIGHTING\n");
383                 else if (options & GPU_SHADER_LIGHTING)
384                         strcat(defines, "#define USE_SCENE_LIGHTING\n");
385
386                 shader = GPU_shader_create(
387                         datatoc_gpu_shader_basic_vert_glsl,
388                         datatoc_gpu_shader_basic_frag_glsl,
389                         geom_glsl,
390                         NULL,
391                         defines, 0, 0, 0);
392                 
393                 if (shader) {
394                         /* set texture map to first texture unit */
395                         if (options & (GPU_SHADER_TEXTURE_2D | GPU_SHADER_TEXTURE_RECT)) {
396                                 GPU_shader_bind(shader);
397                                 glUniform1i(GPU_shader_get_uniform(shader, "texture_map"), 0);
398                                 GPU_shader_unbind();
399                         }
400
401                         GPU_MATERIAL_STATE.cached_shaders[options] = shader;
402                 }
403                 else
404                         GPU_MATERIAL_STATE.failed_shaders[options] = true;
405         }
406
407         return shader;
408 }
409
410 static void gpu_basic_shader_uniform_autoset(GPUShader *shader, int options)
411 {
412         if (options & GPU_SHADER_LINE) {
413                 glGetIntegerv(GL_VIEWPORT, &GPU_MATERIAL_STATE.viewport[0]);
414                 glUniform4iv(GPU_shader_get_uniform(shader, "viewport"), 1, &GPU_MATERIAL_STATE.viewport[0]);
415                 glUniform1f(GPU_shader_get_uniform(shader, "line_width"), GPU_MATERIAL_STATE.line_width);
416         }
417 }
418
419 /* Bind / unbind */
420
421 void GPU_basic_shader_bind(int options)
422 {
423         if (USE_GLSL) {
424                 if (options) {
425                         const int bound_options = GPU_MATERIAL_STATE.bound_options;
426
427                         /* texture options need to be set for basic shader too */
428                         if (options & GPU_SHADER_TEXTURE_2D) {
429                                 glEnable(GL_TEXTURE_2D);
430                         }
431                         else if (bound_options & GPU_SHADER_TEXTURE_2D) {
432                                 glDisable(GL_TEXTURE_2D);
433                         }
434
435                         if (options & GPU_SHADER_TEXTURE_RECT) {
436                                 glEnable(GL_TEXTURE_RECTANGLE);
437                         }
438                         else if (bound_options & GPU_SHADER_TEXTURE_RECT) {
439                                 glDisable(GL_TEXTURE_RECTANGLE);
440                         }
441
442                         GPUShader *shader = gpu_basic_shader(options);
443
444                         if (shader) {
445                                 GPU_shader_bind(shader);
446                                 gpu_basic_shader_uniform_autoset(shader, options);
447                         }
448                 }
449                 else {
450                         GPU_shader_unbind();
451                 }
452         }
453         else {
454                 const int bound_options = GPU_MATERIAL_STATE.bound_options;
455
456                 if (options & GPU_SHADER_LIGHTING) {
457                         glEnable(GL_LIGHTING);
458
459                         if (options & GPU_SHADER_USE_COLOR)
460                                 glEnable(GL_COLOR_MATERIAL);
461                         else
462                                 glDisable(GL_COLOR_MATERIAL);
463
464                         if (options & GPU_SHADER_TWO_SIDED)
465                                 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
466                         else
467                                 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
468                 }
469                 else if (bound_options & GPU_SHADER_LIGHTING) {
470                         glDisable(GL_LIGHTING);
471                         glDisable(GL_COLOR_MATERIAL);
472                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
473                 }
474
475                 if (options & GPU_SHADER_TEXTURE_2D) {
476                         GLint env_mode = (options & (GPU_SHADER_USE_COLOR | GPU_SHADER_LIGHTING)) ? GL_MODULATE : GL_REPLACE;
477                         glEnable(GL_TEXTURE_2D);
478                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, env_mode);
479                 }
480                 else if (bound_options & GPU_SHADER_TEXTURE_2D) {
481                         if ((options & GPU_SHADER_TEXTURE_RECT) == 0) {
482                                 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
483                         }
484                         glDisable(GL_TEXTURE_2D);
485                 }
486
487                 if (options & GPU_SHADER_TEXTURE_RECT) {
488                         GLint env_mode = (options & (GPU_SHADER_USE_COLOR | GPU_SHADER_LIGHTING)) ? GL_MODULATE : GL_REPLACE;
489                         glEnable(GL_TEXTURE_RECTANGLE);
490                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, env_mode);
491                 }
492                 else if (bound_options & GPU_SHADER_TEXTURE_RECT) {
493                         if ((options & GPU_SHADER_TEXTURE_2D) == 0) {
494                                 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
495                         }
496                         glDisable(GL_TEXTURE_RECTANGLE);
497                 }
498
499                 if ((options & GPU_SHADER_LINE) && (options & GPU_SHADER_STIPPLE)) {
500                         glEnable(GL_LINE_STIPPLE);
501                 }
502                 else if ((bound_options & GPU_SHADER_LINE) && (bound_options & GPU_SHADER_STIPPLE)) {
503                         glDisable(GL_LINE_STIPPLE);
504                 }
505
506                 if (((options & GPU_SHADER_LINE) == 0) && (options & GPU_SHADER_STIPPLE)) {
507                         glEnable(GL_POLYGON_STIPPLE);
508                 }
509                 else if (((bound_options & GPU_SHADER_LINE) == 0) && (bound_options & GPU_SHADER_STIPPLE)) {
510                         glDisable(GL_POLYGON_STIPPLE);
511                 }
512
513                 if (options & GPU_SHADER_FLAT_NORMAL) {
514                         glShadeModel(GL_FLAT);
515                 }
516                 else if (bound_options & GPU_SHADER_FLAT_NORMAL) {
517                         glShadeModel(GL_SMOOTH);
518                 }
519         }
520
521         GPU_MATERIAL_STATE.bound_options = options;
522 }
523
524 void GPU_basic_shader_bind_enable(int options)
525 {
526         GPU_basic_shader_bind(GPU_MATERIAL_STATE.bound_options | options);
527 }
528
529 void GPU_basic_shader_bind_disable(int options)
530 {
531         GPU_basic_shader_bind(GPU_MATERIAL_STATE.bound_options & ~options);
532 }
533
534 int GPU_basic_shader_bound_options(void)
535 {
536         /* ideally this should disappear, anything that uses this is making fragile
537          * assumptions that the basic shader is bound and not another shader */
538         return GPU_MATERIAL_STATE.bound_options;
539 }
540
541 /* Material Colors */
542
543 void GPU_basic_shader_colors(
544         const float diffuse[3], const float specular[3],
545         int shininess, float alpha)
546 {
547         float gl_diffuse[4], gl_specular[4];
548
549         if (diffuse)
550                 copy_v3_v3(gl_diffuse, diffuse);
551         else
552                 zero_v3(gl_diffuse);
553         gl_diffuse[3] = alpha;
554
555         if (specular)
556                 copy_v3_v3(gl_specular, specular);
557         else
558                 zero_v3(gl_specular);
559         gl_specular[3] = 1.0f;
560
561         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, gl_diffuse);
562         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, gl_specular);
563         glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, CLAMPIS(shininess, 1, 128));
564 }
565
566 void GPU_basic_shader_light_set(int light_num, GPULightData *light)
567 {
568         int light_bit = (1 << light_num);
569
570         /* note that light position is affected by the current modelview matrix! */
571
572         GPU_MATERIAL_STATE.lights_enabled &= ~light_bit;
573         GPU_MATERIAL_STATE.lights_directional &= ~light_bit;
574
575         if (light) {
576                 float position[4], diffuse[4], specular[4];
577
578                 glEnable(GL_LIGHT0 + light_num);
579
580                 /* position */
581                 if (light->type == GPU_LIGHT_SUN) {
582                         copy_v3_v3(position, light->direction);
583                         position[3] = 0.0f;
584                 }
585                 else {
586                         copy_v3_v3(position, light->position);
587                         position[3] = 1.0f;
588                 }
589                 glLightfv(GL_LIGHT0 + light_num, GL_POSITION, position);
590
591                 /* energy */
592                 copy_v3_v3(diffuse, light->diffuse);
593                 copy_v3_v3(specular, light->specular);
594                 diffuse[3] = 1.0f;
595                 specular[3] = 1.0f;
596                 glLightfv(GL_LIGHT0 + light_num, GL_DIFFUSE, diffuse);
597                 glLightfv(GL_LIGHT0 + light_num, GL_SPECULAR, specular);
598
599                 /* attenuation */
600                 if (light->type == GPU_LIGHT_SUN) {
601                         glLightf(GL_LIGHT0 + light_num, GL_CONSTANT_ATTENUATION, 1.0f);
602                         glLightf(GL_LIGHT0 + light_num, GL_LINEAR_ATTENUATION, 0.0f);
603                         glLightf(GL_LIGHT0 + light_num, GL_QUADRATIC_ATTENUATION, 0.0f);
604                 }
605                 else {
606                         glLightf(GL_LIGHT0 + light_num, GL_CONSTANT_ATTENUATION, light->constant_attenuation);
607                         glLightf(GL_LIGHT0 + light_num, GL_LINEAR_ATTENUATION, light->linear_attenuation);
608                         glLightf(GL_LIGHT0 + light_num, GL_QUADRATIC_ATTENUATION, light->quadratic_attenuation);
609                 }
610
611                 /* spot */
612                 glLightfv(GL_LIGHT0 + light_num, GL_SPOT_DIRECTION, light->direction);
613                 if (light->type == GPU_LIGHT_SPOT) {
614                         glLightf(GL_LIGHT0 + light_num, GL_SPOT_CUTOFF, light->spot_cutoff);
615                         glLightf(GL_LIGHT0 + light_num, GL_SPOT_EXPONENT, light->spot_exponent);
616                 }
617                 else {
618                         glLightf(GL_LIGHT0 + light_num, GL_SPOT_CUTOFF, 180.0f);
619                         glLightf(GL_LIGHT0 + light_num, GL_SPOT_EXPONENT, 0.0f);
620                 }
621
622                 GPU_MATERIAL_STATE.lights_enabled |= light_bit;
623                 if (position[3] == 0.0f)
624                         GPU_MATERIAL_STATE.lights_directional |= light_bit;
625         }
626         else {
627                 /* TODO(sergey): Needs revisit. */
628                 if (USE_GLSL || true) {
629                         /* glsl shader needs these zero to skip them */
630                         const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
631
632                         glLightfv(GL_LIGHT0 + light_num, GL_POSITION, zero);
633                         glLightfv(GL_LIGHT0 + light_num, GL_DIFFUSE, zero);
634                         glLightfv(GL_LIGHT0 + light_num, GL_SPECULAR, zero);
635                 }
636
637                 glDisable(GL_LIGHT0 + light_num);
638         }
639 }
640
641 void GPU_basic_shader_light_set_viewer(bool local)
642 {
643         glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, (local) ? GL_TRUE: GL_FALSE);
644 }
645
646 void GPU_basic_shader_stipple(GPUBasicShaderStipple stipple_id)
647 {
648         if (USE_GLSL) {
649                 glUniform1i(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "stipple_id"), stipple_id);
650         }
651         else {
652                 switch (stipple_id) {
653                         case GPU_SHADER_STIPPLE_HALFTONE:
654                                 glPolygonStipple(stipple_halftone);
655                                 return;
656                         case GPU_SHADER_STIPPLE_QUARTTONE:
657                                 glPolygonStipple(stipple_quarttone);
658                                 return;
659                         case GPU_SHADER_STIPPLE_CHECKER_8PX:
660                                 glPolygonStipple(stipple_checker_8px);
661                                 return;
662                         case GPU_SHADER_STIPPLE_HEXAGON:
663                                 glPolygonStipple(stipple_hexagon);
664                                 return;
665                         case GPU_SHADER_STIPPLE_DIAG_STRIPES_SWAP:
666                                 glPolygonStipple(stipple_diag_stripes_neg);
667                                 return;
668                         case GPU_SHADER_STIPPLE_DIAG_STRIPES:
669                                 glPolygonStipple(stipple_diag_stripes_pos);
670                                 return;
671                         case GPU_SHADER_STIPPLE_S3D_INTERLACE_ROW:
672                                 glPolygonStipple(stipple_interlace_row);
673                                 return;
674                         case GPU_SHADER_STIPPLE_S3D_INTERLACE_ROW_SWAP:
675                                 glPolygonStipple(stipple_interlace_row_swap);
676                                 return;
677                         case GPU_SHADER_STIPPLE_S3D_INTERLACE_COLUMN:
678                                 glPolygonStipple(stipple_interlace_column);
679                                 return;
680                         case GPU_SHADER_STIPPLE_S3D_INTERLACE_COLUMN_SWAP:
681                                 glPolygonStipple(stipple_interlace_column_swap);
682                                 return;
683                         case GPU_SHADER_STIPPLE_S3D_INTERLACE_CHECKER:
684                                 glPolygonStipple(stipple_interlace_checker);
685                                 return;
686                         case GPU_SHADER_STIPPLE_S3D_INTERLACE_CHECKER_SWAP:
687                                 glPolygonStipple(stipple_interlace_checker_swap);
688                                 return;
689                         default:
690                                 glPolygonStipple(stipple_hexagon);
691                                 return;
692                 }
693         }
694 }
695
696 void GPU_basic_shader_line_width(float line_width)
697 {
698         if (USE_GLSL) {
699                 GPU_MATERIAL_STATE.line_width = line_width;
700                 if (GPU_MATERIAL_STATE.bound_options & GPU_SHADER_LINE) {
701                         glUniform1f(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "line_width"), line_width);
702                 }
703         }
704         else {
705                 glLineWidth(line_width);
706         }
707 }
708
709 void GPU_basic_shader_line_stipple(GLint stipple_factor, GLushort stipple_pattern)
710 {
711         if (USE_GLSL) {
712                 glUniform1i(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "stipple_factor"), stipple_factor);
713                 glUniform1i(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "stipple_pattern"), stipple_pattern);
714         }
715         else {
716                 glLineStipple(stipple_factor, stipple_pattern);
717         }
718 }