1 /* ResidualVM - A 3D game interpreter
2 *
3 * ResidualVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "graphics/opengl/context.h"
24
25 #include "common/debug.h"
26 #include "common/str.h"
27 #include "common/textconsole.h"
28 #include "common/tokenizer.h"
29
30 #include "graphics/opengl/system_headers.h"
31
32 #if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS) || defined(USE_GLES2)
33
34 namespace Common {
35 DECLARE_SINGLETON(OpenGL::ContextGL);
36 }
37
38 namespace OpenGL {
39
ContextGL()40 ContextGL::ContextGL() {
41 reset();
42 }
43
reset()44 void ContextGL::reset() {
45 maxTextureSize = 0;
46
47 NPOTSupported = false;
48 shadersSupported = false;
49 framebufferObjectSupported = false;
50 packedDepthStencilSupported = false;
51 unpackSubImageSupported = false;
52 framebufferObjectMultisampleSupported = false;
53 OESDepth24 = false;
54 multisampleMaxSamples = -1;
55 }
56
initialize(ContextOGLType contextType)57 void ContextGL::initialize(ContextOGLType contextType) {
58 // Initialize default state.
59 reset();
60
61 type = contextType;
62
63 // Obtain maximum texture size.
64 glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *)&maxTextureSize);
65 debug(5, "OpenGL maximum texture size: %d", maxTextureSize);
66
67 const char *extString = (const char *)glGetString(GL_EXTENSIONS);
68
69 bool ARBShaderObjects = false;
70 bool ARBShadingLanguage100 = false;
71 bool ARBVertexShader = false;
72 bool ARBFragmentShader = false;
73 bool EXTFramebufferMultisample = false;
74 bool EXTFramebufferBlit = false;
75
76 Common::StringTokenizer tokenizer(extString, " ");
77 while (!tokenizer.empty()) {
78 Common::String token = tokenizer.nextToken();
79
80 if (token == "GL_ARB_texture_non_power_of_two" || token == "GL_OES_texture_npot") {
81 NPOTSupported = true;
82 } else if (token == "GL_ARB_shader_objects") {
83 ARBShaderObjects = true;
84 } else if (token == "GL_ARB_shading_language_100") {
85 ARBShadingLanguage100 = true;
86 } else if (token == "GL_ARB_vertex_shader") {
87 ARBVertexShader = true;
88 } else if (token == "GL_ARB_fragment_shader") {
89 ARBFragmentShader = true;
90 } else if (token == "GL_EXT_framebuffer_object") {
91 framebufferObjectSupported = true;
92 } else if (token == "GL_EXT_packed_depth_stencil" || token == "GL_OES_packed_depth_stencil") {
93 packedDepthStencilSupported = true;
94 } else if (token == "GL_EXT_unpack_subimage") {
95 unpackSubImageSupported = true;
96 } else if (token == "GL_EXT_framebuffer_multisample") {
97 EXTFramebufferMultisample = true;
98 } else if (token == "GL_EXT_framebuffer_blit") {
99 EXTFramebufferBlit = true;
100 } else if (token == "GL_OES_depth24") {
101 OESDepth24 = true;
102 }
103
104 }
105
106 int glslVersion = getGLSLVersion();
107 debug(5, "OpenGL GLSL version: %d", glslVersion);
108
109 if (type == kOGLContextGLES2) {
110 // GLES2 always has (limited) NPOT support.
111 NPOTSupported = true;
112
113 // GLES2 always has shader support.
114 shadersSupported = true;
115
116 // GLES2 always has FBO support.
117 framebufferObjectSupported = true;
118
119 // ScummVM does not support multisample FBOs with GLES2 for now
120 framebufferObjectMultisampleSupported = false;
121 multisampleMaxSamples = -1;
122 } else {
123 shadersSupported = ARBShaderObjects && ARBShadingLanguage100 && ARBVertexShader && ARBFragmentShader && glslVersion >= 120;
124
125 // Desktop GL always has unpack sub-image support
126 unpackSubImageSupported = true;
127
128 framebufferObjectMultisampleSupported = EXTFramebufferMultisample && EXTFramebufferBlit;
129
130 if (framebufferObjectMultisampleSupported) {
131 glGetIntegerv(GL_MAX_SAMPLES, (GLint *)&multisampleMaxSamples);
132 }
133 }
134
135 // Log context type.
136 switch (type) {
137 case kOGLContextGL:
138 debug(5, "OpenGL: GL context initialized");
139 break;
140
141 case kOGLContextGLES2:
142 debug(5, "OpenGL: GLES2 context initialized");
143 break;
144 }
145
146 // Log features supported by GL context.
147 debug(5, "OpenGL: NPOT texture support: %d", NPOTSupported);
148 debug(5, "OpenGL: Shader support: %d", shadersSupported);
149 debug(5, "OpenGL: FBO support: %d", framebufferObjectSupported);
150 debug(5, "OpenGL: Packed depth stencil support: %d", packedDepthStencilSupported);
151 debug(5, "OpenGL: Unpack subimage support: %d", unpackSubImageSupported);
152 }
153
getGLSLVersion() const154 int ContextGL::getGLSLVersion() const {
155 const char *glslVersionString = (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION);
156 if (!glslVersionString) {
157 warning("Could not get GLSL version");
158 return 0;
159 }
160
161 const char *glslVersionFormat;
162 if (type == kOGLContextGL) {
163 glslVersionFormat = "%d.%d";
164 } else {
165 glslVersionFormat = "OpenGL ES GLSL ES %d.%d";
166 }
167
168 int glslMajorVersion, glslMinorVersion;
169 if (sscanf(glslVersionString, glslVersionFormat, &glslMajorVersion, &glslMinorVersion) != 2) {
170 warning("Could not parse GLSL version '%s'", glslVersionString);
171 return 0;
172 }
173
174 return glslMajorVersion * 100 + glslMinorVersion;
175 }
176
177 } // End of namespace OpenGL
178
179 #endif
180