Apply the new ground_level method.
[crawl.git] / crawl-ref / source / glwrapper-ogl.cc
blob4e5395265754c26810137dced677a6ac248e32ea
1 #include "AppHdr.h"
3 #ifdef USE_TILE
4 #ifdef USE_GL
6 #include "glwrapper-ogl.h"
8 // How do we get access to the GL calls?
9 // If other UI types use the -ogl wrapper they should
10 // include more conditional includes here.
11 #ifdef USE_SDL
12 #ifdef USE_GLES
13 #include <SDL.h>
14 #include <SDL_gles.h>
15 #include <GLES/gl.h>
16 #else
17 #include <SDL_opengl.h>
18 #endif
19 #endif
21 #include "debug.h"
23 /////////////////////////////////////////////////////////////////////////////
24 // Static functions from GLStateManager
26 GLStateManager *glmanager = NULL;
28 void GLStateManager::init()
30 if (glmanager)
31 return;
33 glmanager = new OGLStateManager();
36 void GLStateManager::shutdown()
38 delete glmanager;
39 glmanager = NULL;
42 /////////////////////////////////////////////////////////////////////////////
43 // Static functions from GLShapeBuffer
45 GLShapeBuffer *GLShapeBuffer::create(bool texture, bool colour,
46 drawing_modes prim)
48 return (new OGLShapeBuffer(texture, colour, prim));
51 /////////////////////////////////////////////////////////////////////////////
52 // OGLStateManager
54 OGLStateManager::OGLStateManager()
56 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
57 glClearColor(0.0, 0.0, 0.0, 1.0f);
58 glDepthFunc(GL_LEQUAL);
61 void OGLStateManager::set(const GLState& state)
63 if (state.array_vertex != m_current_state.array_vertex)
65 if (state.array_vertex)
66 glEnableClientState(GL_VERTEX_ARRAY);
67 else
68 glDisableClientState(GL_VERTEX_ARRAY);
71 if (state.array_texcoord != m_current_state.array_texcoord)
73 if (state.array_texcoord)
74 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
75 else
76 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
79 if (state.array_colour != m_current_state.array_colour)
81 if (state.array_colour)
83 glEnableClientState(GL_COLOR_ARRAY);
85 else
87 glDisableClientState(GL_COLOR_ARRAY);
89 // [enne] This should *not* be necessary, but the Linux OpenGL
90 // driver that I'm using sets this to the last colour of the
91 // colour array. So, we need to unset it here.
92 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
96 if (state.texture != m_current_state.texture)
98 if (state.texture)
99 glEnable(GL_TEXTURE_2D);
100 else
101 glDisable(GL_TEXTURE_2D);
104 if (state.blend != m_current_state.blend)
106 if (state.blend)
107 glEnable(GL_BLEND);
108 else
109 glDisable(GL_BLEND);
112 if (state.depthtest != m_current_state.depthtest)
114 if (state.depthtest)
115 glEnable(GL_DEPTH_TEST);
116 else
117 glDisable(GL_DEPTH_TEST);
120 if (state.alphatest != m_current_state.alphatest
121 || state.alpharef != m_current_state.alpharef)
123 if (state.alphatest)
125 glEnable(GL_ALPHA_TEST);
126 glAlphaFunc(GL_NOTEQUAL, state.alpharef);
128 else
129 glDisable(GL_ALPHA_TEST);
132 if (state.colour != m_current_state.colour)
134 glColor4f(state.colour.r, state.colour.g,
135 state.colour.b, state.colour.a);
138 m_current_state = state;
141 void OGLStateManager::set_transform(const GLW_3VF &trans, const GLW_3VF &scale)
143 glLoadIdentity();
144 glTranslatef(trans.x, trans.y, trans.z);
145 glScalef(scale.x, scale.y, scale.z);
148 void OGLStateManager::reset_view_for_resize(const coord_def &m_windowsz)
150 glMatrixMode(GL_PROJECTION);
151 glLoadIdentity();
153 // For ease, vertex positions are pixel positions.
154 #ifdef USE_GLES
155 glOrthox(0, m_windowsz.x, m_windowsz.y, 0, -1000, 1000);
156 #else
157 glOrtho(0, m_windowsz.x, m_windowsz.y, 0, -1000, 1000);
158 #endif
161 void OGLStateManager::reset_transform()
163 glLoadIdentity();
164 glTranslatef(0,0,0);
165 glScalef(1,1,1);
168 void OGLStateManager::pixelstore_unpack_alignment(unsigned int bpp)
170 glPixelStorei(GL_UNPACK_ALIGNMENT, bpp);
173 void OGLStateManager::delete_textures(size_t count, unsigned int *textures)
175 glDeleteTextures(count, (GLuint*)textures);
178 void OGLStateManager::generate_textures(size_t count, unsigned int *textures)
180 glGenTextures(count, (GLuint*)textures);
183 void OGLStateManager::bind_texture(unsigned int texture)
185 glBindTexture(GL_TEXTURE_2D, texture);
188 void OGLStateManager::load_texture(unsigned char *pixels, unsigned int width,
189 unsigned int height, MipMapOptions mip_opt)
191 // Assumptions...
192 const unsigned int bpp = 4;
193 const GLenum texture_format = GL_RGBA;
194 const GLenum format = GL_UNSIGNED_BYTE;
195 // Also assume that the texture is already bound using bind_texture
197 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
198 #ifdef GL_CLAMP
199 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
200 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
201 #else
202 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
203 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
204 #endif
205 #ifndef USE_GLES
206 if (mip_opt == MIPMAP_CREATE)
208 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
209 GL_LINEAR_MIPMAP_NEAREST);
210 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
211 gluBuild2DMipmaps(GL_TEXTURE_2D, bpp, width, height,
212 texture_format, format, pixels);
214 else
215 #endif
217 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
218 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
219 glTexImage2D(GL_TEXTURE_2D, 0, bpp, width, height, 0,
220 texture_format, format, pixels);
224 void OGLStateManager::reset_view_for_redraw(float x, float y)
226 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
227 glMatrixMode(GL_MODELVIEW);
228 glLoadIdentity();
229 glTranslatef(x, y , 1.0f);
232 /////////////////////////////////////////////////////////////////////////////
233 // OGLShapeBuffer
235 OGLShapeBuffer::OGLShapeBuffer(bool texture, bool colour, drawing_modes prim) :
236 m_prim_type(prim),
237 m_texture_verts(texture),
238 m_colour_verts(colour)
240 ASSERT(prim == GLW_RECTANGLE || prim == GLW_LINES);
243 const char *OGLShapeBuffer::print_statistics() const
245 return (NULL);
248 unsigned int OGLShapeBuffer::size() const
250 return (m_position_buffer.size());
253 void OGLShapeBuffer::add(const GLWPrim &rect)
255 switch (m_prim_type)
257 case GLW_RECTANGLE:
258 add_rect(rect);
259 break;
260 case GLW_LINES:
261 add_line(rect);
262 break;
263 default:
264 die("Invalid primitive type");
265 break;
269 void OGLShapeBuffer::add_rect(const GLWPrim &rect)
271 // Copy vert positions
272 size_t last = m_position_buffer.size();
273 m_position_buffer.resize(last + 4);
274 m_position_buffer[last ].set(rect.pos_sx, rect.pos_sy, rect.pos_z);
275 m_position_buffer[last + 1].set(rect.pos_sx, rect.pos_ey, rect.pos_z);
276 m_position_buffer[last + 2].set(rect.pos_ex, rect.pos_sy, rect.pos_z);
277 m_position_buffer[last + 3].set(rect.pos_ex, rect.pos_ey, rect.pos_z);
279 // Copy texture coords if necessary
280 if (m_texture_verts)
282 last = m_texture_buffer.size();
283 m_texture_buffer.resize(last + 4);
284 m_texture_buffer[last ].set(rect.tex_sx, rect.tex_sy);
285 m_texture_buffer[last + 1].set(rect.tex_sx, rect.tex_ey);
286 m_texture_buffer[last + 2].set(rect.tex_ex, rect.tex_sy);
287 m_texture_buffer[last + 3].set(rect.tex_ex, rect.tex_ey);
290 // Copy vert colours if necessary
291 if (m_colour_verts)
293 last = m_colour_buffer.size();
294 m_colour_buffer.resize(last + 4);
295 m_colour_buffer[last ].set(rect.col_s);
296 m_colour_buffer[last + 1].set(rect.col_e);
297 m_colour_buffer[last + 2].set(rect.col_s);
298 m_colour_buffer[last + 3].set(rect.col_e);
301 // build indices
302 last = m_ind_buffer.size();
304 if (last > 3)
306 // This is not the first box so make FOUR degenerate triangles
307 m_ind_buffer.resize(last + 6);
308 unsigned short int val = m_ind_buffer[last - 1];
310 // the first three degens finish the previous box and move
311 // to the first position of the new one we just added and
312 // the fourth degen creates a triangle that is a line from p1 to p3
313 m_ind_buffer[last ] = val++;
314 m_ind_buffer[last + 1] = val;
316 // Now add as normal
317 m_ind_buffer[last + 2] = val++;
318 m_ind_buffer[last + 3] = val++;
319 m_ind_buffer[last + 4] = val++;
320 m_ind_buffer[last + 5] = val;
322 else
324 // This is the first box so don't bother making any degenerate triangles
325 m_ind_buffer.resize(last + 4);
326 m_ind_buffer[0] = 0;
327 m_ind_buffer[1] = 1;
328 m_ind_buffer[2] = 2;
329 m_ind_buffer[3] = 3;
333 void OGLShapeBuffer::add_line(const GLWPrim &rect)
335 // Copy vert positions
336 size_t last = m_position_buffer.size();
337 m_position_buffer.resize(last + 2);
338 m_position_buffer[last ].set(rect.pos_sx, rect.pos_sy, rect.pos_z);
339 m_position_buffer[last + 1].set(rect.pos_ex, rect.pos_ey, rect.pos_z);
341 // Copy texture coords if necessary
342 if (m_texture_verts)
344 last = m_texture_buffer.size();
345 m_texture_buffer.resize(last + 2);
346 m_texture_buffer[last ].set(rect.tex_sx, rect.tex_sy);
347 m_texture_buffer[last + 1].set(rect.tex_ex, rect.tex_ey);
350 // Copy vert colours if necessary
351 if (m_colour_verts)
353 last = m_colour_buffer.size();
354 m_colour_buffer.resize(last + 2);
355 m_colour_buffer[last ].set(rect.col_s);
356 m_colour_buffer[last + 1].set(rect.col_e);
360 // Draw the buffer
361 #if 0
362 void OGLShapeBuffer::draw(const GLState &state, const GLW_3VF *pt, const GLW_3VF *ps)
363 #endif
364 void OGLShapeBuffer::draw(const GLState &state)
366 if (m_position_buffer.size() == 0)
367 return;
369 if (!state.array_vertex)
370 return;
372 glmanager->set(state);
374 glVertexPointer(3, GL_FLOAT, 0, &m_position_buffer[0]);
376 if (state.array_texcoord && m_texture_verts)
377 glTexCoordPointer(2, GL_FLOAT, 0, &m_texture_buffer[0]);
379 if (state.array_colour && m_colour_verts)
380 glColorPointer(4, GL_UNSIGNED_BYTE, 0, &m_colour_buffer[0]);
382 switch (m_prim_type)
384 case GLW_RECTANGLE:
385 glDrawElements(GL_TRIANGLE_STRIP, m_ind_buffer.size(),
386 GL_UNSIGNED_SHORT, &m_ind_buffer[0]);
387 break;
388 case GLW_LINES:
389 glDrawArrays(GL_LINES, 0, m_position_buffer.size());
390 break;
391 default:
392 die("Invalid primitive type");
393 break;
397 void OGLShapeBuffer::clear()
399 m_position_buffer.clear();
400 m_ind_buffer.clear();
401 m_texture_buffer.clear();
402 m_colour_buffer.clear();
405 #endif // USE_GL
406 #endif // USE_TILE