GrGLExtensions.cpp revision 9e90aed5de82732cc9921f01388d3063a41a053b
1/*
2 * Copyright 2013 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "gl/GrGLExtensions.h"
9#include "gl/GrGLDefines.h"
10#include "gl/GrGLUtil.h"
11
12#include "SkTSearch.h"
13#include "SkTSort.h"
14
15namespace {
16inline bool extension_compare(const SkString& a, const SkString& b) {
17    return strcmp(a.c_str(), b.c_str()) < 0;
18}
19}
20
21bool GrGLExtensions::init(GrGLStandard standard,
22                          GrGLGetStringProc getString,
23                          GrGLGetStringiProc getStringi,
24                          GrGLGetIntegervProc getIntegerv) {
25    fStrings.reset();
26    if (NULL == getString) {
27        return false;
28    }
29
30    // glGetStringi and indexed extensions were added in version 3.0 of desktop GL and ES.
31    const GrGLubyte* verString = getString(GR_GL_VERSION);
32    if (NULL == verString) {
33        return false;
34    }
35    GrGLVersion version = GrGLGetVersionFromString((const char*) verString);
36    bool indexed = version >= GR_GL_VER(3, 0);
37
38    if (indexed) {
39        if (NULL == getStringi || NULL == getIntegerv) {
40            return false;
41        }
42        GrGLint extensionCnt = 0;
43        getIntegerv(GR_GL_NUM_EXTENSIONS, &extensionCnt);
44        fStrings.push_back_n(extensionCnt);
45        for (int i = 0; i < extensionCnt; ++i) {
46            const char* ext = (const char*) getStringi(GR_GL_EXTENSIONS, i);
47            fStrings[i] = ext;
48        }
49    } else {
50        const char* extensions = (const char*) getString(GR_GL_EXTENSIONS);
51        if (NULL == extensions) {
52            return false;
53        }
54        while (true) {
55            // skip over multiple spaces between extensions
56            while (' ' == *extensions) {
57                ++extensions;
58            }
59            // quit once we reach the end of the string.
60            if ('\0' == *extensions) {
61                break;
62            }
63            // we found an extension
64            size_t length = strcspn(extensions, " ");
65            fStrings.push_back().set(extensions, length);
66            extensions += length;
67        }
68    }
69    if (!fStrings.empty()) {
70        SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp;
71        SkTQSort(&fStrings.front(), &fStrings.back(), cmp);
72    }
73    return true;
74}
75
76bool GrGLExtensions::has(const char* ext) const {
77    if (fStrings.empty()) {
78        return false;
79    }
80    SkString extensionStr(ext);
81    int idx = SkTSearch<SkString, extension_compare>(&fStrings.front(),
82                                                     fStrings.count(),
83                                                     extensionStr,
84                                                     sizeof(SkString));
85    return idx >= 0;
86}
87
88void GrGLExtensions::print(const char* sep) const {
89    if (NULL == sep) {
90        sep = " ";
91    }
92    int cnt = fStrings.count();
93    for (int i = 0; i < cnt; ++i) {
94        GrPrintf("%s%s", fStrings[i].c_str(), (i < cnt - 1) ? sep : "");
95    }
96}
97