1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "GLExtensions.h"
18 
19 #include <string>
20 #include <unordered_set>
21 
22 #include <stdint.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 
26 ANDROID_SINGLETON_STATIC_INSTANCE(android::renderengine::gl::GLExtensions)
27 
28 namespace android {
29 namespace renderengine {
30 namespace gl {
31 
32 namespace {
33 
34 class ExtensionSet {
35 public:
ExtensionSet(const char * extensions)36     ExtensionSet(const char* extensions) {
37         char const* curr = extensions;
38         char const* head = curr;
39         do {
40             head = strchr(curr, ' ');
41             size_t len = head ? head - curr : strlen(curr);
42             if (len > 0) {
43                 mExtensions.emplace(curr, len);
44             }
45             curr = head + 1;
46         } while (head);
47     }
48 
hasExtension(const char * extension) const49     bool hasExtension(const char* extension) const { return mExtensions.count(extension) > 0; }
50 
51 private:
52     std::unordered_set<std::string> mExtensions;
53 };
54 
55 } // anonymous namespace
56 
initWithGLStrings(GLubyte const * vendor,GLubyte const * renderer,GLubyte const * version,GLubyte const * extensions)57 void GLExtensions::initWithGLStrings(GLubyte const* vendor, GLubyte const* renderer,
58                                      GLubyte const* version, GLubyte const* extensions) {
59     mVendor = (char const*)vendor;
60     mRenderer = (char const*)renderer;
61     mVersion = (char const*)version;
62     mExtensions = (char const*)extensions;
63 
64     ExtensionSet extensionSet(mExtensions.c_str());
65     if (extensionSet.hasExtension("GL_EXT_protected_textures")) {
66         mHasProtectedTexture = true;
67     }
68 }
69 
getVendor() const70 char const* GLExtensions::getVendor() const {
71     return mVendor.string();
72 }
73 
getRenderer() const74 char const* GLExtensions::getRenderer() const {
75     return mRenderer.string();
76 }
77 
getVersion() const78 char const* GLExtensions::getVersion() const {
79     return mVersion.string();
80 }
81 
getExtensions() const82 char const* GLExtensions::getExtensions() const {
83     return mExtensions.string();
84 }
85 
initWithEGLStrings(char const * eglVersion,char const * eglExtensions)86 void GLExtensions::initWithEGLStrings(char const* eglVersion, char const* eglExtensions) {
87     mEGLVersion = eglVersion;
88     mEGLExtensions = eglExtensions;
89 
90     ExtensionSet extensionSet(eglExtensions);
91 
92     // EGL_ANDROIDX_no_config_context is an experimental extension with no
93     // written specification. It will be replaced by something more formal.
94     // SurfaceFlinger is using it to allow a single EGLContext to render to
95     // both a 16-bit primary display framebuffer and a 32-bit virtual display
96     // framebuffer.
97     //
98     // EGL_KHR_no_config_context is official extension to allow creating a
99     // context that works with any surface of a display.
100     if (extensionSet.hasExtension("EGL_ANDROIDX_no_config_context") ||
101         extensionSet.hasExtension("EGL_KHR_no_config_context")) {
102         mHasNoConfigContext = true;
103     }
104 
105     if (extensionSet.hasExtension("EGL_ANDROID_native_fence_sync")) {
106         mHasNativeFenceSync = true;
107     }
108     if (extensionSet.hasExtension("EGL_KHR_fence_sync")) {
109         mHasFenceSync = true;
110     }
111     if (extensionSet.hasExtension("EGL_KHR_wait_sync")) {
112         mHasWaitSync = true;
113     }
114     if (extensionSet.hasExtension("EGL_EXT_protected_content")) {
115         mHasProtectedContent = true;
116     }
117     if (extensionSet.hasExtension("EGL_IMG_context_priority")) {
118         mHasContextPriority = true;
119     }
120     if (extensionSet.hasExtension("EGL_KHR_surfaceless_context")) {
121         mHasSurfacelessContext = true;
122     }
123 }
124 
getEGLVersion() const125 char const* GLExtensions::getEGLVersion() const {
126     return mEGLVersion.string();
127 }
128 
getEGLExtensions() const129 char const* GLExtensions::getEGLExtensions() const {
130     return mEGLExtensions.string();
131 }
132 
133 } // namespace gl
134 } // namespace renderengine
135 } // namespace android
136