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