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