1 #include "AppHdr.h"
2
3 #ifdef USE_TILE_LOCAL
4 #ifdef USE_GL
5
6 #include "glwrapper-ogl.h"
7
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 # ifdef __ANDROID__
14 # include <SDL.h>
15 # else
16 # include <SDL2/SDL.h>
17 # include <SDL_gles.h>
18 # endif
19 # include <GLES/gl.h>
20 # else
21 # ifdef __ANDROID__
22 # include <SDL.h>
23 # include <GLES/gl.h>
24 # else
25 # include <SDL_opengl.h>
26 # if defined(__MACOSX__)
27 # include <OpenGL/glu.h>
28 # else
29 # include <GL/glu.h>
30 # endif
31 # endif
32 # endif
33 #endif
34
35 #include "options.h"
36 #include "stringutil.h"
37 #include "tilesdl.h"
38
39 #ifdef __ANDROID__
40 # include <android/log.h>
41 #endif
42
43 // TODO: if this gets big enough, pull out into opengl-utils.cc/h or sth
44 namespace opengl
45 {
check_texture_size(const char * name,int width,int height)46 bool check_texture_size(const char *name, int width, int height)
47 {
48 int max_texture_size;
49 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
50 if (width > max_texture_size || height > max_texture_size)
51 {
52 mprf(MSGCH_ERROR,
53 "Texture %s is bigger than maximum driver texture size "
54 "(%d,%d vs. %d). Sprites from this texture will not display "
55 "properly.",
56 name, width, height, max_texture_size);
57 return false;
58 }
59 return true;
60 }
61
_gl_error_to_string(GLenum e)62 static string _gl_error_to_string(GLenum e)
63 {
64 switch (e)
65 {
66 case GL_NO_ERROR:
67 return "GL_NO_ERROR";
68 case GL_INVALID_ENUM:
69 return "GL_INVALID_ENUM";
70 case GL_INVALID_VALUE:
71 return "GL_INVALID_VALUE";
72 case GL_INVALID_OPERATION:
73 return "GL_INVALID_OPERATION";
74 case GL_INVALID_FRAMEBUFFER_OPERATION:
75 return "GL_INVALID_FRAMEBUFFER_OPERATION";
76 case GL_OUT_OF_MEMORY:
77 return "GL_OUT_OF_MEMORY (fatal)";
78 case GL_STACK_UNDERFLOW:
79 return "GL_STACK_UNDERFLOW";
80 case GL_STACK_OVERFLOW:
81 return "GL_STACK_OVERFLOW";
82 default:
83 return make_stringf("Unknown OpenGL error %d", e);
84 }
85 }
86
87 /**
88 * Log any opengl errors to console. Will crash if a really bad one occurs.
89 *
90 * @return true if there were any errors.
91 */
flush_opengl_errors()92 bool flush_opengl_errors()
93 {
94 GLenum e = GL_NO_ERROR;
95 bool fatal = false;
96 bool errors = false;
97 do
98 {
99 e = glGetError();
100 if (e != GL_NO_ERROR)
101 {
102 errors = true;
103 if (e == GL_OUT_OF_MEMORY)
104 fatal = true;
105 mprf(MSGCH_ERROR, "OpenGL error %s",
106 _gl_error_to_string(e).c_str());
107 }
108 } while (e != GL_NO_ERROR);
109 if (fatal)
110 die("Fatal OpenGL error; giving up");
111 return errors;
112 }
113 }
114
115 /////////////////////////////////////////////////////////////////////////////
116 // Static functions from GLStateManager
117
118 GLStateManager *glmanager = nullptr;
119
init()120 void GLStateManager::init()
121 {
122 if (glmanager)
123 return;
124
125 glmanager = new OGLStateManager();
126 }
127
shutdown()128 void GLStateManager::shutdown()
129 {
130 delete glmanager;
131 glmanager = nullptr;
132 }
133
134 /////////////////////////////////////////////////////////////////////////////
135 // Static functions from GLShapeBuffer
136
create(bool texture,bool colour,drawing_modes prim)137 GLShapeBuffer *GLShapeBuffer::create(bool texture, bool colour,
138 drawing_modes prim)
139 {
140 return new OGLShapeBuffer(texture, colour, prim);
141 }
142
143 /////////////////////////////////////////////////////////////////////////////
144 // OGLStateManager
145
OGLStateManager()146 OGLStateManager::OGLStateManager()
147 {
148 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
149 glClearColor(0.0, 0.0, 0.0, 1.0f);
150 glDepthFunc(GL_LEQUAL);
151
152 #ifdef __ANDROID__
153 m_last_tex = 0;
154 #endif
155 m_window_height = 0;
156 }
157
set(const GLState & state)158 void OGLStateManager::set(const GLState& state)
159 {
160 if (state.array_vertex != m_current_state.array_vertex)
161 {
162 if (state.array_vertex)
163 {
164 glEnableClientState(GL_VERTEX_ARRAY);
165 glDebug("glEnableClientState(GL_VERTEX_ARRAY)");
166 }
167 else
168 {
169 glDisableClientState(GL_VERTEX_ARRAY);
170 glDebug("glDisableClientState(GL_VERTEX_ARRAY)");
171 }
172 }
173
174 if (state.array_texcoord != m_current_state.array_texcoord)
175 {
176 if (state.array_texcoord)
177 {
178 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
179 glDebug("glEnableClientState(GL_TEXTURE_COORD_ARRAY)");
180 }
181 else
182 {
183 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
184 glDebug("glDisableClientState(GL_TEXTURE_COORD_ARRAY)");
185 }
186 }
187
188 if (state.array_colour != m_current_state.array_colour)
189 {
190 if (state.array_colour)
191 {
192 glEnableClientState(GL_COLOR_ARRAY);
193 glDebug("glEnableClientState(GL_COLOR_ARRAY)");
194 }
195 else
196 {
197 glDisableClientState(GL_COLOR_ARRAY);
198 glDebug("glDisableClientState(GL_COLOR_ARRAY)");
199
200 // [enne] This should *not* be necessary, but the Linux OpenGL
201 // driver that I'm using sets this to the last colour of the
202 // colour array. So, we need to unset it here.
203 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
204 glDebug("glColor4f(1.0f, 1.0f, 1.0f, 1.0f)");
205 }
206 }
207
208 if (state.texture != m_current_state.texture)
209 {
210 if (state.texture)
211 {
212 glEnable(GL_TEXTURE_2D);
213 glDebug("glEnable(GL_TEXTURE_2D)");
214 }
215 else
216 {
217 glDisable(GL_TEXTURE_2D);
218 glDebug("glDisable(GL_TEXTURE_2D)");
219 }
220 }
221
222 if (state.blend != m_current_state.blend)
223 {
224 if (state.blend)
225 {
226 glEnable(GL_BLEND);
227 glDebug("glEnable(GL_BLEND)");
228 }
229 else
230 {
231 glDisable(GL_BLEND);
232 glDebug("glDisable(GL_BLEND)");
233 }
234 }
235
236 if (state.depthtest != m_current_state.depthtest)
237 {
238 if (state.depthtest)
239 {
240 glEnable(GL_DEPTH_TEST);
241 glDebug("glEnable(GL_DEPTH_TEST)");
242 }
243 else
244 {
245 glDisable(GL_DEPTH_TEST);
246 glDebug("glEnable(GL_DEPTH_TEST)");
247 }
248 }
249
250 if (state.alphatest != m_current_state.alphatest
251 || state.alpharef != m_current_state.alpharef)
252 {
253 if (state.alphatest)
254 {
255 glEnable(GL_ALPHA_TEST);
256 glAlphaFunc(GL_NOTEQUAL, state.alpharef);
257 glDebug("glAlphaFunc(GL_NOTEQUAL, state.alpharef)");
258 }
259 else
260 {
261 glDisable(GL_ALPHA_TEST);
262 glDebug("glDisable(GL_ALPHA_TEST)");
263 }
264 }
265
266 if (state.colour != m_current_state.colour)
267 {
268 glColor4f(state.colour.r, state.colour.g,
269 state.colour.b, state.colour.a);
270 glDebug("glColor4f");
271 }
272
273 m_current_state = state;
274 }
275
276 struct {
277 GLW_3VF trans, scale;
278 } current_transform;
279
set_transform(const GLW_3VF & trans,const GLW_3VF & scale)280 void OGLStateManager::set_transform(const GLW_3VF &trans, const GLW_3VF &scale)
281 {
282 glLoadIdentity();
283 glTranslatef(trans.x, trans.y, trans.z);
284 glScalef(scale.x, scale.y, scale.z);
285 current_transform = { trans, scale };
286 }
287
reset_transform()288 void OGLStateManager::reset_transform()
289 {
290 set_transform({0,0,0}, {1,1,1});
291 }
292
get_transform(GLW_3VF * trans,GLW_3VF * scale)293 void OGLStateManager::get_transform(GLW_3VF *trans, GLW_3VF *scale)
294 {
295 if (trans) *trans = current_transform.trans;
296 if (scale) *scale = current_transform.scale;
297 }
298
logical_to_device(int n) const299 int OGLStateManager::logical_to_device(int n) const
300 {
301 return display_density.logical_to_device(n);
302 }
303
device_to_logical(int n,bool round) const304 int OGLStateManager::device_to_logical(int n, bool round) const
305 {
306 return display_density.device_to_logical(n, round);
307 }
308
set_scissor(int x,int y,unsigned int w,unsigned int h)309 void OGLStateManager::set_scissor(int x, int y, unsigned int w, unsigned int h)
310 {
311 glEnable(GL_SCISSOR_TEST);
312 glScissor(logical_to_device(x), logical_to_device(m_window_height-y-h),
313 logical_to_device(w), logical_to_device(h));
314 }
315
reset_scissor()316 void OGLStateManager::reset_scissor()
317 {
318 glDisable(GL_SCISSOR_TEST);
319 }
320
reset_view_for_resize(const coord_def & m_windowsz,const coord_def & m_drawablesz)321 void OGLStateManager::reset_view_for_resize(const coord_def &m_windowsz,
322 const coord_def &m_drawablesz)
323 {
324 glViewport(0, 0, m_drawablesz.x, m_drawablesz.y);
325 m_window_height = m_windowsz.y;
326
327 glMatrixMode(GL_PROJECTION);
328 glLoadIdentity();
329
330 // For ease, vertex positions are pixel positions.
331 #ifdef USE_GLES
332 # ifdef __ANDROID__
333 glOrthof(0, m_windowsz.x, m_windowsz.y, 0, -1000, 1000);
334 # else
335 glOrthox(0, m_windowsz.x, m_windowsz.y, 0, -1000, 1000);
336 # endif
337 #else
338 glOrtho(0, m_windowsz.x, m_windowsz.y, 0, -1000, 1000);
339 #endif
340 glDebug("glOrthof");
341 }
342
pixelstore_unpack_alignment(unsigned int bpp)343 void OGLStateManager::pixelstore_unpack_alignment(unsigned int bpp)
344 {
345 glPixelStorei(GL_UNPACK_ALIGNMENT, bpp);
346 glDebug("glPixelStorei");
347 }
348
delete_textures(size_t count,unsigned int * textures)349 void OGLStateManager::delete_textures(size_t count, unsigned int *textures)
350 {
351 glDeleteTextures(count, (GLuint*)textures);
352 glDebug("glDeleteTextures");
353 }
354
generate_textures(size_t count,unsigned int * textures)355 void OGLStateManager::generate_textures(size_t count, unsigned int *textures)
356 {
357 glGenTextures(count, (GLuint*)textures);
358 glDebug("glGenTextures");
359 }
360
bind_texture(unsigned int texture)361 void OGLStateManager::bind_texture(unsigned int texture)
362 {
363 glBindTexture(GL_TEXTURE_2D, texture);
364 glDebug("glBindTexture");
365 #ifdef __ANDROID__
366 m_last_tex = texture;
367 #endif
368 }
369
load_texture(unsigned char * pixels,unsigned int width,unsigned int height,MipMapOptions mip_opt,int xoffset,int yoffset)370 void OGLStateManager::load_texture(unsigned char *pixels, unsigned int width,
371 unsigned int height, MipMapOptions mip_opt,
372 int xoffset, int yoffset)
373 {
374 // Assumptions...
375 #ifdef __ANDROID__
376 const GLenum bpp = GL_RGBA;
377 #else
378 const unsigned int bpp = 4;
379 #endif
380 const GLenum texture_format = GL_RGBA;
381 const GLenum format = GL_UNSIGNED_BYTE;
382 // Also assume that the texture is already bound using bind_texture
383
384 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
385 glDebug("glTexEnvf");
386
387 #ifdef GL_CLAMP
388 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
389 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
390 #else
391 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
392 glDebug("glTexParameterf GL_TEXTURE_WRAP_S");
393 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
394 glDebug("glTexParameterf GL_TEXTURE_WRAP_T");
395 #endif
396 #ifndef USE_GLES
397 if (mip_opt == MIPMAP_CREATE)
398 {
399 // TODO: should min react to Options.tile_filter_scaling?
400 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
401 GL_LINEAR_MIPMAP_NEAREST);
402 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
403 Options.tile_filter_scaling ? GL_LINEAR : GL_NEAREST);
404 gluBuild2DMipmaps(GL_TEXTURE_2D, bpp, width, height,
405 texture_format, format, pixels);
406 }
407 else
408 #endif
409 {
410 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
411 Options.tile_filter_scaling ? GL_LINEAR : GL_NEAREST);
412 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
413 Options.tile_filter_scaling ? GL_LINEAR : GL_NEAREST);
414 if (xoffset >= 0 && yoffset >= 0)
415 {
416 glTexSubImage2D(GL_TEXTURE_2D, 0, xoffset, yoffset, width, height,
417 texture_format, format, pixels);
418 glDebug("glTexSubImage2D");
419 }
420 else
421 {
422 glTexImage2D(GL_TEXTURE_2D, 0, bpp, width, height, 0,
423 texture_format, format, pixels);
424 glDebug("glTexImage2D");
425 }
426 }
427 }
428
reset_view_for_redraw()429 void OGLStateManager::reset_view_for_redraw()
430 {
431 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
432 glMatrixMode(GL_MODELVIEW);
433 glLoadIdentity();
434
435 glTranslatef(0.0f, 0.0f, 1.0f);
436 glDebug("glTranslatef");
437 }
438
439 #ifdef __ANDROID__
fixup_gl_state()440 void OGLStateManager::fixup_gl_state()
441 {
442 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
443 glClearColor(0.0, 0.0, 0.0, 1.0f);
444 glDepthFunc(GL_LEQUAL);
445
446 glEnable(GL_TEXTURE_2D);
447 glBindTexture(GL_TEXTURE_2D, m_last_tex);
448 glDebug("glBindTexture (REBIND)");
449 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
450 glDebug("glTexEnvf (REBIND)");
451
452 if (m_current_state.array_vertex)
453 {
454 glEnableClientState(GL_VERTEX_ARRAY);
455 glDebug("glEnableClientState(GL_VERTEX_ARRAY)");
456 }
457 else
458 {
459 glDisableClientState(GL_VERTEX_ARRAY);
460 glDebug("glDisableClientState(GL_VERTEX_ARRAY)");
461 }
462 if (m_current_state.array_texcoord)
463 {
464 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
465 glDebug("glEnableClientState(GL_TEXTURE_COORD_ARRAY)");
466 }
467 else
468 {
469 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
470 glDebug("glDisableClientState(GL_TEXTURE_COORD_ARRAY)");
471 }
472 if (m_current_state.array_colour)
473 {
474 glEnableClientState(GL_COLOR_ARRAY);
475 glDebug("glEnableClientState(GL_COLOR_ARRAY)");
476 glColor4f(m_current_state.colour.r, m_current_state.colour.g,
477 m_current_state.colour.b, m_current_state.colour.a);
478 glDebug("glColor4f");
479 }
480 else
481 {
482 glDisableClientState(GL_COLOR_ARRAY);
483 glDebug("glDisableClientState(GL_COLOR_ARRAY)");
484
485 // [enne] This should *not* be necessary, but the Linux OpenGL
486 // driver that I'm using sets this to the last colour of the
487 // colour array. So, we need to unset it here.
488 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
489 glDebug("glColor4f(1.0f, 1.0f, 1.0f, 1.0f)");
490 }
491 if (m_current_state.texture)
492 {
493 // glEnable(GL_TEXTURE_2D);
494 // glDebug("glEnable(GL_TEXTURE_2D)");
495 }
496 else
497 {
498 glDisable(GL_TEXTURE_2D);
499 glDebug("glDisable(GL_TEXTURE_2D)");
500 }
501 if (m_current_state.blend)
502 {
503 glEnable(GL_BLEND);
504 glDebug("glEnable(GL_BLEND)");
505 }
506 else
507 {
508 glDisable(GL_BLEND);
509 glDebug("glDisable(GL_BLEND)");
510 }
511 if (m_current_state.depthtest)
512 {
513 glEnable(GL_DEPTH_TEST);
514 glDebug("glEnable(GL_DEPTH_TEST)");
515 }
516 else
517 {
518 glDisable(GL_DEPTH_TEST);
519 glDebug("glEnable(GL_DEPTH_TEST)");
520 }
521 if (m_current_state.alphatest)
522 {
523 glEnable(GL_ALPHA_TEST);
524 glAlphaFunc(GL_NOTEQUAL, m_current_state.alpharef);
525 glDebug("glAlphaFunc(GL_NOTEQUAL, state.alpharef)");
526 }
527 else
528 {
529 glDisable(GL_ALPHA_TEST);
530 glDebug("glDisable(GL_ALPHA_TEST)");
531 }
532 }
533 #endif
534
glDebug(const char * msg) const535 bool OGLStateManager::glDebug(const char* msg) const
536 {
537 #if defined(__ANDROID__) || defined(DEBUG_DIAGNOSTICS)
538 int e = glGetError();
539 if (e > 0)
540 {
541 # ifdef __ANDROID__
542 __android_log_print(ANDROID_LOG_INFO, "Crawl.gl", "ERROR %x: %s", e, msg);
543 # else
544 fprintf(stderr, "OGLStateManager ERROR %x: %s\n", e, msg);
545 # endif
546 return true;
547 }
548 #else
549 UNUSED(msg);
550 #endif
551 return false;
552 }
553
554 /////////////////////////////////////////////////////////////////////////////
555 // OGLShapeBuffer
556
OGLShapeBuffer(bool texture,bool colour,drawing_modes prim)557 OGLShapeBuffer::OGLShapeBuffer(bool texture, bool colour, drawing_modes prim) :
558 m_prim_type(prim),
559 m_texture_verts(texture),
560 m_colour_verts(colour)
561 {
562 ASSERT(prim == GLW_RECTANGLE || prim == GLW_LINES);
563 }
564
print_statistics() const565 const char *OGLShapeBuffer::print_statistics() const
566 {
567 return nullptr;
568 }
569
size() const570 unsigned int OGLShapeBuffer::size() const
571 {
572 return m_position_buffer.size();
573 }
574
add(const GLWPrim & rect)575 void OGLShapeBuffer::add(const GLWPrim &rect)
576 {
577 switch (m_prim_type)
578 {
579 case GLW_RECTANGLE:
580 add_rect(rect);
581 break;
582 case GLW_LINES:
583 add_line(rect);
584 break;
585 default:
586 die("Invalid primitive type");
587 break;
588 }
589 }
590
add_rect(const GLWPrim & rect)591 void OGLShapeBuffer::add_rect(const GLWPrim &rect)
592 {
593 // Copy vert positions
594 size_t last = m_position_buffer.size();
595 m_position_buffer.resize(last + 4);
596 m_position_buffer[last ].set(rect.pos_sx, rect.pos_sy, rect.pos_z);
597 m_position_buffer[last + 1].set(rect.pos_sx, rect.pos_ey, rect.pos_z);
598 m_position_buffer[last + 2].set(rect.pos_ex, rect.pos_sy, rect.pos_z);
599 m_position_buffer[last + 3].set(rect.pos_ex, rect.pos_ey, rect.pos_z);
600
601 // Copy texture coords if necessary
602 if (m_texture_verts)
603 {
604 last = m_texture_buffer.size();
605 m_texture_buffer.resize(last + 4);
606 m_texture_buffer[last ].set(rect.tex_sx, rect.tex_sy);
607 m_texture_buffer[last + 1].set(rect.tex_sx, rect.tex_ey);
608 m_texture_buffer[last + 2].set(rect.tex_ex, rect.tex_sy);
609 m_texture_buffer[last + 3].set(rect.tex_ex, rect.tex_ey);
610 }
611
612 // Copy vert colours if necessary
613 if (m_colour_verts)
614 {
615 last = m_colour_buffer.size();
616 m_colour_buffer.resize(last + 4);
617 m_colour_buffer[last ].set(rect.col_s);
618 m_colour_buffer[last + 1].set(rect.col_e);
619 m_colour_buffer[last + 2].set(rect.col_s);
620 m_colour_buffer[last + 3].set(rect.col_e);
621 }
622
623 // build indices
624 last = m_ind_buffer.size();
625
626 if (last > 3)
627 {
628 // This is not the first box so make FOUR degenerate triangles
629 m_ind_buffer.resize(last + 6);
630 unsigned short int val = m_ind_buffer[last - 1];
631
632 // the first three degens finish the previous box and move
633 // to the first position of the new one we just added and
634 // the fourth degen creates a triangle that is a line from p1 to p3
635 m_ind_buffer[last ] = val++;
636 m_ind_buffer[last + 1] = val;
637
638 // Now add as normal
639 m_ind_buffer[last + 2] = val++;
640 m_ind_buffer[last + 3] = val++;
641 m_ind_buffer[last + 4] = val++;
642 m_ind_buffer[last + 5] = val;
643 }
644 else
645 {
646 // This is the first box so don't bother making any degenerate triangles
647 m_ind_buffer.resize(last + 4);
648 m_ind_buffer[0] = 0;
649 m_ind_buffer[1] = 1;
650 m_ind_buffer[2] = 2;
651 m_ind_buffer[3] = 3;
652 }
653 }
654
add_line(const GLWPrim & rect)655 void OGLShapeBuffer::add_line(const GLWPrim &rect)
656 {
657 // Copy vert positions
658 size_t last = m_position_buffer.size();
659 m_position_buffer.resize(last + 2);
660 m_position_buffer[last ].set(rect.pos_sx, rect.pos_sy, rect.pos_z);
661 m_position_buffer[last + 1].set(rect.pos_ex, rect.pos_ey, rect.pos_z);
662
663 // Copy texture coords if necessary
664 if (m_texture_verts)
665 {
666 last = m_texture_buffer.size();
667 m_texture_buffer.resize(last + 2);
668 m_texture_buffer[last ].set(rect.tex_sx, rect.tex_sy);
669 m_texture_buffer[last + 1].set(rect.tex_ex, rect.tex_ey);
670 }
671
672 // Copy vert colours if necessary
673 if (m_colour_verts)
674 {
675 last = m_colour_buffer.size();
676 m_colour_buffer.resize(last + 2);
677 m_colour_buffer[last ].set(rect.col_s);
678 m_colour_buffer[last + 1].set(rect.col_e);
679 }
680 }
681
682 // Draw the buffer
draw(const GLState & state)683 void OGLShapeBuffer::draw(const GLState &state)
684 {
685 if (m_position_buffer.empty())
686 return;
687
688 if (!state.array_vertex)
689 return;
690
691 glmanager->set(state);
692
693 glVertexPointer(3, GL_FLOAT, 0, &m_position_buffer[0]);
694 glDebug("glVertexPointer");
695
696 if (state.array_texcoord && m_texture_verts)
697 glTexCoordPointer(2, GL_FLOAT, 0, &m_texture_buffer[0]);
698 glDebug("glTexCoordPointer");
699
700 if (state.array_colour && m_colour_verts)
701 glColorPointer(4, GL_UNSIGNED_BYTE, 0, &m_colour_buffer[0]);
702 glDebug("glColorPointer");
703
704 switch (m_prim_type)
705 {
706 case GLW_RECTANGLE:
707 glDrawElements(GL_TRIANGLE_STRIP, m_ind_buffer.size(),
708 GL_UNSIGNED_SHORT, &m_ind_buffer[0]);
709 break;
710 case GLW_LINES:
711 glDrawArrays(GL_LINES, 0, m_position_buffer.size());
712 break;
713 default:
714 die("Invalid primitive type");
715 break;
716 }
717 glDebug("glDrawElements");
718 }
719
clear()720 void OGLShapeBuffer::clear()
721 {
722 m_position_buffer.clear();
723 m_ind_buffer.clear();
724 m_texture_buffer.clear();
725 m_colour_buffer.clear();
726 }
727
glDebug(const char * msg) const728 bool OGLShapeBuffer::glDebug(const char* msg) const
729 {
730 #if defined(__ANDROID__) || defined(DEBUG_DIAGNOSTICS)
731 int e = glGetError();
732 if (e > 0)
733 {
734 # ifdef __ANDROID__
735 __android_log_print(ANDROID_LOG_INFO, "Crawl.gl", "ERROR %x: %s", e, msg);
736 # else
737 fprintf(stderr, "OGLShapeBuffer ERROR %x: %s\n", e, msg);
738 # endif
739 return true;
740 }
741 #else
742 UNUSED(msg);
743 #endif
744 return false;
745 }
746
747 #endif // USE_GL
748 #endif // USE_TILE_LOCAL
749