Cleanup: comment blocks
[blender.git] / source / blender / gpu / intern / gpu_extensions.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) 2005 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_extensions.c
29  *  \ingroup gpu
30  *
31  * Wrap OpenGL features such as textures, shaders and GLSL
32  * with checks for drivers and GPU support.
33  */
34
35 #include "BLI_utildefines.h"
36 #include "BLI_math_base.h"
37 #include "BLI_math_vector.h"
38
39 #include "BKE_global.h"
40
41 #include "GPU_basic_shader.h"
42 #include "GPU_extensions.h"
43 #include "GPU_glew.h"
44 #include "GPU_texture.h"
45
46 #include "intern/gpu_private.h"
47
48 #include <stdlib.h>
49 #include <stdio.h>
50 #include <string.h>
51
52 #ifdef WIN32
53 #  include "BLI_winstuff.h"
54 #endif
55
56 /* Extensions support */
57
58 /* -- extension: version of GL that absorbs it
59  * ARB_framebuffer object: 3.0
60  * EXT_framebuffer_object: 3.0
61  * EXT_framebuffer_blit: 3.0
62  * EXT_framebuffer_multisample: 3.0
63  * EXT_framebuffer_multisample_blit_scaled: ???
64  * ARB_draw_instanced: 3.1
65  * ARB_texture_multisample: 3.2
66  * EXT_geometry_shader4: 3.2
67  * ARB_texture_query_lod: 4.0
68  */
69
70 static struct GPUGlobal {
71         GLint maxtexsize;
72         GLint maxcubemapsize;
73         GLint maxtextures;
74         bool extdisabled;
75         int colordepth;
76         int samples_color_texture_max;
77         GPUDeviceType device;
78         GPUOSType os;
79         GPUDriverType driver;
80         /* workaround for different calculation of dfdy factors on GPUs. Some GPUs/drivers
81          * calculate dfdy in shader differently when drawing to an offscreen buffer. First
82          * number is factor on screen and second is off-screen */
83         float dfdyfactors[2];
84         float max_anisotropy;
85 } GG = {1, 0};
86
87 /* GPU Types */
88
89 bool GPU_type_matches(GPUDeviceType device, GPUOSType os, GPUDriverType driver)
90 {
91         return (GG.device & device) && (GG.os & os) && (GG.driver & driver);
92 }
93
94 /* GPU Extensions */
95
96 void GPU_extensions_disable(void)
97 {
98         GG.extdisabled = true;
99 }
100
101 int GPU_max_texture_size(void)
102 {
103         return GG.maxtexsize;
104 }
105
106 int GPU_max_textures(void)
107 {
108         return GG.maxtextures;
109 }
110
111 float GPU_max_texture_anisotropy(void)
112 {
113         return GG.max_anisotropy;
114 }
115
116 int GPU_max_color_texture_samples(void)
117 {
118         return GG.samples_color_texture_max;
119 }
120
121 int GPU_max_cube_map_size(void)
122 {
123         return GG.maxcubemapsize;
124 }
125
126 void GPU_get_dfdy_factors(float fac[2])
127 {
128         copy_v2_v2(fac, GG.dfdyfactors);
129 }
130
131 void gpu_extensions_init(void)
132 {
133         /* BLI_assert(GLEW_VERSION_2_1); */
134         /* ^-- maybe a bit extreme? */
135
136         glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &GG.maxtextures);
137
138         glGetIntegerv(GL_MAX_TEXTURE_SIZE, &GG.maxtexsize);
139         glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &GG.maxcubemapsize);
140
141         if (GLEW_EXT_texture_filter_anisotropic)
142                 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &GG.max_anisotropy);
143         else
144                 GG.max_anisotropy = 1.0f;
145
146         GLint r, g, b;
147         glGetIntegerv(GL_RED_BITS, &r);
148         glGetIntegerv(GL_GREEN_BITS, &g);
149         glGetIntegerv(GL_BLUE_BITS, &b);
150         GG.colordepth = r + g + b; /* assumes same depth for RGB */
151
152         if (GLEW_VERSION_3_2 || GLEW_ARB_texture_multisample) {
153                 glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &GG.samples_color_texture_max);
154         }
155
156         const char *vendor = (const char *)glGetString(GL_VENDOR);
157         const char *renderer = (const char *)glGetString(GL_RENDERER);
158         const char *version = (const char *)glGetString(GL_VERSION);
159
160         if (strstr(vendor, "ATI")) {
161                 GG.device = GPU_DEVICE_ATI;
162                 GG.driver = GPU_DRIVER_OFFICIAL;
163         }
164         else if (strstr(vendor, "NVIDIA")) {
165                 GG.device = GPU_DEVICE_NVIDIA;
166                 GG.driver = GPU_DRIVER_OFFICIAL;
167         }
168         else if (strstr(vendor, "Intel") ||
169                  /* src/mesa/drivers/dri/intel/intel_context.c */
170                  strstr(renderer, "Mesa DRI Intel") ||
171                  strstr(renderer, "Mesa DRI Mobile Intel"))
172         {
173                 GG.device = GPU_DEVICE_INTEL;
174                 GG.driver = GPU_DRIVER_OFFICIAL;
175         }
176         else if (strstr(renderer, "Mesa DRI R") || (strstr(renderer, "Gallium ") && strstr(renderer, " on ATI "))) {
177                 GG.device = GPU_DEVICE_ATI;
178                 GG.driver = GPU_DRIVER_OPENSOURCE;
179         }
180         else if (strstr(renderer, "Nouveau") || strstr(vendor, "nouveau")) {
181                 GG.device = GPU_DEVICE_NVIDIA;
182                 GG.driver = GPU_DRIVER_OPENSOURCE;
183         }
184         else if (strstr(vendor, "Mesa")) {
185                 GG.device = GPU_DEVICE_SOFTWARE;
186                 GG.driver = GPU_DRIVER_SOFTWARE;
187         }
188         else if (strstr(vendor, "Microsoft")) {
189                 GG.device = GPU_DEVICE_SOFTWARE;
190                 GG.driver = GPU_DRIVER_SOFTWARE;
191         }
192         else if (strstr(renderer, "Apple Software Renderer")) {
193                 GG.device = GPU_DEVICE_SOFTWARE;
194                 GG.driver = GPU_DRIVER_SOFTWARE;
195         }
196         else {
197                 GG.device = GPU_DEVICE_ANY;
198                 GG.driver = GPU_DRIVER_ANY;
199         }
200
201         /* make sure double side isn't used by default and only getting enabled in places where it's
202          * really needed to prevent different unexpected behaviors like with intel gme965 card (sergey) */
203         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
204
205 #ifdef _WIN32
206         GG.os = GPU_OS_WIN;
207 #elif defined(__APPLE__)
208         GG.os = GPU_OS_MAC;
209 #else
210         GG.os = GPU_OS_UNIX;
211 #endif
212
213
214         /* df/dy calculation factors, those are dependent on driver */
215         if ((strstr(vendor, "ATI") && strstr(version, "3.3.10750"))) {
216                 GG.dfdyfactors[0] = 1.0;
217                 GG.dfdyfactors[1] = -1.0;
218         }
219         else if ((GG.device == GPU_DEVICE_INTEL) && (GG.os == GPU_OS_WIN) &&
220                  (strstr(version, "4.0.0 - Build 10.18.10.3308") ||
221                   strstr(version, "4.0.0 - Build 9.18.10.3186") ||
222                   strstr(version, "4.0.0 - Build 9.18.10.3165") ||
223                   strstr(version, "3.1.0 - Build 9.17.10.3347") ||
224                   strstr(version, "3.1.0 - Build 9.17.10.4101") ||
225                   strstr(version, "3.3.0 - Build 8.15.10.2618")))
226         {
227                 GG.dfdyfactors[0] = -1.0;
228                 GG.dfdyfactors[1] = 1.0;
229         }
230         else {
231                 GG.dfdyfactors[0] = 1.0;
232                 GG.dfdyfactors[1] = 1.0;
233         }
234
235
236         GPU_invalid_tex_init();
237         GPU_basic_shaders_init();
238 }
239
240 void gpu_extensions_exit(void)
241 {
242         GPU_basic_shaders_exit();
243         GPU_invalid_tex_free();
244 }
245
246 bool GPU_legacy_support(void)
247 {
248         /* return whether or not current GL context is compatible with legacy OpenGL */
249         static bool checked = false;
250         static bool support = true;
251
252         if (!checked) {
253                 if (GLEW_VERSION_3_2) {
254                         GLint profile;
255                         glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &profile);
256
257                         if (G.debug & G_DEBUG_GPU) {
258                                 printf("GL_CONTEXT_PROFILE_MASK = %#x (%s profile)\n", (unsigned int)profile,
259                                        (profile & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) ? "compatibility" :
260                                        (profile & GL_CONTEXT_CORE_PROFILE_BIT) ? "core" : "unknown");
261                         }
262
263                         if (profile == 0) {
264                                 /* workaround for nVidia's Linux driver */
265                                 support = GLEW_ARB_compatibility;
266                         }
267                         else {
268                                 support = profile & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT;
269                         }
270                 }
271                 else if (GLEW_VERSION_3_1) {
272                         support = GLEW_ARB_compatibility;
273                 }
274
275                 /* any OpenGL version <= 3.0 is legacy, so support remains true */
276
277                 checked = true;
278         }
279
280         return support;
281 }
282
283 bool GPU_glsl_support(void)
284 {
285         /* always supported, still queried by game engine */
286         return true;
287 }
288
289 bool GPU_full_non_power_of_two_support(void)
290 {
291         /* always supported on full GL but still relevant for OpenGL ES 2.0 where
292          * NPOT textures can't use mipmaps or repeat wrap mode */
293         return true;
294 }
295
296 bool GPU_display_list_support(void)
297 {
298         /* deprecated in GL 3
299          * supported on older GL and compatibility profile
300          * still queried by game engine
301          */
302         return true;
303 }
304
305 bool GPU_bicubic_bump_support(void)
306 {
307         return GLEW_VERSION_4_0 || (GLEW_ARB_texture_query_lod && GLEW_VERSION_3_0);
308 }
309
310 bool GPU_geometry_shader_support(void)
311 {
312         /* in GL 3.2 geometry shaders are fully supported
313          * core profile clashes with our other shaders so accept compatibility only
314          * other GL versions can use EXT_geometry_shader4 if available
315          */
316         return (GLEW_VERSION_3_2 && GPU_legacy_support()) || GLEW_EXT_geometry_shader4;
317 }
318
319 bool GPU_geometry_shader_support_via_extension(void)
320 {
321         return GLEW_EXT_geometry_shader4 && !(GLEW_VERSION_3_2 && GPU_legacy_support());
322 }
323
324 bool GPU_instanced_drawing_support(void)
325 {
326         return GLEW_VERSION_3_1 || GLEW_ARB_draw_instanced;
327 }
328
329 int GPU_color_depth(void)
330 {
331         return GG.colordepth;
332 }
333
334 bool GPU_mem_stats_supported(void)
335 {
336         return (GLEW_NVX_gpu_memory_info || (GLEW_ATI_meminfo)) && (G.debug & G_DEBUG_GPU_MEM);
337 }
338
339
340 void GPU_mem_stats_get(int *totalmem, int *freemem)
341 {
342         if (GLEW_NVX_gpu_memory_info) {
343                 /* returned value in Kb */
344                 glGetIntegerv(GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, totalmem);
345
346                 glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, freemem);
347         }
348         else if (GLEW_ATI_meminfo) {
349                 int stats[4];
350
351                 glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, stats);
352                 *freemem = stats[0];
353                 *totalmem = 0;
354         }
355         else {
356                 *totalmem = 0;
357                 *freemem = 0;
358         }
359 }
360