0c2f11b1f741ae06fdc654cd59bf094d53516469
[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_extensions.h"
42 #include "GPU_glew.h"
43 #include "GPU_texture.h"
44
45 #include "intern/gpu_private.h"
46
47 #include <stdlib.h>
48 #include <stdio.h>
49 #include <string.h>
50
51 #ifdef WIN32
52 #  include "BLI_winstuff.h"
53 #endif
54
55 /* Extensions support */
56
57 /* -- extension: version of GL that absorbs it
58  * EXT_gpu_shader4: 3.0
59  * ARB_framebuffer object: 3.0
60  * EXT_framebuffer_multisample_blit_scaled: ???
61  * ARB_draw_instanced: 3.1
62  * ARB_texture_multisample: 3.2
63  * ARB_texture_query_lod: 4.0
64  */
65
66 static struct GPUGlobal {
67         GLint maxtexsize;
68         GLint maxtexlayers;
69         GLint maxcubemapsize;
70         GLint maxtextures;
71         GLint maxubosize;
72         GLint maxubobinds;
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 int GPU_max_texture_size(void)
95 {
96         return GG.maxtexsize;
97 }
98
99 int GPU_max_texture_layers(void)
100 {
101         return GG.maxtexlayers;
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 int GPU_max_ubo_binds(void)
125 {
126         return GG.maxubobinds;
127 }
128
129 int GPU_max_ubo_size(void)
130 {
131         return GG.maxubosize;
132 }
133
134 void GPU_get_dfdy_factors(float fac[2])
135 {
136         copy_v2_v2(fac, GG.dfdyfactors);
137 }
138
139 void gpu_extensions_init(void)
140 {
141         /* during 2.8 development each platform has its own OpenGL minimum requirements
142          * final 2.8 release will be unified on OpenGL 3.3 core profile, no required extensions
143          * see developer.blender.org/T49012 for details
144          */
145         BLI_assert(GLEW_VERSION_3_3);
146
147         glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &GG.maxtextures);
148
149         glGetIntegerv(GL_MAX_TEXTURE_SIZE, &GG.maxtexsize);
150         glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &GG.maxtexlayers);
151         glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &GG.maxcubemapsize);
152
153         if (GLEW_EXT_texture_filter_anisotropic)
154                 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &GG.max_anisotropy);
155         else
156                 GG.max_anisotropy = 1.0f;
157
158         glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS, &GG.maxubobinds);
159         glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &GG.maxubosize);
160
161 #ifndef NDEBUG
162         GLint ret;
163         glBindFramebuffer(GL_FRAMEBUFFER, 0);
164         glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_FRONT_LEFT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &ret);
165         /* We expect FRONT_LEFT to be the default buffer. */
166         BLI_assert(ret == GL_FRAMEBUFFER_DEFAULT);
167 #endif
168
169         GLint r, g, b;
170         glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_FRONT_LEFT, GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE, &r);
171         glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_FRONT_LEFT, GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE, &g);
172         glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_FRONT_LEFT, GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE, &b);
173         GG.colordepth = r + g + b; /* Assumes same depth for RGB. */
174
175         if (GLEW_VERSION_3_2 || GLEW_ARB_texture_multisample) {
176                 glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &GG.samples_color_texture_max);
177         }
178
179         const char *vendor = (const char *)glGetString(GL_VENDOR);
180         const char *renderer = (const char *)glGetString(GL_RENDERER);
181         const char *version = (const char *)glGetString(GL_VERSION);
182
183         if (strstr(vendor, "ATI") || strstr(vendor, "AMD")) {
184                 GG.device = GPU_DEVICE_ATI;
185                 GG.driver = GPU_DRIVER_OFFICIAL;
186         }
187         else if (strstr(vendor, "NVIDIA")) {
188                 GG.device = GPU_DEVICE_NVIDIA;
189                 GG.driver = GPU_DRIVER_OFFICIAL;
190         }
191         else if (strstr(vendor, "Intel") ||
192                  /* src/mesa/drivers/dri/intel/intel_context.c */
193                  strstr(renderer, "Mesa DRI Intel") ||
194                  strstr(renderer, "Mesa DRI Mobile Intel"))
195         {
196                 GG.device = GPU_DEVICE_INTEL;
197                 GG.driver = GPU_DRIVER_OFFICIAL;
198         }
199         else if ((strstr(renderer, "Mesa DRI R")) ||
200                  (strstr(renderer, "Radeon") && strstr(vendor, "X.Org")) ||
201                  (strstr(renderer, "Gallium ") && strstr(renderer, " on ATI ")) ||
202                  (strstr(renderer, "Gallium ") && strstr(renderer, " on AMD ")))
203         {
204                 GG.device = GPU_DEVICE_ATI;
205                 GG.driver = GPU_DRIVER_OPENSOURCE;
206         }
207         else if (strstr(renderer, "Nouveau") || strstr(vendor, "nouveau")) {
208                 GG.device = GPU_DEVICE_NVIDIA;
209                 GG.driver = GPU_DRIVER_OPENSOURCE;
210         }
211         else if (strstr(vendor, "Mesa")) {
212                 GG.device = GPU_DEVICE_SOFTWARE;
213                 GG.driver = GPU_DRIVER_SOFTWARE;
214         }
215         else if (strstr(vendor, "Microsoft")) {
216                 GG.device = GPU_DEVICE_SOFTWARE;
217                 GG.driver = GPU_DRIVER_SOFTWARE;
218         }
219         else if (strstr(renderer, "Apple Software Renderer")) {
220                 GG.device = GPU_DEVICE_SOFTWARE;
221                 GG.driver = GPU_DRIVER_SOFTWARE;
222         }
223         else {
224                 printf("Warning: Could not find a matching GPU name. Things may not behave as expected.\n");
225                 GG.device = GPU_DEVICE_ANY;
226                 GG.driver = GPU_DRIVER_ANY;
227         }
228
229 #ifdef _WIN32
230         GG.os = GPU_OS_WIN;
231 #elif defined(__APPLE__)
232         GG.os = GPU_OS_MAC;
233 #else
234         GG.os = GPU_OS_UNIX;
235 #endif
236
237
238         /* df/dy calculation factors, those are dependent on driver */
239         if ((strstr(vendor, "ATI") && strstr(version, "3.3.10750"))) {
240                 GG.dfdyfactors[0] = 1.0;
241                 GG.dfdyfactors[1] = -1.0;
242         }
243         else if ((GG.device == GPU_DEVICE_INTEL) && (GG.os == GPU_OS_WIN) &&
244                  (strstr(version, "4.0.0 - Build 10.18.10.3308") ||
245                   strstr(version, "4.0.0 - Build 9.18.10.3186") ||
246                   strstr(version, "4.0.0 - Build 9.18.10.3165") ||
247                   strstr(version, "3.1.0 - Build 9.17.10.3347") ||
248                   strstr(version, "3.1.0 - Build 9.17.10.4101") ||
249                   strstr(version, "3.3.0 - Build 8.15.10.2618")))
250         {
251                 GG.dfdyfactors[0] = -1.0;
252                 GG.dfdyfactors[1] = 1.0;
253         }
254         else {
255                 GG.dfdyfactors[0] = 1.0;
256                 GG.dfdyfactors[1] = 1.0;
257         }
258
259
260         GPU_invalid_tex_init();
261 }
262
263 void gpu_extensions_exit(void)
264 {
265         GPU_invalid_tex_free();
266 }
267
268 bool GPU_full_non_power_of_two_support(void)
269 {
270         /* always supported on full GL but still relevant for OpenGL ES 2.0 where
271          * NPOT textures can't use mipmaps or repeat wrap mode */
272         return true;
273 }
274
275 bool GPU_bicubic_bump_support(void)
276 {
277         return GLEW_VERSION_4_0 || (GLEW_ARB_texture_query_lod && GLEW_VERSION_3_0);
278 }
279
280 int GPU_color_depth(void)
281 {
282         return GG.colordepth;
283 }
284
285 bool GPU_mem_stats_supported(void)
286 {
287         return (GLEW_NVX_gpu_memory_info || GLEW_ATI_meminfo) && (G.debug & G_DEBUG_GPU_MEM);
288 }
289
290
291 void GPU_mem_stats_get(int *totalmem, int *freemem)
292 {
293         /* TODO(merwin): use Apple's platform API to get this info */
294
295         if (GLEW_NVX_gpu_memory_info) {
296                 /* returned value in Kb */
297                 glGetIntegerv(GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, totalmem);
298
299                 glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, freemem);
300         }
301         else if (GLEW_ATI_meminfo) {
302                 int stats[4];
303
304                 glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, stats);
305                 *freemem = stats[0];
306                 *totalmem = 0;
307         }
308         else {
309                 *totalmem = 0;
310                 *freemem = 0;
311         }
312 }