1096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger/*
2096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger * Copyright 2013 Google Inc.
3096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger *
4096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
5096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger * found in the LICENSE file.
6096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger */
7096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
8096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#include "gl/GrGLExtensions.h"
9096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#include "gl/GrGLDefines.h"
10096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#include "gl/GrGLUtil.h"
11096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
12096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#include "SkTSearch.h"
13096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#include "SkTSort.h"
14096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
15096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenbergernamespace {
167839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerinline bool extension_compare(const SkString& a, const SkString& b) {
177839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    return strcmp(a.c_str(), b.c_str()) < 0;
18096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger}
19096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger}
20096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
21096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenbergerbool GrGLExtensions::init(GrGLBinding binding,
22096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger                          GrGLGetStringProc getString,
23096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger                          GrGLGetStringiProc getStringi,
24096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger                          GrGLGetIntegervProc getIntegerv) {
25096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    fStrings.reset();
26096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    if (NULL == getString) {
27096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        return false;
28096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    }
290a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
300a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    // glGetStringi and indexed extensions were added in version 3.0 of desktop GL and ES.
310a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    const GrGLubyte* verString = getString(GR_GL_VERSION);
320a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    if (NULL == verString) {
330a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        return false;
34096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    }
350a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    GrGLVersion version = GrGLGetVersionFromString((const char*) verString);
360a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    bool indexed = version >= GR_GL_VER(3, 0);
370a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
38096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    if (indexed) {
39096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        if (NULL == getStringi || NULL == getIntegerv) {
40096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            return false;
41096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        }
42096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        GrGLint extensionCnt = 0;
43096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        getIntegerv(GR_GL_NUM_EXTENSIONS, &extensionCnt);
44096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        fStrings.push_back_n(extensionCnt);
45096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        for (int i = 0; i < extensionCnt; ++i) {
46096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            const char* ext = (const char*) getStringi(GR_GL_EXTENSIONS, i);
47096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            fStrings[i] = ext;
48096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        }
49096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    } else {
50096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        const char* extensions = (const char*) getString(GR_GL_EXTENSIONS);
51096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        if (NULL == extensions) {
52096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            return false;
53096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        }
54096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        while (true) {
55096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            // skip over multiple spaces between extensions
56096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            while (' ' == *extensions) {
57096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger                ++extensions;
58096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            }
59096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            // quit once we reach the end of the string.
60096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            if ('\0' == *extensions) {
61096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger                break;
62096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            }
63096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            // we found an extension
64096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            size_t length = strcspn(extensions, " ");
65096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            fStrings.push_back().set(extensions, length);
66096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            extensions += length;
67096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        }
68096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    }
6958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (!fStrings.empty()) {
707839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp;
71096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        SkTQSort(&fStrings.front(), &fStrings.back(), cmp);
72096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    }
73096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    return true;
74096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger}
75096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
76096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenbergerbool GrGLExtensions::has(const char* ext) const {
7758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (fStrings.empty()) {
7858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        return false;
7958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
80096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    SkString extensionStr(ext);
81096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    int idx = SkTSearch<SkString, extension_compare>(&fStrings.front(),
82096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger                                                     fStrings.count(),
83096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger                                                     extensionStr,
84096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger                                                     sizeof(SkString));
85096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    return idx >= 0;
86096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger}
877839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
887839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergervoid GrGLExtensions::print(const char* sep) const {
897839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (NULL == sep) {
907839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        sep = " ";
917839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
927839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    int cnt = fStrings.count();
937839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    for (int i = 0; i < cnt; ++i) {
947839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        GrPrintf("%s%s", fStrings[i].c_str(), (i < cnt - 1) ? sep : "");
957839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
967839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
97