gfx/gl/GLContextFeatures.cpp

branch
TOR_BUG_3246
changeset 7
129ffea94266
equal deleted inserted replaced
-1:000000000000 0:fd263f4d742f
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6
7 #include "GLContext.h"
8 #include "nsPrintfCString.h"
9
10 #ifdef XP_MACOSX
11 #include "nsCocoaFeatures.h"
12 #endif
13
14 namespace mozilla {
15 namespace gl {
16
17 const size_t kMAX_EXTENSION_GROUP_SIZE = 5;
18
19 // ARB_ES2_compatibility is natively supported in OpenGL 4.1.
20 static const unsigned int kGLCoreVersionForES2Compat = 410;
21
22 // ARB_ES3_compatibility is natively supported in OpenGL 4.3.
23 static const unsigned int kGLCoreVersionForES3Compat = 430;
24
25 struct FeatureInfo
26 {
27 const char* mName;
28 unsigned int mOpenGLVersion;
29 unsigned int mOpenGLESVersion;
30 GLContext::GLExtensions mExtensions[kMAX_EXTENSION_GROUP_SIZE];
31 };
32
33 static const FeatureInfo sFeatureInfoArr[] = {
34 {
35 "bind_buffer_offset",
36 0, // OpenGL version
37 0, // OpenGL ES version
38 {
39 GLContext::EXT_transform_feedback,
40 GLContext::NV_transform_feedback,
41 GLContext::Extensions_End
42 }
43 },
44 {
45 "blend_minmax",
46 200, // OpenGL version
47 300, // OpenGL ES version
48 {
49 GLContext::EXT_blend_minmax,
50 GLContext::Extensions_End
51 }
52 },
53 {
54 "depth_texture",
55 200, // OpenGL version
56 300, // OpenGL ES version
57 {
58 GLContext::ARB_depth_texture,
59 GLContext::OES_depth_texture,
60 // Intentionally avoid putting ANGLE_depth_texture here,
61 // it does not offer quite the same functionality.
62 GLContext::Extensions_End
63 }
64 },
65 {
66 "draw_buffers",
67 200, // OpenGL version
68 300, // OpenGL ES version
69 {
70 GLContext::ARB_draw_buffers,
71 GLContext::EXT_draw_buffers,
72 GLContext::Extensions_End
73 }
74 },
75 {
76 "draw_instanced",
77 310, // OpenGL version
78 300, // OpenGL ES version
79 {
80 GLContext::ARB_draw_instanced,
81 GLContext::EXT_draw_instanced,
82 GLContext::NV_draw_instanced,
83 GLContext::ANGLE_instanced_arrays,
84 GLContext::Extensions_End
85 }
86 },
87 {
88 "draw_range_elements",
89 120, // OpenGL version
90 300, // OpenGL ES version
91 {
92 GLContext::EXT_draw_range_elements,
93 GLContext::Extensions_End
94 }
95 },
96 {
97 "element_index_uint",
98 200, // OpenGL version
99 300, // OpenGL ES version
100 {
101 GLContext::OES_element_index_uint,
102 GLContext::Extensions_End
103 }
104 },
105 {
106 "ES2_compatibility",
107 kGLCoreVersionForES2Compat,
108 200, // OpenGL ES version
109 {
110 GLContext::ARB_ES2_compatibility,
111 GLContext::Extensions_End
112 }
113 },
114 {
115 "ES3_compatibility",
116 kGLCoreVersionForES3Compat,
117 300, // OpenGL ES version
118 {
119 GLContext::ARB_ES3_compatibility,
120 GLContext::Extensions_End
121 }
122 },
123 {
124 // Removes clamping for float color outputs from frag shaders.
125 "frag_color_float",
126 300, // OpenGL version
127 300, // OpenGL ES version
128 {
129 GLContext::ARB_color_buffer_float,
130 GLContext::EXT_color_buffer_float,
131 GLContext::EXT_color_buffer_half_float,
132 GLContext::Extensions_End
133 }
134 },
135 {
136 "frag_depth",
137 200, // OpenGL version
138 300, // OpenGL ES version
139 {
140 GLContext::EXT_frag_depth,
141 GLContext::Extensions_End
142 }
143 },
144 {
145 "framebuffer_blit",
146 300, // OpenGL version
147 300, // OpenGL ES version
148 {
149 GLContext::EXT_framebuffer_blit,
150 GLContext::ANGLE_framebuffer_blit,
151 GLContext::Extensions_End
152 }
153 },
154 {
155 "framebuffer_multisample",
156 300, // OpenGL version
157 300, // OpenGL ES version
158 {
159 GLContext::EXT_framebuffer_multisample,
160 GLContext::ANGLE_framebuffer_multisample,
161 GLContext::Extensions_End
162 }
163 },
164 {
165 "framebuffer_object",
166 300, // OpenGL version
167 200, // OpenGL ES version
168 {
169 GLContext::ARB_framebuffer_object,
170 GLContext::EXT_framebuffer_object,
171 GLContext::Extensions_End
172 }
173 },
174 {
175 "get_query_object_iv",
176 200, // OpenGL version
177 0, // OpenGL ES version
178 {
179 GLContext::Extensions_End
180 }
181 /*
182 * XXX_get_query_object_iv only provide GetQueryObjectiv provided by
183 * ARB_occlusion_query (added by OpenGL 2.0).
184 */
185 },
186 {
187 "instanced_arrays",
188 330, // OpenGL version
189 300, // OpenGL ES version
190 {
191 GLContext::ARB_instanced_arrays,
192 GLContext::NV_instanced_arrays,
193 GLContext::ANGLE_instanced_arrays,
194 GLContext::Extensions_End
195 }
196 },
197 {
198 "instanced_non_arrays",
199 330, // OpenGL version
200 300, // OpenGL ES version
201 {
202 GLContext::ARB_instanced_arrays,
203 GLContext::Extensions_End
204 }
205 /* This is an expanded version of `instanced_arrays` that allows for all
206 * enabled active attrib arrays to have non-zero divisors.
207 * ANGLE_instanced_arrays and NV_instanced_arrays forbid this, but GLES3
208 * has no such restriction.
209 */
210 },
211 {
212 "occlusion_query",
213 200, // OpenGL version
214 0, // OpenGL ES version
215 {
216 GLContext::Extensions_End
217 }
218 // XXX_occlusion_query depend on ARB_occlusion_query (added in OpenGL 2.0)
219 },
220 {
221 "occlusion_query_boolean",
222 kGLCoreVersionForES3Compat,
223 300, // OpenGL ES version
224 {
225 GLContext::ARB_ES3_compatibility,
226 GLContext::EXT_occlusion_query_boolean,
227 GLContext::Extensions_End
228 }
229 /*
230 * XXX_occlusion_query_boolean provide ANY_SAMPLES_PASSED_CONSERVATIVE,
231 * but EXT_occlusion_query_boolean is only a OpenGL ES extension. But
232 * it is supported on desktop if ARB_ES3_compatibility because
233 * EXT_occlusion_query_boolean (added in OpenGL ES 3.0).
234 */
235 },
236 {
237 "occlusion_query2",
238 330, // = min(330, kGLCoreVersionForES3Compat),
239 300, // OpenGL ES version
240 {
241 GLContext::ARB_occlusion_query2,
242 GLContext::ARB_ES3_compatibility,
243 GLContext::EXT_occlusion_query_boolean,
244 GLContext::Extensions_End
245 }
246 /*
247 * XXX_occlusion_query2 (add in OpenGL 3.3) provide ANY_SAMPLES_PASSED,
248 * which is provided by ARB_occlusion_query2, EXT_occlusion_query_boolean
249 * (added in OpenGL ES 3.0) and ARB_ES3_compatibility
250 */
251 },
252 {
253 "packed_depth_stencil",
254 300, // OpenGL version
255 300, // OpenGL ES version
256 {
257 GLContext::EXT_packed_depth_stencil,
258 GLContext::OES_packed_depth_stencil,
259 GLContext::Extensions_End
260 }
261 },
262 {
263 "query_objects",
264 200, // OpenGL version
265 300, // OpenGL ES version
266 {
267 GLContext::EXT_occlusion_query_boolean,
268 GLContext::Extensions_End
269 }
270 /*
271 * XXX_query_objects only provide entry points commonly supported by
272 * ARB_occlusion_query (added in OpenGL 2.0) and EXT_occlusion_query_boolean
273 * (added in OpenGL ES 3.0)
274 */
275 },
276 {
277 "renderbuffer_float",
278 300, // OpenGL version
279 300, // OpenGL ES version
280 {
281 GLContext::ARB_texture_float,
282 GLContext::EXT_color_buffer_float,
283 GLContext::Extensions_End
284 }
285 },
286 {
287 "renderbuffer_half_float",
288 300, // OpenGL version
289 300, // OpenGL ES version
290 {
291 GLContext::ARB_texture_float,
292 GLContext::EXT_color_buffer_half_float,
293 GLContext::Extensions_End
294 }
295 },
296 {
297 "robustness",
298 0, // OpenGL version
299 0, // OpenGL ES version
300 {
301 GLContext::ARB_robustness,
302 GLContext::EXT_robustness,
303 GLContext::Extensions_End
304 }
305 },
306 {
307 "sRGB",
308 300, // OpenGL version
309 300, // OpenGL ES version
310 {
311 GLContext::EXT_sRGB,
312 GLContext::Extensions_End
313 }
314 },
315 {
316 "standard_derivatives",
317 200, // OpenGL version
318 300, // OpenGL ES version
319 {
320 GLContext::OES_standard_derivatives,
321 GLContext::Extensions_End
322 }
323 },
324 {
325 "texture_float",
326 300, // OpenGL version
327 300, // OpenGL ES version
328 {
329 GLContext::ARB_texture_float,
330 GLContext::OES_texture_float,
331 GLContext::Extensions_End
332 }
333 },
334 {
335 "texture_float_linear",
336 310, // OpenGL version
337 300, // OpenGL ES version
338 {
339 GLContext::ARB_texture_float,
340 GLContext::OES_texture_float_linear,
341 GLContext::Extensions_End
342 }
343 },
344 {
345 "texture_half_float",
346 300, // OpenGL version
347 300, // OpenGL ES version
348 {
349 GLContext::ARB_half_float_pixel,
350 GLContext::ARB_texture_float,
351 GLContext::NV_half_float,
352 GLContext::Extensions_End
353 }
354 /**
355 * We are not including OES_texture_half_float in this feature, because:
356 * GL_HALF_FLOAT = 0x140B
357 * GL_HALF_FLOAT_ARB = 0x140B == GL_HALF_FLOAT
358 * GL_HALF_FLOAT_NV = 0x140B == GL_HALF_FLOAT
359 * GL_HALF_FLOAT_OES = 0x8D61 != GL_HALF_FLOAT
360 * WebGL handles this specifically with an OES_texture_half_float check.
361 */
362 },
363 {
364 "texture_half_float_linear",
365 310, // OpenGL version
366 300, // OpenGL ES version
367 {
368 GLContext::ARB_half_float_pixel,
369 GLContext::ARB_texture_float,
370 GLContext::NV_half_float,
371 GLContext::OES_texture_half_float_linear,
372 GLContext::Extensions_End
373 }
374 },
375 {
376 "texture_non_power_of_two",
377 200, // OpenGL version
378 300, // OpenGL ES version
379 {
380 GLContext::ARB_texture_non_power_of_two,
381 GLContext::OES_texture_npot,
382 GLContext::Extensions_End
383 }
384 },
385 {
386 "transform_feedback",
387 300, // OpenGL version
388 300, // OpenGL ES version
389 {
390 GLContext::EXT_transform_feedback,
391 GLContext::NV_transform_feedback,
392 GLContext::Extensions_End
393 }
394 },
395 {
396 "vertex_array_object",
397 300, // OpenGL version
398 300, // OpenGL ES version
399 {
400 GLContext::ARB_vertex_array_object,
401 GLContext::OES_vertex_array_object,
402 GLContext::APPLE_vertex_array_object,
403 GLContext::Extensions_End
404 }
405 }
406 };
407
408 static inline const FeatureInfo&
409 GetFeatureInfo(GLFeature feature)
410 {
411 static_assert(MOZ_ARRAY_LENGTH(sFeatureInfoArr) == size_t(GLFeature::EnumMax),
412 "Mismatched lengths for sFeatureInfoInfos and GLFeature enums");
413
414 MOZ_ASSERT(feature < GLFeature::EnumMax,
415 "GLContext::GetFeatureInfoInfo : unknown <feature>");
416
417 return sFeatureInfoArr[size_t(feature)];
418 }
419
420 static inline uint32_t
421 ProfileVersionForFeature(GLFeature feature, ContextProfile profile)
422 {
423 MOZ_ASSERT(profile != ContextProfile::Unknown,
424 "GLContext::ProfileVersionForFeature : unknown <profile>");
425
426 const FeatureInfo& featureInfo = GetFeatureInfo(feature);
427
428 if (profile == ContextProfile::OpenGLES) {
429 return featureInfo.mOpenGLESVersion;
430 }
431
432 return featureInfo.mOpenGLVersion;
433 }
434
435 static inline bool
436 IsFeatureIsPartOfProfileVersion(GLFeature feature,
437 ContextProfile profile, unsigned int version)
438 {
439 unsigned int profileVersion = ProfileVersionForFeature(feature, profile);
440
441 /**
442 * if `profileVersion` is zero, it means that no version of the profile
443 * added support for the feature.
444 */
445 return profileVersion && version >= profileVersion;
446 }
447
448 const char*
449 GLContext::GetFeatureName(GLFeature feature)
450 {
451 return GetFeatureInfo(feature).mName;
452 }
453
454 static bool
455 CanReadSRGBFromFBOTexture(GLContext* gl)
456 {
457 if (!gl->WorkAroundDriverBugs())
458 return true;
459
460 #ifdef XP_MACOSX
461 // Bug 843668:
462 // MacOSX 10.6 reports to support EXT_framebuffer_sRGB and
463 // EXT_texture_sRGB but fails to convert from sRGB to linear
464 // when writing to an sRGB texture attached to an FBO.
465 if (!nsCocoaFeatures::OnLionOrLater()) {
466 return false;
467 }
468 #endif // XP_MACOSX
469 return true;
470 }
471
472 void
473 GLContext::InitFeatures()
474 {
475 for (size_t feature_index = 0; feature_index < size_t(GLFeature::EnumMax); feature_index++)
476 {
477 GLFeature feature = GLFeature(feature_index);
478
479 if (IsFeatureIsPartOfProfileVersion(feature, mProfile, mVersion)) {
480 mAvailableFeatures[feature_index] = true;
481 continue;
482 }
483
484 mAvailableFeatures[feature_index] = false;
485
486 const FeatureInfo& featureInfo = GetFeatureInfo(feature);
487
488 for (size_t j = 0; true; j++)
489 {
490 MOZ_ASSERT(j < kMAX_EXTENSION_GROUP_SIZE, "kMAX_EXTENSION_GROUP_SIZE too small");
491
492 if (featureInfo.mExtensions[j] == GLContext::Extensions_End) {
493 break;
494 }
495
496 if (IsExtensionSupported(featureInfo.mExtensions[j])) {
497 mAvailableFeatures[feature_index] = true;
498 break;
499 }
500 }
501 }
502
503 // Bug 843668: Work around limitation of the feature system.
504 // For sRGB support under OpenGL to match OpenGL ES spec, check for both
505 // EXT_texture_sRGB and EXT_framebuffer_sRGB is required.
506 const bool aresRGBExtensionsAvailable =
507 IsExtensionSupported(EXT_texture_sRGB) &&
508 (IsExtensionSupported(ARB_framebuffer_sRGB) ||
509 IsExtensionSupported(EXT_framebuffer_sRGB));
510
511 mAvailableFeatures[size_t(GLFeature::sRGB)] =
512 aresRGBExtensionsAvailable &&
513 CanReadSRGBFromFBOTexture(this);
514 }
515
516 void
517 GLContext::MarkUnsupported(GLFeature feature)
518 {
519 mAvailableFeatures[size_t(feature)] = false;
520
521 const FeatureInfo& featureInfo = GetFeatureInfo(feature);
522
523 for (size_t i = 0; true; i++)
524 {
525 MOZ_ASSERT(i < kMAX_EXTENSION_GROUP_SIZE, "kMAX_EXTENSION_GROUP_SIZE too small");
526
527 if (featureInfo.mExtensions[i] == GLContext::Extensions_End) {
528 break;
529 }
530
531 MarkExtensionUnsupported(featureInfo.mExtensions[i]);
532 }
533
534 MOZ_ASSERT(!IsSupported(feature), "GLContext::MarkUnsupported has failed!");
535
536 NS_WARNING(nsPrintfCString("%s marked as unsupported", GetFeatureName(feature)).get());
537 }
538
539 } /* namespace gl */
540 } /* namespace mozilla */

mercurial