1//
2// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7#include "libGLESv2/Caps.h"
8#include "common/debug.h"
9#include "common/angleutils.h"
10
11#include "angle_gl.h"
12
13#include <algorithm>
14#include <sstream>
15
16namespace gl
17{
18
19TextureCaps::TextureCaps()
20    : texturable(false),
21      filterable(false),
22      renderable(false),
23      sampleCounts()
24{
25}
26
27GLuint TextureCaps::getMaxSamples() const
28{
29    return !sampleCounts.empty() ? *sampleCounts.rbegin() : 0;
30}
31
32GLuint TextureCaps::getNearestSamples(GLuint requestedSamples) const
33{
34    if (requestedSamples == 0)
35    {
36        return 0;
37    }
38
39    for (SupportedSampleSet::const_iterator i = sampleCounts.begin(); i != sampleCounts.end(); i++)
40    {
41        GLuint samples = *i;
42        if (samples >= requestedSamples)
43        {
44            return samples;
45        }
46    }
47
48    return 0;
49}
50
51void TextureCapsMap::insert(GLenum internalFormat, const TextureCaps &caps)
52{
53    mCapsMap.insert(std::make_pair(internalFormat, caps));
54}
55
56void TextureCapsMap::remove(GLenum internalFormat)
57{
58    InternalFormatToCapsMap::iterator i = mCapsMap.find(internalFormat);
59    if (i != mCapsMap.end())
60    {
61        mCapsMap.erase(i);
62    }
63}
64
65const TextureCaps &TextureCapsMap::get(GLenum internalFormat) const
66{
67    static TextureCaps defaultUnsupportedTexture;
68    InternalFormatToCapsMap::const_iterator iter = mCapsMap.find(internalFormat);
69    return (iter != mCapsMap.end()) ? iter->second : defaultUnsupportedTexture;
70}
71
72TextureCapsMap::const_iterator TextureCapsMap::begin() const
73{
74    return mCapsMap.begin();
75}
76
77TextureCapsMap::const_iterator TextureCapsMap::end() const
78{
79    return mCapsMap.end();
80}
81
82size_t TextureCapsMap::size() const
83{
84    return mCapsMap.size();
85}
86
87Extensions::Extensions()
88    : elementIndexUint(false),
89      packedDepthStencil(false),
90      getProgramBinary(false),
91      rgb8rgba8(false),
92      textureFormatBGRA8888(false),
93      readFormatBGRA(false),
94      pixelBufferObject(false),
95      mapBuffer(false),
96      mapBufferRange(false),
97      textureHalfFloat(false),
98      textureHalfFloatLinear(false),
99      textureFloat(false),
100      textureFloatLinear(false),
101      textureRG(false),
102      textureCompressionDXT1(false),
103      textureCompressionDXT3(false),
104      textureCompressionDXT5(false),
105      depthTextures(false),
106      textureNPOT(false),
107      drawBuffers(false),
108      textureStorage(false),
109      textureFilterAnisotropic(false),
110      maxTextureAnisotropy(false),
111      occlusionQueryBoolean(false),
112      fence(false),
113      timerQuery(false),
114      robustness(false),
115      blendMinMax(false),
116      framebufferBlit(false),
117      framebufferMultisample(false),
118      instancedArrays(false),
119      packReverseRowOrder(false),
120      standardDerivatives(false),
121      shaderTextureLOD(false),
122      fragDepth(false),
123      textureUsage(false),
124      translatedShaderSource(false),
125      colorBufferFloat(false)
126{
127}
128
129static void InsertExtensionString(const std::string &extension, bool supported, std::vector<std::string> *extensionVector)
130{
131    if (supported)
132    {
133        extensionVector->push_back(extension);
134    }
135}
136
137std::vector<std::string> Extensions::getStrings() const
138{
139    std::vector<std::string> extensionStrings;
140
141    //                   | Extension name                     | Supported flag          | Output vector   |
142    InsertExtensionString("GL_OES_element_index_uint",         elementIndexUint,         &extensionStrings);
143    InsertExtensionString("GL_OES_packed_depth_stencil",       packedDepthStencil,       &extensionStrings);
144    InsertExtensionString("GL_OES_get_program_binary",         getProgramBinary,         &extensionStrings);
145    InsertExtensionString("GL_OES_rgb8_rgba8",                 rgb8rgba8,                &extensionStrings);
146    InsertExtensionString("GL_EXT_texture_format_BGRA8888",    textureFormatBGRA8888,    &extensionStrings);
147    InsertExtensionString("GL_EXT_read_format_bgra",           readFormatBGRA,           &extensionStrings);
148    InsertExtensionString("GL_NV_pixel_buffer_object",         pixelBufferObject,        &extensionStrings);
149    InsertExtensionString("GL_OES_mapbuffer",                  mapBuffer,                &extensionStrings);
150    InsertExtensionString("GL_EXT_map_buffer_range",           mapBufferRange,           &extensionStrings);
151    InsertExtensionString("GL_OES_texture_half_float",         textureHalfFloat,         &extensionStrings);
152    InsertExtensionString("GL_OES_texture_half_float_linear",  textureHalfFloatLinear,   &extensionStrings);
153    InsertExtensionString("GL_OES_texture_float",              textureFloat,             &extensionStrings);
154    InsertExtensionString("GL_OES_texture_float_linear",       textureFloatLinear,       &extensionStrings);
155    InsertExtensionString("GL_EXT_texture_rg",                 textureRG,                &extensionStrings);
156    InsertExtensionString("GL_EXT_texture_compression_dxt1",   textureCompressionDXT1,   &extensionStrings);
157    InsertExtensionString("GL_ANGLE_texture_compression_dxt3", textureCompressionDXT3,   &extensionStrings);
158    InsertExtensionString("GL_ANGLE_texture_compression_dxt5", textureCompressionDXT5,   &extensionStrings);
159    InsertExtensionString("GL_EXT_sRGB",                       sRGB,                     &extensionStrings);
160    InsertExtensionString("GL_ANGLE_depth_texture",            depthTextures,            &extensionStrings);
161    InsertExtensionString("GL_EXT_texture_storage",            textureStorage,           &extensionStrings);
162    InsertExtensionString("GL_OES_texture_npot",               textureNPOT,              &extensionStrings);
163    InsertExtensionString("GL_EXT_draw_buffers",               drawBuffers,              &extensionStrings);
164    InsertExtensionString("GL_EXT_texture_filter_anisotropic", textureFilterAnisotropic, &extensionStrings);
165    InsertExtensionString("GL_EXT_occlusion_query_boolean",    occlusionQueryBoolean,    &extensionStrings);
166    InsertExtensionString("GL_NV_fence",                       fence,                    &extensionStrings);
167    InsertExtensionString("GL_ANGLE_timer_query",              timerQuery,               &extensionStrings);
168    InsertExtensionString("GL_EXT_robustness",                 robustness,               &extensionStrings);
169    InsertExtensionString("GL_EXT_blend_minmax",               blendMinMax,              &extensionStrings);
170    InsertExtensionString("GL_ANGLE_framebuffer_blit",         framebufferBlit,          &extensionStrings);
171    InsertExtensionString("GL_ANGLE_framebuffer_multisample",  framebufferMultisample,   &extensionStrings);
172    InsertExtensionString("GL_ANGLE_instanced_arrays",         instancedArrays,          &extensionStrings);
173    InsertExtensionString("GL_ANGLE_pack_reverse_row_order",   packReverseRowOrder,      &extensionStrings);
174    InsertExtensionString("GL_OES_standard_derivatives",       standardDerivatives,      &extensionStrings);
175    InsertExtensionString("GL_EXT_shader_texture_lod",         shaderTextureLOD,         &extensionStrings);
176    InsertExtensionString("GL_EXT_frag_depth",                 fragDepth,                &extensionStrings);
177    InsertExtensionString("GL_ANGLE_texture_usage",            textureUsage,             &extensionStrings);
178    InsertExtensionString("GL_ANGLE_translated_shader_source", translatedShaderSource,   &extensionStrings);
179    InsertExtensionString("GL_EXT_color_buffer_float",         colorBufferFloat,         &extensionStrings);
180
181    return extensionStrings;
182}
183
184static bool GetFormatSupport(const TextureCapsMap &textureCaps, const std::vector<GLenum> &requiredFormats,
185                             bool requiresFiltering, bool requiresRendering)
186{
187    for (size_t i = 0; i < requiredFormats.size(); i++)
188    {
189        const TextureCaps &cap = textureCaps.get(requiredFormats[i]);
190
191        if (requiresFiltering && !cap.filterable)
192        {
193            return false;
194        }
195
196        if (requiresRendering && !cap.renderable)
197        {
198            return false;
199        }
200    }
201
202    return true;
203}
204
205// Checks for GL_OES_rgb8_rgba8 support
206static bool DetermineRGB8AndRGBA8TextureSupport(const TextureCapsMap &textureCaps)
207{
208    std::vector<GLenum> requiredFormats;
209    requiredFormats.push_back(GL_RGB8);
210    requiredFormats.push_back(GL_RGBA8);
211
212    return GetFormatSupport(textureCaps, requiredFormats, true, true);
213}
214
215// Checks for GL_EXT_texture_format_BGRA8888 support
216static bool DetermineBGRA8TextureSupport(const TextureCapsMap &textureCaps)
217{
218    std::vector<GLenum> requiredFormats;
219    requiredFormats.push_back(GL_BGRA8_EXT);
220
221    return GetFormatSupport(textureCaps, requiredFormats, true, true);
222}
223
224// Checks for GL_OES_texture_half_float support
225static bool DetermineHalfFloatTextureSupport(const TextureCapsMap &textureCaps)
226{
227    std::vector<GLenum> requiredFormats;
228    requiredFormats.push_back(GL_RGB16F);
229    requiredFormats.push_back(GL_RGBA16F);
230
231    return GetFormatSupport(textureCaps, requiredFormats, false, true);
232}
233
234// Checks for GL_OES_texture_half_float_linear support
235static bool DetermineHalfFloatTextureFilteringSupport(const TextureCapsMap &textureCaps)
236{
237    std::vector<GLenum> requiredFormats;
238    requiredFormats.push_back(GL_RGB16F);
239    requiredFormats.push_back(GL_RGBA16F);
240
241    return GetFormatSupport(textureCaps, requiredFormats, true, false);
242}
243
244// Checks for GL_OES_texture_float support
245static bool DetermineFloatTextureSupport(const TextureCapsMap &textureCaps)
246{
247    std::vector<GLenum> requiredFormats;
248    requiredFormats.push_back(GL_RGB32F);
249    requiredFormats.push_back(GL_RGBA32F);
250
251    return GetFormatSupport(textureCaps, requiredFormats, false, true);
252}
253
254// Checks for GL_OES_texture_float_linear support
255static bool DetermineFloatTextureFilteringSupport(const TextureCapsMap &textureCaps)
256{
257    std::vector<GLenum> requiredFormats;
258    requiredFormats.push_back(GL_RGB32F);
259    requiredFormats.push_back(GL_RGBA32F);
260
261    return GetFormatSupport(textureCaps, requiredFormats, true, false);
262}
263
264// Checks for GL_EXT_texture_rg support
265static bool DetermineRGTextureSupport(const TextureCapsMap &textureCaps, bool checkHalfFloatFormats, bool checkFloatFormats)
266{
267    std::vector<GLenum> requiredFormats;
268    requiredFormats.push_back(GL_R8);
269    requiredFormats.push_back(GL_RG8);
270    if (checkHalfFloatFormats)
271    {
272        requiredFormats.push_back(GL_R16F);
273        requiredFormats.push_back(GL_RG16F);
274    }
275    if (checkFloatFormats)
276    {
277        requiredFormats.push_back(GL_R32F);
278        requiredFormats.push_back(GL_RG32F);
279    }
280
281    return GetFormatSupport(textureCaps, requiredFormats, true, false);
282}
283
284// Check for GL_EXT_texture_compression_dxt1
285static bool DetermineDXT1TextureSupport(const TextureCapsMap &textureCaps)
286{
287    std::vector<GLenum> requiredFormats;
288    requiredFormats.push_back(GL_COMPRESSED_RGB_S3TC_DXT1_EXT);
289    requiredFormats.push_back(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT);
290
291    return GetFormatSupport(textureCaps, requiredFormats, true, false);
292}
293
294// Check for GL_ANGLE_texture_compression_dxt3
295static bool DetermineDXT3TextureSupport(const TextureCapsMap &textureCaps)
296{
297    std::vector<GLenum> requiredFormats;
298    requiredFormats.push_back(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE);
299
300    return GetFormatSupport(textureCaps, requiredFormats, true, false);
301}
302
303// Check for GL_ANGLE_texture_compression_dxt5
304static bool DetermineDXT5TextureSupport(const TextureCapsMap &textureCaps)
305{
306    std::vector<GLenum> requiredFormats;
307    requiredFormats.push_back(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE);
308
309    return GetFormatSupport(textureCaps, requiredFormats, true, false);
310}
311
312// Check for GL_ANGLE_texture_compression_dxt5
313static bool DetermineSRGBTextureSupport(const TextureCapsMap &textureCaps)
314{
315    std::vector<GLenum> requiredFilterFormats;
316    requiredFilterFormats.push_back(GL_SRGB8);
317    requiredFilterFormats.push_back(GL_SRGB8_ALPHA8);
318
319    std::vector<GLenum> requiredRenderFormats;
320    requiredRenderFormats.push_back(GL_SRGB8_ALPHA8);
321
322    return GetFormatSupport(textureCaps, requiredFilterFormats, true, false) &&
323           GetFormatSupport(textureCaps, requiredRenderFormats, false, true);
324}
325
326// Check for GL_ANGLE_depth_texture
327static bool DetermineDepthTextureSupport(const TextureCapsMap &textureCaps)
328{
329    std::vector<GLenum> requiredFormats;
330    requiredFormats.push_back(GL_DEPTH_COMPONENT16);
331    requiredFormats.push_back(GL_DEPTH_COMPONENT32_OES);
332    requiredFormats.push_back(GL_DEPTH24_STENCIL8_OES);
333
334    return GetFormatSupport(textureCaps, requiredFormats, true, true);
335}
336
337// Check for GL_EXT_color_buffer_float
338static bool DetermineColorBufferFloatSupport(const TextureCapsMap &textureCaps)
339{
340    std::vector<GLenum> requiredFormats;
341    requiredFormats.push_back(GL_R16F);
342    requiredFormats.push_back(GL_RG16F);
343    requiredFormats.push_back(GL_RGBA16F);
344    requiredFormats.push_back(GL_R32F);
345    requiredFormats.push_back(GL_RG32F);
346    requiredFormats.push_back(GL_RGBA32F);
347    requiredFormats.push_back(GL_R11F_G11F_B10F);
348
349    return GetFormatSupport(textureCaps, requiredFormats, false, true);
350}
351
352void Extensions::setTextureExtensionSupport(const TextureCapsMap &textureCaps)
353{
354    rgb8rgba8 = DetermineRGB8AndRGBA8TextureSupport(textureCaps);
355    textureFormatBGRA8888 = DetermineBGRA8TextureSupport(textureCaps);
356    textureHalfFloat = DetermineHalfFloatTextureSupport(textureCaps);
357    textureHalfFloatLinear = DetermineHalfFloatTextureFilteringSupport(textureCaps);
358    textureFloat = DetermineFloatTextureSupport(textureCaps);
359    textureFloatLinear = DetermineFloatTextureFilteringSupport(textureCaps);
360    textureRG = DetermineRGTextureSupport(textureCaps, textureHalfFloat, textureFloat);
361    textureCompressionDXT1 = DetermineDXT1TextureSupport(textureCaps);
362    textureCompressionDXT3 = DetermineDXT3TextureSupport(textureCaps);
363    textureCompressionDXT5 = DetermineDXT5TextureSupport(textureCaps);
364    sRGB = DetermineSRGBTextureSupport(textureCaps);
365    depthTextures = DetermineDepthTextureSupport(textureCaps);
366    colorBufferFloat = DetermineColorBufferFloatSupport(textureCaps);
367}
368
369Caps::Caps()
370    : maxElementIndex(0),
371      max3DTextureSize(0),
372      max2DTextureSize(0),
373      maxArrayTextureLayers(0),
374      maxLODBias(0),
375      maxCubeMapTextureSize(0),
376      maxRenderbufferSize(0),
377      maxDrawBuffers(0),
378      maxColorAttachments(0),
379      maxViewportWidth(0),
380      maxViewportHeight(0),
381      minAliasedPointSize(0),
382      maxAliasedPointSize(0),
383      minAliasedLineWidth(0),
384      // Table 6.29
385      maxElementsIndices(0),
386      maxElementsVertices(0),
387      maxServerWaitTimeout(0),
388      // Table 6.31
389      maxVertexAttributes(0),
390      maxVertexUniformComponents(0),
391      maxVertexUniformVectors(0),
392      maxVertexUniformBlocks(0),
393      maxVertexOutputComponents(0),
394      maxVertexTextureImageUnits(0),
395      // Table 6.32
396      maxFragmentUniformComponents(0),
397      maxFragmentUniformVectors(0),
398      maxFragmentUniformBlocks(0),
399      maxFragmentInputComponents(0),
400      maxTextureImageUnits(0),
401      minProgramTexelOffset(0),
402      maxProgramTexelOffset(0),
403
404      maxUniformBufferBindings(0),
405      maxUniformBlockSize(0),
406      uniformBufferOffsetAlignment(0),
407      maxCombinedUniformBlocks(0),
408      maxCombinedVertexUniformComponents(0),
409      maxCombinedFragmentUniformComponents(0),
410      maxVaryingComponents(0),
411      maxVaryingVectors(0),
412      maxCombinedTextureImageUnits(0),
413
414      maxTransformFeedbackInterleavedComponents(0),
415      maxTransformFeedbackSeparateAttributes(0),
416      maxTransformFeedbackSeparateComponents(0)
417{
418}
419
420}
421