Recognize llvmpipe renderer as software OpenGL
[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")) ||
177                  (strstr(renderer, "Gallium ") && strstr(renderer, " on ATI ")) ||
178                  (strstr(renderer, "Gallium ") && strstr(renderer, " on AMD ")))
179         {
180                 GG.device = GPU_DEVICE_ATI;
181                 GG.driver = GPU_DRIVER_OPENSOURCE;
182         }
183         else if (strstr(renderer, "Nouveau") || strstr(vendor, "nouveau")) {
184                 GG.device = GPU_DEVICE_NVIDIA;
185                 GG.driver = GPU_DRIVER_OPENSOURCE;
186         }
187         else if (strstr(vendor, "Mesa")) {
188                 GG.device = GPU_DEVICE_SOFTWARE;
189                 GG.driver = GPU_DRIVER_SOFTWARE;
190         }
191         else if (strstr(vendor, "Microsoft")) {
192                 GG.device = GPU_DEVICE_SOFTWARE;
193                 GG.driver = GPU_DRIVER_SOFTWARE;
194         }
195         else if (strstr(renderer, "Apple Software Renderer")) {
196                 GG.device = GPU_DEVICE_SOFTWARE;
197                 GG.driver = GPU_DRIVER_SOFTWARE;
198         }
199         else if (strstr(renderer, "llvmpipe")) {
200                 GG.device = GPU_DEVICE_SOFTWARE;
201                 GG.driver = GPU_DRIVER_SOFTWARE;
202         }
203         else {
204                 GG.device = GPU_DEVICE_ANY;
205                 GG.driver = GPU_DRIVER_ANY;
206         }
207
208         /* make sure double side isn't used by default and only getting enabled in places where it's
209          * really needed to prevent different unexpected behaviors like with intel gme965 card (sergey) */
210         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
211
212 #ifdef _WIN32
213         GG.os = GPU_OS_WIN;
214 #elif defined(__APPLE__)
215         GG.os = GPU_OS_MAC;
216 #else
217         GG.os = GPU_OS_UNIX;
218 #endif
219
220
221         /* df/dy calculation factors, those are dependent on driver */
222         if ((strstr(vendor, "ATI") && strstr(version, "3.3.10750"))) {
223                 GG.dfdyfactors[0] = 1.0;
224                 GG.dfdyfactors[1] = -1.0;
225         }
226         else if ((GG.device == GPU_DEVICE_INTEL) && (GG.os == GPU_OS_WIN) &&
227                  (strstr(version, "4.0.0 - Build 10.18.10.3308") ||
228                   strstr(version, "4.0.0 - Build 9.18.10.3186") ||
229                   strstr(version, "4.0.0 - Build 9.18.10.3165") ||
230                   strstr(version, "3.1.0 - Build 9.17.10.3347") ||
231                   strstr(version, "3.1.0 - Build 9.17.10.4101") ||
232                   strstr(version, "3.3.0 - Build 8.15.10.2618")))
233         {
234                 GG.dfdyfactors[0] = -1.0;
235                 GG.dfdyfactors[1] = 1.0;
236         }
237         else {
238                 GG.dfdyfactors[0] = 1.0;
239                 GG.dfdyfactors[1] = 1.0;
240         }
241
242
243         GPU_invalid_tex_init();
244         GPU_basic_shaders_init();
245 }
246
247 void gpu_extensions_exit(void)
248 {
249         GPU_basic_shaders_exit();
250         GPU_invalid_tex_free();
251 }
252
253 bool GPU_legacy_support(void)
254 {
255         /* return whether or not current GL context is compatible with legacy OpenGL */
256         static bool checked = false;
257         static bool support = true;
258
259         if (!checked) {
260                 if (GLEW_VERSION_3_2) {
261                         GLint profile;
262                         glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &profile);
263
264                         if (G.debug & G_DEBUG_GPU) {
265                                 printf("GL_CONTEXT_PROFILE_MASK = %#x (%s profile)\n", (unsigned int)profile,
266                                        (profile & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) ? "compatibility" :
267                                        (profile & GL_CONTEXT_CORE_PROFILE_BIT) ? "core" : "unknown");
268                         }
269
270                         if (profile == 0) {
271                                 /* workaround for nVidia's Linux driver */
272                                 support = GLEW_ARB_compatibility;
273                         }
274                         else {
275                                 support = profile & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT;
276                         }
277                 }
278                 else if (GLEW_VERSION_3_1) {
279                         support = GLEW_ARB_compatibility;
280                 }
281
282                 /* any OpenGL version <= 3.0 is legacy, so support remains true */
283
284                 checked = true;
285         }
286
287         return support;
288 }
289
290 bool GPU_full_non_power_of_two_support(void)
291 {
292         /* always supported on full GL but still relevant for OpenGL ES 2.0 where
293          * NPOT textures can't use mipmaps or repeat wrap mode */
294         return true;
295 }
296
297 bool GPU_display_list_support(void)
298 {
299         /* deprecated in GL 3
300          * supported on older GL and compatibility profile
301          * still queried by game engine
302          */
303         return true;
304 }
305
306 bool GPU_bicubic_bump_support(void)
307 {
308         return GLEW_VERSION_4_0 || (GLEW_ARB_texture_query_lod && GLEW_VERSION_3_0);
309 }
310
311 bool GPU_geometry_shader_support(void)
312 {
313         /* in GL 3.2 geometry shaders are fully supported
314          * core profile clashes with our other shaders so accept compatibility only
315          * other GL versions can use EXT_geometry_shader4 if available
316          */
317         return (GLEW_VERSION_3_2 && GPU_legacy_support()) || GLEW_EXT_geometry_shader4;
318 }
319
320 bool GPU_geometry_shader_support_via_extension(void)
321 {
322         return GLEW_EXT_geometry_shader4 && !(GLEW_VERSION_3_2 && GPU_legacy_support());
323 }
324
325 bool GPU_instanced_drawing_support(void)
326 {
327         return GLEW_VERSION_3_1 || GLEW_ARB_draw_instanced;
328 }
329
330 int GPU_color_depth(void)
331 {
332         return GG.colordepth;
333 }
334
335 bool GPU_mem_stats_supported(void)
336 {
337         return (GLEW_NVX_gpu_memory_info || (GLEW_ATI_meminfo)) && (G.debug & G_DEBUG_GPU_MEM);
338 }
339
340
341 void GPU_mem_stats_get(int *totalmem, int *freemem)
342 {
343         if (GLEW_NVX_gpu_memory_info) {
344                 /* returned value in Kb */
345                 glGetIntegerv(GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, totalmem);
346
347                 glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, freemem);
348         }
349         else if (GLEW_ATI_meminfo) {
350                 int stats[4];
351
352                 glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, stats);
353                 *freemem = stats[0];
354                 *totalmem = 0;
355         }
356         else {
357                 *totalmem = 0;
358                 *freemem = 0;
359         }
360 }