1 /*
2 * Copyright (C) 2003-2011 Neverball authors
3 *
4 * NEVERBALL is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published
6 * by the Free Software Foundation; either version 2 of the License,
7 * or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 */
14
15 #include <SDL.h>
16 #include <stdio.h>
17
18 #include "glext.h"
19 #include "log.h"
20
21 struct gl_info gli;
22
23 /*---------------------------------------------------------------------------*/
24
25 #if !ENABLE_OPENGLES
26
27 PFNGLCLIENTACTIVETEXTURE_PROC glClientActiveTexture_;
28 PFNGLACTIVETEXTURE_PROC glActiveTexture_;
29
30 PFNGLGENBUFFERS_PROC glGenBuffers_;
31 PFNGLBINDBUFFER_PROC glBindBuffer_;
32 PFNGLBUFFERDATA_PROC glBufferData_;
33 PFNGLBUFFERSUBDATA_PROC glBufferSubData_;
34 PFNGLDELETEBUFFERS_PROC glDeleteBuffers_;
35 PFNGLISBUFFER_PROC glIsBuffer_;
36
37 PFNGLPOINTPARAMETERF_PROC glPointParameterf_;
38 PFNGLPOINTPARAMETERFV_PROC glPointParameterfv_;
39
40 PFNGLGETSHADERIV_PROC glGetShaderiv_;
41 PFNGLGETSHADERINFOLOG_PROC glGetShaderInfoLog_;
42 PFNGLGETPROGRAMIV_PROC glGetProgramiv_;
43 PFNGLGETPROGRAMINFOLOG_PROC glGetProgramInfoLog_;
44 PFNGLCREATESHADER_PROC glCreateShader_;
45 PFNGLCREATEPROGRAM_PROC glCreateProgram_;
46 PFNGLSHADERSOURCE_PROC glShaderSource_;
47 PFNGLCOMPILESHADER_PROC glCompileShader_;
48 PFNGLDELETESHADER_PROC glDeleteShader_;
49 PFNGLDELETEPROGRAM_PROC glDeleteProgram_;
50 PFNGLATTACHSHADER_PROC glAttachShader_;
51 PFNGLLINKPROGRAM_PROC glLinkProgram_;
52 PFNGLUSEPROGRAM_PROC glUseProgram_;
53 PFNGLGETUNIFORMLOCATION_PROC glGetUniformLocation_;
54 PFNGLUNIFORM1F_PROC glUniform1f_;
55 PFNGLUNIFORM2F_PROC glUniform2f_;
56 PFNGLUNIFORM3F_PROC glUniform3f_;
57 PFNGLUNIFORM4F_PROC glUniform4f_;
58
59 PFNGLBINDFRAMEBUFFER_PROC glBindFramebuffer_;
60 PFNGLDELETEFRAMEBUFFERS_PROC glDeleteFramebuffers_;
61 PFNGLGENFRAMEBUFFERS_PROC glGenFramebuffers_;
62 PFNGLFRAMEBUFFERTEXTURE2D_PROC glFramebufferTexture2D_;
63 PFNGLCHECKFRAMEBUFFERSTATUS_PROC glCheckFramebufferStatus_;
64
65 PFNGLSTRINGMARKERGREMEDY_PROC glStringMarkerGREMEDY_;
66
67 #endif
68
69 /*---------------------------------------------------------------------------*/
70
glext_check(const char * needle)71 int glext_check(const char *needle)
72 {
73 const GLubyte *haystack, *c;
74
75 /* Search for the given string in the OpenGL extension strings. */
76
77 for (haystack = glGetString(GL_EXTENSIONS); *haystack; haystack++)
78 {
79 for (c = (const GLubyte *) needle; *c && *haystack; c++, haystack++)
80 if (*c != *haystack)
81 break;
82
83 if ((*c == 0) && (*haystack == ' ' || *haystack == '\0'))
84 return 1;
85 }
86
87 return 0;
88 }
89
glext_assert(const char * ext)90 int glext_assert(const char *ext)
91 {
92 if (!glext_check(ext))
93 {
94 log_printf("Missing required OpenGL extension (%s)\n", ext);
95 return 0;
96 }
97 return 1;
98 }
99
100 /*---------------------------------------------------------------------------*/
101
102 #define SDL_GL_GFPA(fun, str) do { \
103 ptr = SDL_GL_GetProcAddress(str); \
104 memcpy(&fun, &ptr, sizeof (void *)); \
105 } while(0)
106
107 /*---------------------------------------------------------------------------*/
108
glext_fail(const char * title,const char * message)109 int glext_fail(const char *title, const char *message)
110 {
111 SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, title, message, NULL);
112 return 0;
113 }
114
glext_init(void)115 int glext_init(void)
116 {
117 void *ptr = 0;
118
119 memset(&gli, 0, sizeof (struct gl_info));
120
121 /* Common init. */
122
123 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gli.max_texture_size);
124 glGetIntegerv(GL_MAX_TEXTURE_UNITS, &gli.max_texture_units);
125
126 /* Desktop init. */
127
128 #if !ENABLE_OPENGLES
129
130 if (glext_assert("ARB_multitexture"))
131 {
132 SDL_GL_GFPA(glClientActiveTexture_, "glClientActiveTextureARB");
133 SDL_GL_GFPA(glActiveTexture_, "glActiveTextureARB");
134 }
135
136 if (glext_assert("ARB_vertex_buffer_object"))
137 {
138 SDL_GL_GFPA(glGenBuffers_, "glGenBuffersARB");
139 SDL_GL_GFPA(glBindBuffer_, "glBindBufferARB");
140 SDL_GL_GFPA(glBufferData_, "glBufferDataARB");
141 SDL_GL_GFPA(glBufferSubData_, "glBufferSubDataARB");
142 SDL_GL_GFPA(glDeleteBuffers_, "glDeleteBuffersARB");
143 SDL_GL_GFPA(glIsBuffer_, "glIsBufferARB");
144 }
145
146 if (glext_assert("ARB_point_parameters"))
147 {
148 SDL_GL_GFPA(glPointParameterf_, "glPointParameterfARB");
149 SDL_GL_GFPA(glPointParameterfv_, "glPointParameterfvARB");
150 }
151
152 if (glext_check("ARB_shader_objects"))
153 {
154 SDL_GL_GFPA(glGetShaderiv_, "glGetShaderiv");
155 SDL_GL_GFPA(glGetShaderInfoLog_, "glGetShaderInfoLog");
156 SDL_GL_GFPA(glGetProgramiv_, "glGetProgramiv");
157 SDL_GL_GFPA(glGetProgramInfoLog_, "glGetProgramInfoLog");
158 SDL_GL_GFPA(glCreateShader_, "glCreateShader");
159 SDL_GL_GFPA(glCreateProgram_, "glCreateProgram");
160 SDL_GL_GFPA(glShaderSource_, "glShaderSource");
161 SDL_GL_GFPA(glCompileShader_, "glCompileShader");
162 SDL_GL_GFPA(glDeleteShader_, "glDeleteShader");
163 SDL_GL_GFPA(glDeleteProgram_, "glDeleteProgram");
164 SDL_GL_GFPA(glAttachShader_, "glAttachShader");
165 SDL_GL_GFPA(glLinkProgram_, "glLinkProgram");
166 SDL_GL_GFPA(glUseProgram_, "glUseProgram");
167 SDL_GL_GFPA(glGetUniformLocation_, "glGetUniformLocation");
168 SDL_GL_GFPA(glUniform1f_, "glUniform1f");
169 SDL_GL_GFPA(glUniform2f_, "glUniform2f");
170 SDL_GL_GFPA(glUniform3f_, "glUniform3f");
171 SDL_GL_GFPA(glUniform4f_, "glUniform4f");
172
173 gli.shader_objects = 1;
174 }
175
176 if (glext_check("ARB_framebuffer_object"))
177 {
178 SDL_GL_GFPA(glBindFramebuffer_, "glBindFramebuffer");
179 SDL_GL_GFPA(glDeleteFramebuffers_, "glDeleteFramebuffers");
180 SDL_GL_GFPA(glGenFramebuffers_, "glGenFramebuffers");
181 SDL_GL_GFPA(glFramebufferTexture2D_, "glFramebufferTexture2D");
182 SDL_GL_GFPA(glCheckFramebufferStatus_, "glCheckFramebufferStatus");
183
184 gli.framebuffer_object = 1;
185 }
186
187 if (glext_check("GREMEDY_string_marker"))
188 SDL_GL_GFPA(glStringMarkerGREMEDY_, "glStringMarkerGREMEDY");
189
190 #endif
191
192 return 1;
193 }
194
195 /*---------------------------------------------------------------------------*/
196
glClipPlane4f_(GLenum p,GLfloat a,GLfloat b,GLfloat c,GLfloat d)197 void glClipPlane4f_(GLenum p, GLfloat a, GLfloat b, GLfloat c, GLfloat d)
198 {
199 #if ENABLE_OPENGLES
200
201 GLfloat v[4];
202
203 v[0] = a;
204 v[1] = b;
205 v[2] = c;
206 v[3] = d;
207
208 glClipPlanef(p, v);
209
210 #else
211
212 GLdouble v[4];
213
214 v[0] = a;
215 v[1] = b;
216 v[2] = c;
217 v[3] = d;
218
219 glClipPlane(p, v);
220
221 #endif
222 }
223
224 /*---------------------------------------------------------------------------*/
225