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