11744f97ea73384b9f75b0ccee0a36a213c681d3absalomon@google.com/* 21744f97ea73384b9f75b0ccee0a36a213c681d3absalomon@google.com * Copyright 2013 Google Inc. 31744f97ea73384b9f75b0ccee0a36a213c681d3absalomon@google.com * 41744f97ea73384b9f75b0ccee0a36a213c681d3absalomon@google.com * Use of this source code is governed by a BSD-style license that can be 51744f97ea73384b9f75b0ccee0a36a213c681d3absalomon@google.com * found in the LICENSE file. 61744f97ea73384b9f75b0ccee0a36a213c681d3absalomon@google.com */ 71744f97ea73384b9f75b0ccee0a36a213c681d3absalomon@google.com 81744f97ea73384b9f75b0ccee0a36a213c681d3absalomon@google.com#include "gl/GrGLExtensions.h" 91744f97ea73384b9f75b0ccee0a36a213c681d3absalomon@google.com#include "gl/GrGLDefines.h" 101744f97ea73384b9f75b0ccee0a36a213c681d3absalomon@google.com#include "gl/GrGLUtil.h" 111744f97ea73384b9f75b0ccee0a36a213c681d3absalomon@google.com 12ff436617d8f11297f0eff93ddd49fb9022d0843bbsalomon@google.com#include "SkTSearch.h" 13ff436617d8f11297f0eff93ddd49fb9022d0843bbsalomon@google.com#include "SkTSort.h" 14ff436617d8f11297f0eff93ddd49fb9022d0843bbsalomon@google.com 15d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.orgnamespace { // This cannot be static because it is used as a template parameter. 1620f7f173e05b60f541910d0c1da9850ac73e2958bsalomon@google.cominline bool extension_compare(const SkString& a, const SkString& b) { 1720f7f173e05b60f541910d0c1da9850ac73e2958bsalomon@google.com return strcmp(a.c_str(), b.c_str()) < 0; 18ff436617d8f11297f0eff93ddd49fb9022d0843bbsalomon@google.com} 19ff436617d8f11297f0eff93ddd49fb9022d0843bbsalomon@google.com} 20ff436617d8f11297f0eff93ddd49fb9022d0843bbsalomon@google.com 21d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.org// finds the index of ext in strings or a negative result if ext is not found. 22d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.orgstatic int find_string(const SkTArray<SkString>& strings, const char ext[]) { 23d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.org if (strings.empty()) { 24d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.org return -1; 25d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.org } 26d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.org SkString extensionStr(ext); 27d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.org int idx = SkTSearch<SkString, extension_compare>(&strings.front(), 28d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.org strings.count(), 29d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.org extensionStr, 30d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.org sizeof(SkString)); 31d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.org return idx; 32d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.org} 33d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.org 34d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.orgGrGLExtensions::GrGLExtensions(const GrGLExtensions& that) : fStrings(SkNEW(SkTArray<SkString>)) { 35d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.org *this = that; 36d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.org} 37d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.org 38d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.orgGrGLExtensions& GrGLExtensions::operator=(const GrGLExtensions& that) { 39d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.org *fStrings = *that.fStrings; 40d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.org fInitialized = that.fInitialized; 41d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.org return *this; 42d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.org} 43d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.org 449e90aed5de82732cc9921f01388d3063a41a053bcommit-bot@chromium.orgbool GrGLExtensions::init(GrGLStandard standard, 451744f97ea73384b9f75b0ccee0a36a213c681d3absalomon@google.com GrGLGetStringProc getString, 461744f97ea73384b9f75b0ccee0a36a213c681d3absalomon@google.com GrGLGetStringiProc getStringi, 471744f97ea73384b9f75b0ccee0a36a213c681d3absalomon@google.com GrGLGetIntegervProc getIntegerv) { 4890313cc36a6f43a3e9d3818aca536cd6631c222bcommit-bot@chromium.org fInitialized = false; 4990313cc36a6f43a3e9d3818aca536cd6631c222bcommit-bot@chromium.org fStrings->reset(); 5090313cc36a6f43a3e9d3818aca536cd6631c222bcommit-bot@chromium.org 511744f97ea73384b9f75b0ccee0a36a213c681d3absalomon@google.com if (NULL == getString) { 521744f97ea73384b9f75b0ccee0a36a213c681d3absalomon@google.com return false; 531744f97ea73384b9f75b0ccee0a36a213c681d3absalomon@google.com } 54726e621000582e4de7c9ce0f7e9950c3af4e5d9bcommit-bot@chromium.org 55726e621000582e4de7c9ce0f7e9950c3af4e5d9bcommit-bot@chromium.org // glGetStringi and indexed extensions were added in version 3.0 of desktop GL and ES. 56726e621000582e4de7c9ce0f7e9950c3af4e5d9bcommit-bot@chromium.org const GrGLubyte* verString = getString(GR_GL_VERSION); 57f4e67e3e5e5017284300a61e7bb046723a44b0cfcommit-bot@chromium.org GrGLVersion version = GrGLGetVersionFromString((const char*) verString); 58f4e67e3e5e5017284300a61e7bb046723a44b0cfcommit-bot@chromium.org if (GR_GL_INVALID_VER == version) { 59726e621000582e4de7c9ce0f7e9950c3af4e5d9bcommit-bot@chromium.org return false; 601744f97ea73384b9f75b0ccee0a36a213c681d3absalomon@google.com } 61f4e67e3e5e5017284300a61e7bb046723a44b0cfcommit-bot@chromium.org 62726e621000582e4de7c9ce0f7e9950c3af4e5d9bcommit-bot@chromium.org bool indexed = version >= GR_GL_VER(3, 0); 63726e621000582e4de7c9ce0f7e9950c3af4e5d9bcommit-bot@chromium.org 641744f97ea73384b9f75b0ccee0a36a213c681d3absalomon@google.com if (indexed) { 651744f97ea73384b9f75b0ccee0a36a213c681d3absalomon@google.com if (NULL == getStringi || NULL == getIntegerv) { 661744f97ea73384b9f75b0ccee0a36a213c681d3absalomon@google.com return false; 671744f97ea73384b9f75b0ccee0a36a213c681d3absalomon@google.com } 681744f97ea73384b9f75b0ccee0a36a213c681d3absalomon@google.com GrGLint extensionCnt = 0; 691744f97ea73384b9f75b0ccee0a36a213c681d3absalomon@google.com getIntegerv(GR_GL_NUM_EXTENSIONS, &extensionCnt); 7090313cc36a6f43a3e9d3818aca536cd6631c222bcommit-bot@chromium.org fStrings->push_back_n(extensionCnt); 711744f97ea73384b9f75b0ccee0a36a213c681d3absalomon@google.com for (int i = 0; i < extensionCnt; ++i) { 721744f97ea73384b9f75b0ccee0a36a213c681d3absalomon@google.com const char* ext = (const char*) getStringi(GR_GL_EXTENSIONS, i); 7390313cc36a6f43a3e9d3818aca536cd6631c222bcommit-bot@chromium.org (*fStrings)[i] = ext; 741744f97ea73384b9f75b0ccee0a36a213c681d3absalomon@google.com } 751744f97ea73384b9f75b0ccee0a36a213c681d3absalomon@google.com } else { 761744f97ea73384b9f75b0ccee0a36a213c681d3absalomon@google.com const char* extensions = (const char*) getString(GR_GL_EXTENSIONS); 77eed625df23ee83a94f1814c43744b1961b79adf1skia.committer@gmail.com if (NULL == extensions) { 781744f97ea73384b9f75b0ccee0a36a213c681d3absalomon@google.com return false; 791744f97ea73384b9f75b0ccee0a36a213c681d3absalomon@google.com } 801744f97ea73384b9f75b0ccee0a36a213c681d3absalomon@google.com while (true) { 81a22407283650ae570d8f93db0f4f6df266812716bsalomon@google.com // skip over multiple spaces between extensions 82a22407283650ae570d8f93db0f4f6df266812716bsalomon@google.com while (' ' == *extensions) { 83a22407283650ae570d8f93db0f4f6df266812716bsalomon@google.com ++extensions; 84a22407283650ae570d8f93db0f4f6df266812716bsalomon@google.com } 85a22407283650ae570d8f93db0f4f6df266812716bsalomon@google.com // quit once we reach the end of the string. 86a22407283650ae570d8f93db0f4f6df266812716bsalomon@google.com if ('\0' == *extensions) { 871744f97ea73384b9f75b0ccee0a36a213c681d3absalomon@google.com break; 881744f97ea73384b9f75b0ccee0a36a213c681d3absalomon@google.com } 89a22407283650ae570d8f93db0f4f6df266812716bsalomon@google.com // we found an extension 90a22407283650ae570d8f93db0f4f6df266812716bsalomon@google.com size_t length = strcspn(extensions, " "); 9190313cc36a6f43a3e9d3818aca536cd6631c222bcommit-bot@chromium.org fStrings->push_back().set(extensions, length); 92a22407283650ae570d8f93db0f4f6df266812716bsalomon@google.com extensions += length; 931744f97ea73384b9f75b0ccee0a36a213c681d3absalomon@google.com } 941744f97ea73384b9f75b0ccee0a36a213c681d3absalomon@google.com } 9590313cc36a6f43a3e9d3818aca536cd6631c222bcommit-bot@chromium.org if (!fStrings->empty()) { 9620f7f173e05b60f541910d0c1da9850ac73e2958bsalomon@google.com SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp; 9790313cc36a6f43a3e9d3818aca536cd6631c222bcommit-bot@chromium.org SkTQSort(&fStrings->front(), &fStrings->back(), cmp); 98a1d27cd07af36436a3c9c4495055fea5bbd219afbsalomon@google.com } 9990313cc36a6f43a3e9d3818aca536cd6631c222bcommit-bot@chromium.org fInitialized = true; 1001744f97ea73384b9f75b0ccee0a36a213c681d3absalomon@google.com return true; 1011744f97ea73384b9f75b0ccee0a36a213c681d3absalomon@google.com} 1021744f97ea73384b9f75b0ccee0a36a213c681d3absalomon@google.com 103d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.orgbool GrGLExtensions::has(const char ext[]) const { 104d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.org SkASSERT(fInitialized); 105d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.org return find_string(*fStrings, ext) >= 0; 106d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.org} 107d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.org 108d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.orgbool GrGLExtensions::remove(const char ext[]) { 109d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.org SkASSERT(fInitialized); 110d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.org int idx = find_string(*fStrings, ext); 111d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.org if (idx >= 0) { 112d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.org // This is not terribly effecient but we really only expect this function to be called at 113d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.org // most a handful of times when our test programs start. 114d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.org SkAutoTDelete< SkTArray<SkString> > oldStrings(fStrings.detach()); 115d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.org fStrings.reset(SkNEW(SkTArray<SkString>(oldStrings->count() - 1))); 116d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.org fStrings->push_back_n(idx, &oldStrings->front()); 117d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.org fStrings->push_back_n(oldStrings->count() - idx - 1, &(*oldStrings)[idx] + 1); 118d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.org return true; 119d8ed85101ee77ad2cb0c186a79d197698a75d246commit-bot@chromium.org } else { 12042db2e45137cf93bb1df7f9a1d4f71d45a3e8bd5bsalomon@google.com return false; 12142db2e45137cf93bb1df7f9a1d4f71d45a3e8bd5bsalomon@google.com } 1221744f97ea73384b9f75b0ccee0a36a213c681d3absalomon@google.com} 12300142c44057e5a7c156b17a4bfc98a9605cf3f18bsalomon@google.com 124a3baf3be0e2a3128fb73bd41d40d130f75a4dc86commit-bot@chromium.orgvoid GrGLExtensions::add(const char ext[]) { 125a3baf3be0e2a3128fb73bd41d40d130f75a4dc86commit-bot@chromium.org int idx = find_string(*fStrings, ext); 126a3baf3be0e2a3128fb73bd41d40d130f75a4dc86commit-bot@chromium.org if (idx < 0) { 127a3baf3be0e2a3128fb73bd41d40d130f75a4dc86commit-bot@chromium.org // This is not the most effecient approach since we end up doing a full sort of the 128a3baf3be0e2a3128fb73bd41d40d130f75a4dc86commit-bot@chromium.org // extensions after the add 129a3baf3be0e2a3128fb73bd41d40d130f75a4dc86commit-bot@chromium.org fStrings->push_back().set(ext); 130a3baf3be0e2a3128fb73bd41d40d130f75a4dc86commit-bot@chromium.org SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp; 131a3baf3be0e2a3128fb73bd41d40d130f75a4dc86commit-bot@chromium.org SkTQSort(&fStrings->front(), &fStrings->back(), cmp); 132a3baf3be0e2a3128fb73bd41d40d130f75a4dc86commit-bot@chromium.org } 133a3baf3be0e2a3128fb73bd41d40d130f75a4dc86commit-bot@chromium.org} 134a3baf3be0e2a3128fb73bd41d40d130f75a4dc86commit-bot@chromium.org 13500142c44057e5a7c156b17a4bfc98a9605cf3f18bsalomon@google.comvoid GrGLExtensions::print(const char* sep) const { 13600142c44057e5a7c156b17a4bfc98a9605cf3f18bsalomon@google.com if (NULL == sep) { 13700142c44057e5a7c156b17a4bfc98a9605cf3f18bsalomon@google.com sep = " "; 13800142c44057e5a7c156b17a4bfc98a9605cf3f18bsalomon@google.com } 13990313cc36a6f43a3e9d3818aca536cd6631c222bcommit-bot@chromium.org int cnt = fStrings->count(); 14000142c44057e5a7c156b17a4bfc98a9605cf3f18bsalomon@google.com for (int i = 0; i < cnt; ++i) { 14190313cc36a6f43a3e9d3818aca536cd6631c222bcommit-bot@chromium.org GrPrintf("%s%s", (*fStrings)[i].c_str(), (i < cnt - 1) ? sep : ""); 14200142c44057e5a7c156b17a4bfc98a9605cf3f18bsalomon@google.com } 14300142c44057e5a7c156b17a4bfc98a9605cf3f18bsalomon@google.com} 144